3

I've noticed this recurring problem when I'm trying to program joysticks or buttons that are active-low (0 = pressed), like on the Commodore 64 or Game Boy Advance. Regardless of the language or number of buttons, one of two things keep happening:

  1. The game crashes when certain directions are pressed (usually left or down)
  2. The player-controlled game object either moves on its own, or not at all.

EDIT: I was reading from the wrong joystick port. Derp. Now that I've fixed that, I'm having a different problem: The hardware sprite I'm moving goes in the wrong directions. Right is down and vice-versa.

Here is my code for my Commodore 64 joystick driver:

The two subroutines below are called in the following main game loop:
forever:
    JSR Player_ReadControlsDual
    txa
    pha
    tya
    pha
        ldy #0
        ldx #0
        jsr generateOAM   ;this draws hardware sprites, not relevant to my question
    pla
    tay
    pla
    tax
    jsr handle_input
    jmp forever


Player_ReadControlsDual:
        lda $DC00           ;Read in Joystick 1
        ora #%11100000      ;Set unused bits
        sta joypad1
        


        ; lda $DC01             ;Read in Joystick 2
        ; ora #%11100000        ;Set unused bits
        ; sta joypad2

        rts
        ;uncommenting this causes the CPU to crash 
        ;when pressing down or right, even though joypad2 is not being checked!

JOYSTICK_FIRE   equ BIT_4
JOYSTICK_RIGHT  equ BIT_3
JOYSTICK_LEFT   equ BIT_2
JOYSTICK_DOWN   equ BIT_1
JOYSTICK_UP     equ BIT_0

handle_input:

    lda joypad1
    cmp #$FF                    ; if all bits are 1, no buttons pressed.
    beq continueReadingInput    
    ;results in the object moving on its own.
    ;if this condition is flipped, the object is still. 
    ;Either way, the object ignores player input.

        jmp doneReadingInput    ;don't bother checking if no keys pressed
continueReadingInput:
    lda joypad1
    and #JOYSTICK_FIRE
    beq JoyNotFire

JoyNotFire:
    lda joypad1
    and #JOYSTICK_RIGHT
    beq JoyNotRight
    pha
    txa
    pha
    tya
    pha
        ldy #0
        lda object_xpos,y
        clc
        adc #$01
        sta object_xpos,y
        lda object_xpos+1,y
        adc #$00
        sta object_xpos+1,y
    pla
    tay
    pla
    tax
    pla
JoyNotRight:
    lda joypad1
    and #JOYSTICK_LEFT
    beq JoyNotLeft

JoyNotLeft:
    lda joypad1
    and #JOYSTICK_DOWN
    beq JoyNotDown
    pha
    txa
    pha
    tya
    pha
        ldy #0
        lda object_ypos,y
        clc
        adc #$01
        sta object_ypos,y
    pla
    tay
    pla
    tax
    pla
JoyNotDown:
    lda joypad1
    and #JOYSTICK_UP
    beq doneReadingInput

doneReadingInput:
    rts
1
  • 1
    Now you have edited your question into two questions. Please ask separate questions separately.
    – Chenmunka
    Sep 10 at 12:58
1

Assuming the FIRE button on joy1 is pressed, then your joypad1 should store the value %11101111. In order to check this, using your constants:

lda joypad1
and #JOYSTICK_FIRE
bne JoyNotFire
; handle FIRE pressed
...
JoyNotFire:
...

Your code appears to do the opposite. The and opcode above is doing the following bit-wise logical operation:

%11101111 & %00010000

That gives a value of zero, and sets the Z flag in the processor status. So, it's bne / Z not set that indicates the FIRE button is NOT pressed.

Not the answer you're looking for? Browse other questions tagged or ask your own question.