Add 6 button support
From Sonic Retro
(Original guide by Gardeguey on SSRG)
(Updated by Kramlat and JGMR)
Note from the editor: The original author of the guide (Gardeguey) targeted the older 2005 Hivebrain disassembly. Using the newer GitHub version is a bit more trivial. I will be adding instructions for that at a future date.
EDIT: For some reason, the 6 button controller doesn't work correctly in Kega, but in Regen, it works. No idea why...
STEP 1
Change all the text with...
$FFFFF602 to RAM_Control_1_Extra
$FFFFF603 to RAM_Control_1_ExtraPress
$FFFFF604 to RAM_Control_1_Hold
$FFFFF605 to RAM_Control_1_Press
STEP 2
Add these variables at the begining of the asm file:
;Buttons map (HardWareMan)
JoyUp equ 1
JoyDown equ 2
JoyUpDown equ 3
JoyLeft equ 4
JoyRight equ 8
JoyLeftRight equ $C
JoyCursor equ $F
JoyB equ $10
JoyC equ $20
JoyA equ $40
JoyABC equ $70
JoyStart equ $80
JoyABCS equ $F0
JoyZ equ $100
JoyY equ $200
JoyX equ $400
JoyXYZ equ $700
JoyMode equ $800
JoyMS equ $880
JoyXYZM equ $F00
JoyABCXYZ equ $770
JoyAnyButton equ $FF0
JoyAnyKey equ $FFF
;New ;Old
RAM_Control_1_Extra equ $FFFFFFA0 ;$FFFFF602
RAM_Control_1_ExtraPress equ $FFFFFFA2 ;$FFFFF603
RAM_Control_1_Hold equ $FFFFFFA4 ;$FFFFF604
RAM_Control_1_Press equ $FFFFFFA6 ;$FFFFF605
RAM_Control_2_Extra equ $FFFFFFA8 ;$FFFFF606
RAM_Control_2_ExtraPress equ $FFFFFFAA ;$FFFFF607
RAM_Control_2_Hold equ $FFFFFFAC ;$FFFFF608
RAM_Control_2_Press equ $FFFFFFAE ;$FFFFF609
STEP 3
Go To "ReadJoypads" and replace:
ReadJoypads:
lea ($FFFFF604).w,a0 ; address where joypad states are written
lea ($A10003).l,a1 ; first joypad port
bsr.s Joypad_Read ; do the first joypad
addq.w #2,a1 ; do the second joypad
Joypad_Read:
move.b #0,(a1)
nop
nop
move.b (a1),d0
lsl.b #2,d0
andi.b #$C0,d0
move.b #$40,(a1)
nop
nop
move.b (a1),d1
andi.b #$3F,d1
or.b d1,d0
not.b d0
move.b (a0),d1
eor.b d0,d1
move.b d0,(a0)+
and.b d0,d1
move.b d1,(a0)+
rts
With this:
ReadJoypads:
bsr.s Detect6buttonPad_Player1
cmp.b #$F0,d0
bne.w ReadJoypads_3Button
bra.s ReadJoypads_6Button
Detect6buttonPad_Player1: ; It works on the real thing and emus (Tiido)
move.b #0, ($A10003) ; Pull TH line low
move.b #$40, ($A10003) ; Pull TH line high
move.b#0, ($A10003) ; Pull TH line low
move.b #$40, ($A10003) ; Pull TH line high
move.b #0, ($A10003) ; Pull TH line low
move.b ($A10003),d0 ; Read controller port
and.b #$F, d0 ; Mask out unneeded data
move.b #$40, ($A10003) ; Pull TH line high
move.b #0, ($A10003) ; Pull TH line low
move.b ($A10003),d1 ; Read controller port
lsl.b #4, d1
or.b d1, d0
rts
ReadJoypads_6Button:
lea (RAM_Control_1_Hold).w,a0
lea ($A10003).l,a1
jsr Joypad_Read_6Button
lea (RAM_Control_2_Hold).w,a0
adda #2,a1
;By HardWareMan (SpritesMind), modified by GF64
Joypad_Read_6Button:
clr.l d0 ;Clear d0
clr.l d1 ;Clear d1
move.b #$40,(a1) ;SYN = 1
nop ;Delay
nop ;Delay
move.b (a1),d1 ;Reading first 6 buttons
andi.b #$3F,d1 ;Mask it
move.b #$00,(a1) ;SYN = 0
nop ;Delay
nop ;Delay
move.b (a1),d0 ;Read second 2 buttons
and.b #$30,d0 ;Mask it
rol.b #2,d0 ;Shift by 2 bits
or.b d0,d1 ;Combine basic 8 buttons and store it to d1
move.b #$40,(a1) ;SYN = 1
nop ;Delay
nop ;Delay
move.b #$00,(a1) ;SYN = 0
nop ;Delay
nop ;Delay
move.b #$40,(a1) ;SYN = 1
nop ;Delay
nop ;Delay
move.b #0,(a1) ;SYN = 0
nop ;Delay
nop ;Delay
move.b #$40,(a1) ;SYN = 1
nop ;Delay
nop ;All this for unlock extra buttons (XYZM)
move.b (a1),d0 ;Read extra buttons
andi.b #$F,d0 ;Mask it
eor.b #$F,d0 ;Invert it
rol.l #8,d0 ;Shift it by 8 bits
or.w d1,d0 ;Combine it with basic buttons
not.b d0 ;Invert basic buttons
move.w (a0),d1 ;[GF64]
eor.w d0,d1 ;[GF64]
move.b #$40,(a1) ;SYN = 1
move.w d0,(a0)+ ;Save joystick state
and.w d0,d1 ;[GF64]
move.w d1,(a0)+ ;[GF64]
rts
ReadJoypads_3Button:
lea (RAM_Control_1_Hold+$1).w,a0
lea ($A10003).l,a1
jsr Joypad_3Button_Read
lea (RAM_Control_2_Hold+$1).w,a0
lea ($A10005).l,a1
Joypad_3Button_Read:
move.b #0,(a1)
nop
nop
move.b (a1),d0
lsl.b #2,d0
andi.b #$C0,d0
move.b #$40,(a1)
nop
nop
move.b (a1),d1
andi.b #$3F,d1
or.b d1,d0
not.b d0
move.b (a0),d1
eor.b d0,d1
move.b d0,(a0)+
and.b d0,d1
move.b d1,1(a0)
rts
STEP 4
Now replace in every instruction related to the controller from .b to .w
Examples:
cmpi.b #$20,(RAM_Control_1_Press).w ; is button C pressed?
to
cmpi.w #$20,(RAM_Control_1_Press).w ; is button C pressed?
Code:
andi.b #$80,(RAM_Control_1_Press).w ; is Start button pressed?
to
andi.w #$80,(RAM_Control_1_Press).w ; is Start button pressed?
Code:
tst.b (RAM_Control_1_Press).w ; is any button pressed?
to
tst.w (RAM_Control_1_Press).w ; is any button pressed?
Code:
move.b (RAM_Control_1_Press).w,d0
andi.b #$20,d0 ; is C button pressed?
beq.s loc_3230 ; if not, branch
to
move.w (RAM_Control_1_Press).w,d0
andi.w #$20,d0 ; is C button pressed?
beq.s loc_3230 ; if not, branch
if a instruction already contains a .w , change to .l
move.w #0,(RAM_Control_1_Extra).w
to
move.l #0,(RAM_Control_1_Extra).w
Code:
move.w #$400,(RAM_Control_1_Extra).w ; move Sonic to the left
to
move.l #$400,(RAM_Control_1_Extra).w ; move Sonic to the left
Code:
move.w d0,(RAM_Control_1_Extra).w ; stop Sonic moving
to
move.l d0,(RAM_Control_1_Extra).w ; stop Sonic moving
if a instruction contains a "btst", use "+1"
btst #6,(RAM_Control_1_Hold).w ; check if A is pressed
beq.w PlayLevel ; if not, play level
to
btst #6,(RAM_Control_1_Hold+1).w ; check if A is pressed
beq.w PlayLevel ; if not, play level
In SS_MainLoop, SS_EndLoop and loc_12C58
Change:
move.w (RAM_Control_1_Hold).w,(RAM_Control_1_Extra).w
to:
move.l (RAM_Control_1_Hold).w,(RAM_Control_1_Extra).w
In loc_1D018 replace:
move.b (RAM_Control_1_Hold).w,d4
with
move.b (RAM_Control_1_Hold+1).w,d4
STEP 5
Since the demos are recorded with a 3button controller, go to loc_4056, and change:
lea (RAM_Control_1_Hold).w,a0
move.b d0,d1
move.w (a0),d2
eor.b d2,d0
move.b d1,(a0)+
and.b d1,d0
move.b d0,(a0)+
to
lea (RAM_Control_1_Hold).w,a0
move.b d0,d1
move.w (a0),d2
eor.b d2,d0
move.b d1,1(a0)
and.b d1,d0
move.b d0,3(a0)
and that's all.
CREDITS
Credits to:
Tiido - for the Dectect6ButtonPad from TMEGALIB
HardWareMan - for the original 6button subroutine