How to add 6 button support to Sonic 1

Discussion in 'Tutorials' started by Gardeguey, Aug 17, 2010.

Thread Status:
Not open for further replies.
  1. Gardeguey

    Gardeguey Well-Known Member Member

    Joined:
    Aug 6, 2010
    Messages:
    81
    Location:
    México
    EDIT: For some reason, the 6 button controller doesn't work correctly in Kega, but in Regen, it works. No idea why...


    NOTE: this tutorial is for the Sonic 1 2005 Disassembly


    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 $0001


    JoyDown equ $0002


    JoyUpDown equ $0003


    JoyLeft equ $0004


    JoyRight equ $0008


    JoyLeftRight equ $000C


    JoyCursor equ $000F


    JoyB equ $0010


    JoyC equ $0020


    JoyA equ $0040


    JoyABC equ $0070


    JoyStart equ $0080


    JoyABCS equ $00F0


    JoyZ equ $0100


    JoyY equ $0200


    JoyX equ $0400


    JoyMode equ $0800


    JoyMS equ $0880


    JoyXYZM equ $0F00


    JoyAnyButton equ $0FF0


    JoyAnyKey equ $0FFF


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




    Detect6buttonPad_Player1: ; It works on the real thing and emus (Tiido)


    MOVE.B #$00, ($A10003) ; Pull TH line low


    MOVE.B #$40, ($A10003) ; Pull TH line high


    MOVE.B #$00, ($A10003) ; Pull TH line low


    MOVE.B #$40, ($A10003) ; Pull TH line high


    MOVE.B #$00, ($A10003) ; Pull TH line low


    MOVE.B ($A10003),D0 ; Read controller port


    AND.B #$0F, D0 ; Mask out unneeded data


    MOVE.B #$40, ($A10003) ; Pull TH line high


    MOVE.B #$00, ($A10003) ; Pull TH line low


    MOVE.B ($A10003),D1 ; Read controller port


    LSL.B #4, D1


    OR.B D1, D0


    RTS


    ReadJoypads:


    jsr Detect6buttonPad_Player1


    cmp.b #$F0,d0


    bne ReadJoypads_3Button


    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 #$00,(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 #$0F,d0 ;Mask it


    eor.b #$0F,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_Read


    lea (RAM_Control_2_Hold+$1).w,a0


    lea ($A10005).l,a1


    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,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



    to



    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, here is the source code with all the steps done:


    Download


    Credits to:


    Tiido - for the Dectect6ButtonPad from TMEGALIB


    HardWareMan - for the original 6button subroutine
     
    Last edited by a moderator: Aug 20, 2010
  2. DeoxysKyogre

    DeoxysKyogre No idea what to put here .-. Member

    Joined:
    Jan 31, 2009
    Messages:
    298
    Seems being a real interesting guide. I like it! It will be useful if I try something that needs this! :)
     
  3. theocas

    theocas #! Member

    Joined:
    Apr 10, 2010
    Messages:
    375
    Thanks for the guide, I will certainly use it at some point. Also, if you're using it, you gotta advertise that your hack requires 6-button support.
     
  4. Ravenfreak

    Ravenfreak Incineroooaaarr! Member

    Joined:
    Feb 10, 2010
    Messages:
    355
    Location:
    O'Fallon, MO
    Oh my god, I've been wanting to add 6 button support to Sonic 1, but I didn't know the specific values for the X,Y, and Z buttons. Good job!
     
  5. Spanner

    Spanner Sonic Hacking Contest Lead Organiser Administrator

    Joined:
    Aug 9, 2007
    Messages:
    2,175
    I'm not a fan of the six-button setup but this might allow some variation with a few character moves. Good job for porting it over. ^_^
     
  6. Hanoch

    Hanoch Well-Known Member Member

    Joined:
    Aug 3, 2008
    Messages:
    312
    Location:
    Israel
    How does it work anyway? This is exactly like the how to add a new sega screen guide. Simply copying and pasting, and tons of equates. Will it be possible that someone would revise it, to have less equates and still use flags $F602-$F605?
     
  7. Gardeguey

    Gardeguey Well-Known Member Member

    Joined:
    Aug 6, 2010
    Messages:
    81
    Location:
    México
    Check the source code: Download


    and $F602-$F605 gets free to use

    the equs are actually useful:



    move.w (RAM_Control_1_ExtraPress).w,d0
    andi.w #JoyX+JoyY+JoyZ+JoyABC,d0 ; is X,Y,Z,A,B or C pressed? ($0770)


    beq.w locret_1348E ; if not, branch



    But seriously, i don't know why Kega can't recognize the 6-button controller correctly, but in other emulators (Regen,Gens,Genesis Plus [Wii]), works fine.
     
    Last edited by a moderator: Aug 21, 2010
  8. Ravenfreak

    Ravenfreak Incineroooaaarr! Member

    Joined:
    Feb 10, 2010
    Messages:
    355
    Location:
    O'Fallon, MO
    IIRC, you have to enable the 6-button controller by going to Options>Configuration>Controllers. The first option sets whether to use the 3-button one, 6 button one, Menacer (the gun) or Mouse.
     
  9. theocas

    theocas #! Member

    Joined:
    Apr 10, 2010
    Messages:
    375
    Strangely when I did that, none of the ABC or XYZ buttons worked.
     
  10. MarkeyJester

    MarkeyJester Julie knew her killer. Member

    Joined:
    Jun 27, 2009
    Messages:
    2,541
    Location:
    Miss Fox's heart~
    I could've sworn the routine for collecting 6 pad buttons was a lot more complexe.


    Sonic Crackers...



    ; ===========================================================================
    ; ---------------------------------------------------------------------------


    ; Subroutine to get the buttons being pressed from the control ports and


    ; dumping them to ram


    ; ---------------------------------------------------------------------------


    GetControls: ; Offset: 0000096E


    lea ($FFFFC938).w,a1


    lea ($A10003).l,a0


    lea ($FFFFC936).w,a2


    bsr.w sub_9D4


    lea ($A10005).l,a0


    lea ($FFFFC937).w,a2


    bsr.w sub_9D4


    bsr.s sub_992


    rts


    sub_992:


    moveq #7,d0


    cmpi.b #7,($FFFFC936).w


    bne.s loc_9A0


    subq.w #4,d0


    bra.s loc_9A2


    loc_9A0:


    subq.w #1,d0


    loc_9A2:


    cmpi.b #7,($FFFFC937).w


    bne.s loc_9B0


    subq.w #4,d0


    bcs.s locret_9D2


    bra.s loc_9B2


    loc_9B0:


    subq.w #1,d0


    loc_9B2:


    move.b #$F,(a1)


    clr.b 1(a1)


    clr.w 2(a1)


    clr.l 4(a1)


    clr.l 8(a1)


    clr.l $C(a1)


    lea $10(a1),a1


    dbf d0,loc_9B2


    locret_9D2:


    rts


    sub_9D4:


    bsr.w sub_A06


    move.b d0,(a2)


    andi.w #$E,d0


    add.w d0,d0


    jsr loc_9E6(pc,d0.w)


    rts


    ; ===========================================================================


    ; ---------------------------------------------------------------------------


    loc_9E6: nop


    rts


    ; ---------------------------------------------------------------------------


    bra.w loc_A5A


    ; ---------------------------------------------------------------------------


    nop


    rts


    ; ---------------------------------------------------------------------------


    bra.w loc_C70


    ; ---------------------------------------------------------------------------


    nop


    rts


    ; ---------------------------------------------------------------------------


    nop


    rts


    ; ---------------------------------------------------------------------------


    bra.w loc_B30


    ; ---------------------------------------------------------------------------


    bra.w loc_BBA


    ; ---------------------------------------------------------------------------


    ; ===========================================================================


    sub_A06:


    move.w #$100,($A11100).l ; stop the Z80


    move.b #$40,6(a0)


    move.b #$40,(a0)


    moveq #0,d0


    moveq #0,d1


    moveq #$F,d2


    nop


    move.b (a0),d1


    and.b d1,d2


    swap d1


    or.b byte_A4A(pc,d2.w),d0


    move.b #0,(a0)


    lsl.w #2,d0


    moveq #$F,d2


    nop


    move.b (a0),d1


    and.b d1,d2


    or.b byte_A4A(pc,d2.w),d0


    move.b #$40,(a0)


    move.w #0,($A11100).l


    rts


    ; ===========================================================================


    ; ---------------------------------------------------------------------------


    byte_A4A: dc.b $00,$01,$01,$01


    dc.b $02,$03,$03,$03


    dc.b $02,$03,$03,$03


    dc.b $02,$03,$03,$03


    ; ---------------------------------------------------------------------------


    ; ===========================================================================


    loc_A5A:


    move.b #2,0(a1)


    move.w #$FF,d7


    move.w #$100,($A11100).l


    move.b #$60,6(a0)


    move.b #$20,(a0)


    btst #4,(a0)


    beq.s loc_AAC


    bsr.w sub_C48


    bcs.w loc_AAC


    moveq #0,d6


    bsr.w sub_C2E


    bcs.w loc_AAC


    bsr.w sub_ACA


    move.b #$60,(a0)


    loc_A96:


    btst #4,(a0)


    dbne d7,loc_A96


    beq.w loc_C62


    move.w #0,($A11100).l


    rts


    loc_AAC:


    lea $10(a1),a1


    move.b #$60,(a0)


    loc_AB4:


    btst #4,(a0)


    dbne d7,loc_AB4


    beq.w loc_C62


    move.w #0,($A11100).l


    rts


    sub_ACA:


    bsr.w sub_C2E


    bcs.w loc_C5C


    andi.w #$F,d0


    move.b d0,1(a1)


    bsr.w sub_C2E


    bcs.w loc_C5C


    andi.w #$F,d0


    move.b d0,2(a1)


    bsr.w sub_C2E


    bcs.w loc_C5C


    andi.w #$F,d0


    move.b d0,3(a1)


    bsr.w sub_C2E


    bcs.w loc_C5C


    andi.w #$F,d0


    move.b d0,4(a1)


    bsr.w sub_C2E


    bcs.w loc_C5C


    andi.w #$F,d0


    move.b d0,5(a1)


    bsr.w sub_C2E


    bcs.w loc_C5C


    andi.w #$F,d0


    move.b d0,6(a1)


    lea $10(a1),a1


    rts


    ; ===========================================================================


    loc_B30:


    move.w #$100,($A11100).l ; stop the Z80


    move.b #$40,6(a0)


    moveq #2,d3


    loc_B40:


    move.l d1,d0


    andi.b #$F,d0


    beq.s loc_B6E


    move.b #$40,(a0)


    moveq #0,d1


    nop


    nop


    nop


    move.b (a0),d1


    move.b #0,(a0)


    swap d1


    nop


    nop


    nop


    move.b 0(a0),d1


    dbf d3,loc_B40


    bra.w loc_BDA


    loc_B6E:


    move.b #$40,(a0)


    moveq #0,d2


    move.b 0(a0),d2


    move.b #0,(a0)


    swap d2


    move.b 0(a0),d2


    move.w #0,($A11100).l


    move.b #1,0(a1)


    move.w d1,d0


    swap d1


    asl.b #2,d0


    andi.w #$C0,d0


    andi.w #$3F,d1


    or.b d1,d0


    not.b d0


    bsr.w sub_C0A


    swap d2


    move.w d2,d0


    not.b d0


    andi.w #$F,d0


    bsr.w sub_C1C


    lea $10(a1),a1


    rts


    loc_BBA:


    move.b #$F,0(a1)


    clr.b 1(a1)


    clr.w 2(a1)


    clr.l 4(a1)


    clr.l 8(a1)


    clr.l $C(a1)


    lea $10(a1),a1


    rts


    loc_BDA:


    clr.b 0(a1)


    move.b #$40,6(a0)


    move.w d1,d0


    swap d1


    move.b #$40,(a0)


    move.w #0,($A11100).l


    asl.b #2,d0


    andi.w #$C0,d0


    andi.w #$3F,d1


    or.b d1,d0


    not.b d0


    bsr.s sub_C0A


    lea $10(a1),a1


    rts


    sub_C0A:


    move.b 4(a1),d1


    eor.b d0,d1


    move.b d0,4(a1)


    and.b d0,d1


    move.b d1,5(a1)


    rts


    sub_C1C:


    move.b 3(a1),d1


    eor.b d0,d1


    move.b d0,3(a1)


    and.b d0,d1


    move.b d1,6(a1)


    rts


    sub_C2E:


    bchg #0,d6


    bne.s sub_C48


    loc_C34:


    move.b #$20,(a0)


    loc_C38:


    move.b (a0),d0


    btst #4,d0


    dbne d7,loc_C38


    beq.s loc_C5C


    move.b (a0),d0


    rts


    sub_C48:


    move.b #0,(a0)


    loc_C4C:


    move.b (a0),d0


    btst #4,d0


    dbeq d7,loc_C4C


    bne.s loc_C5C


    move.b (a0),d0


    rts


    loc_C5C:


    ori #1,ccr


    rts


    loc_C62:


    move.w #0,($A11100).l


    ori #1,ccr


    rts


    ; ===========================================================================


    loc_C70:


    move.w #$100,($A11100).l


    move.b #$20,(a0)


    move.b #$60,6(a0)


    move.w #$FF,d7


    btst #4,(a0)


    beq.w loc_D10


    bsr.s sub_C48


    bcs.w loc_D10


    andi.b #$F,d0


    bsr.s loc_C34


    bcs.w loc_D10


    andi.b #$F,d0


    bsr.s sub_C48


    bcs.w loc_D10


    andi.b #$F,d0


    move.b d0,0(a1)


    bsr.s loc_C34


    bcs.w loc_D10


    andi.b #$F,d0


    move.b d0,$10(a1)


    bsr.s sub_C48


    bcs.w loc_D10


    andi.b #$F,d0


    move.b d0,$20(a1)


    moveq #0,d6


    bsr.w sub_C2E


    bcs.w loc_D10


    andi.b #$F,d0


    move.b d0,$30(a1)


    bsr.s sub_D3A


    bcs.w loc_D10


    bsr.s sub_D3A


    bcs.w loc_D14


    bsr.s sub_D3A


    bcs.w loc_D18


    bsr.s sub_D3A


    bcs.w loc_D1C


    move.b #$60,(a0)


    loc_CFA:


    btst #4,(a0)


    dbne d7,loc_CFA


    beq.w loc_C62


    move.w #0,($A11100).l


    rts


    loc_D10:


    lea $10(a1),a1


    loc_D14:


    lea $10(a1),a1


    loc_D18:


    lea $10(a1),a1


    loc_D1C:


    lea $10(a1),a1


    move.b #$60,(a0)


    loc_D24:


    btst #4,(a0)


    dbne d7,loc_D24


    beq.w loc_C62


    move.w #0,($A11100).l


    rts


    sub_D3A:


    moveq #0,d0


    move.b (a1),d0


    cmpi.b #2,d0


    bhi.s loc_D58


    add.w d0,d0


    add.w d0,d0


    jmp loc_D4C(pc,d0.w)


    ; ===========================================================================


    ; ---------------------------------------------------------------------------


    loc_D4C: bra.w loc_D98


    bra.w loc_D72


    bra.w sub_ACA


    ; ---------------------------------------------------------------------------


    ; ===========================================================================


    loc_D58:


    clr.b 1(a1)


    clr.w 2(a1)


    clr.l 4(a1)


    clr.l 8(a1)


    clr.l $C(a1)


    lea $10(a1),a1


    rts


    ; ===========================================================================


    loc_D72:


    bsr.w sub_DAA


    bsr.w sub_C2E


    bcs.w loc_C5C


    not.b d0


    andi.w #$F,d0


    move.b d0,d2


    move.b d1,d0


    bsr.w sub_C0A


    move.b d2,d0


    bsr.w sub_C1C


    lea $10(a1),a1


    rts


    loc_D98:


    bsr.s sub_DAA


    bcs.w loc_C5C


    move.b d1,d0


    bsr.w sub_C0A


    lea $10(a1),a1


    rts


    sub_DAA:


    bsr.w sub_C2E


    bcs.w loc_C5C


    andi.w #$F,d0


    move.w d0,d1


    bsr.w sub_C2E


    bcs.w loc_C5C


    asl.w #4,d0


    or.b d0,d1


    not.b d1


    rts



    Should this be useful for anyone's research.
     
  11. Ravenfreak

    Ravenfreak Incineroooaaarr! Member

    Joined:
    Feb 10, 2010
    Messages:
    355
    Location:
    O'Fallon, MO
    You have to redefine the keys for the controller after enabling the 6-button controller. (That is, if you are using the keyboard rather than a controller. xP)
     
  12. theocas

    theocas #! Member

    Joined:
    Apr 10, 2010
    Messages:
    375
    I did that. I think Mac OS X Fusion has some weird issue. After all, it's programmed in ASM to use the Carbon Framework (aka outdated)
     
  13. Gardeguey

    Gardeguey Well-Known Member Member

    Joined:
    Aug 6, 2010
    Messages:
    81
    Location:
    México
    6 button test ROM


    Run this ROM in kega, you will notice that the X,Y,Z,MODE doesn't work, it detects UDLR instead


    But in Regen, it works correctly.
     
  14. Ravenfreak

    Ravenfreak Incineroooaaarr! Member

    Joined:
    Feb 10, 2010
    Messages:
    355
    Location:
    O'Fallon, MO
    You know what, you're right. o_O That's strange, maybe something in the code is messed up? I've played Cosmic Carnage with the 6-button controller enabled with Fusion, and it worked correctly... (though that's a 32x game, but would that matter? :\)
     
    Last edited by a moderator: Aug 26, 2010
Thread Status:
Not open for further replies.