2

My last question wasn't specific enough so I'll rephrase it. I've been having trouble with programming game consoles/computers like Commodore 64 that have active-low joysticks, where the bits are all packed into one or more bytes that is read from the joystick port. (I'm used to the NES where you have to strobe the keys and read it active-high). I'd like to convert the routine below to active-high, by flipping the bits of joypad1, removing the CMP #$FF, and changing each BNE to BEQ. I thought that would have been enough, but this ends up making none of the controls work. (Each direction is set up to move a hardware sprite around the screen.) How do I correctly alter the code below to read the input active-high?

JOYSTICK_FIRE   equ #%00010000
JOYSTICK_RIGHT  equ #%00001000
JOYSTICK_LEFT   equ #%00000100
JOYSTICK_DOWN   equ #%00000010
JOYSTICK_UP     equ #%00000001

handle_input:
    lda joypad1
    cmp #$FF                    ; if all bits are 1, no buttons pressed.
    bne continueReadingInput    
        jmp doneReadingInput    ;don't bother checking if no keys pressed
continueReadingInput:
    lda joypad1
    and #JOYSTICK_FIRE
    bne JoyNotFire
    ;YOUR CODE FOR WHAT HAPPENS WHEN YOU PRESS FIRE GOES HERE.

JoyNotFire:
    lda joypad1
    and #JOYSTICK_RIGHT
    bne JoyNotRight

    ;YOUR CODE FOR WHAT HAPPENS WHEN YOU PRESS LEFT GOES HERE.
JoyNotRight:
    lda joypad1
    and #JOYSTICK_LEFT
    bne JoyNotLeft

    ;YOUR CODE FOR WHAT HAPPENS WHEN YOU PRESS LEFT GOES HERE.

JoyNotLeft:
    lda joypad1
    and #JOYSTICK_DOWN
    bne JoyNotDown

    ;YOUR CODE FOR WHAT HAPPENS WHEN YOU PRESS DOWN GOES HERE.

JoyNotDown:
    lda joypad1_held
    and #JOYSTICK_UP
    bne doneReadingInput
    ;YOUR CODE FOR WHAT HAPPENS WHEN YOU PRESS UP GOES HERE.
    
doneReadingInput:
    rts
8
  • 8
    Could you not just throw in an appropriate EOR #$ff?
    – Tommy
    Sep 15, 2021 at 3:21
  • I tried that but it either led to a CPU jam or no input response. I seem to have the same problem regardless of which hardware I'm programming for, even the Game Boy Advance has the same issues. I'll try it again tonight, doing EOR #$FF after each LDA joypad1 and see what happens. I'd rather just do it once when the joypad1 variable is created but it causes problems. Sep 15, 2021 at 15:17
  • The EOR #$FF method after each instance of LDA JOYPAD1 works, unless I try comparing anything other than JOYPAD1 (such as JOYPAD1_HELD, JOYPAD1_PRESSED etc.) Flipping the bits read from the joystick and saving them to the variable crashes the game but only when pressing Down or Left. Very strange Sep 16, 2021 at 0:20
  • 1
    I find the debugger a little bit difficult to use. I'll give it a shot. I tried starting over and I'm not having the same issues so it must have been an error somewhere else. Sep 16, 2021 at 21:37
  • 1
    @user3840170 I mean to do the following: LDA $DC01 EOR #$FF STA JOYPAD1 where JOYPAD1 is a zero page address. Then do all my controller reading this frame from JOYPAD1 rather than $DC01. Dec 19, 2021 at 17:31

2 Answers 2

3

So as it turns out, the reason this didn't work had nothing to do with the joystick. It was because I was using zero page addresses $00 and $01 to store the joystick output, which was clobbering the memory management unit. Silly me!

2
  • That would certainly ensure some entertaining debugging sessions. 8-)
    – Nimloth
    Jul 22, 2022 at 15:41
  • Yes, storing data into memory locations that are not RAM but important IO is a bad thing. It's worth to check which addresses are available before typing code.
    – Justme
    Jul 22, 2022 at 19:25
1

Maybe this way. I quickly created it and it is untested. I hope it helps.

Edit: I probably misunderstood and adapted the routine to handle active high inputs. I don't fully understand why you want a routine to look like handling active high, when it is handling active low.

However now I edited it (using xor like Tommy suggested) to process active-low inputs with code that normally would be used for active high.

; check joystick
; and handle movement
; active high code

JOYSTICK_FIRE   equ #%00010000
JOYSTICK_RIGHT  equ #%00001000
JOYSTICK_LEFT   equ #%00000100
JOYSTICK_DOWN   equ #%00000010
JOYSTICK_UP     equ #%00000001

JoyCheckInput:
    lda joystick
    EOR #$FF
    and #%00011111              ; isolate the relevant bits
    beq JoyCheckDone:           ; if all bits are 0, no buttons pressed.
        
JoyCheckFire:
    lda joystick
    EOR #$FF
    and #JOYSTICK_FIRE          ;isolate that bit
    beq JoyCheckRight
    ;handle user presses fire

JoyCheckRight:
    lda joystick
    EOR #$FF
    and #JOYSTICK_RIGHT
    beq JoyCheckLeft
    ;handle user steers right
    
JoyCheckLeft:
    lda joystick
    EOR #$FF
    and #JOYSTICK_LEFT
    beq JoyCheckDown
    ;handle user steers left

JoyCheckDown:
    lda joystick
    EOR #$FF
    and #JOYSTICK_DOWN
    beq JoyCheckUp
    ;handle user steers down
 
JoyCheckUp:
    lda joystick
    EOR #$FF
    and #JOYSTICK_UP
    beq JoyCheckDone
    ;handle user steers up
    
JoyCheckDone:
    rts 

Still, it would be better to write it directly for active-low:

JoyCheckFire:
    lda joystick
    and #JOYSTICK_FIRE          ;isolate that bit
    bne JoyCheckRight
    ;handle user presses fire
and so on...
2
  • 1
    I think the point is to read from the real joystick register, which is still active-low, and transform the value read so that it could be used as if it were active-high; not to pretend it was active-high to begin with (which it cannot be). But to be honest, I am not quite sure. Dec 15, 2021 at 15:04
  • 1
    Yes, probably you are right. I really didn't completely get what he wants the routine to do exactly. I now edited the routine to handle active-low input still using beq-skip-branches (if that makes sense). A little frustrating to spend one or two hours to try to help and work something out which lowers your score =/
    – Steve I
    Dec 15, 2021 at 22:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .