Actions

SCHG How-to

Add 6 button support

From Sonic Retro

EDIT: For some reason, the 6 button controller doesn't work correctly in Kega, but in Regen, it works. No idea why...

NOTE: The original author (Gardeguey) targeted the 2005 Hivebrain Disassembly. Using the newer git version is a bit more trivial. I will be adding instructions on that at a future date.

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 to:

Tiido - for the Dectect6ButtonPad from TMEGALIB

HardWareMan - for the original 6button subroutine

Gardeguey - for the (archived tutorial) on SSRG