[stella] Simple Joystick Input Reading Routine

Subject: [stella] Simple Joystick Input Reading Routine
From: Ruffin Bailey <rufbo@xxxxxxxxxxx>
Date: Sat, 27 Jun 1998 11:23:28 -0500
Well, it's about time I wrote some more code.  I thought I'd start with
a real entry level joystick input reading routine.  Hopefully this is
fairly well commented and easy to understand.  The sprite is real basic
(just 10100101 for 16 scan lines) and there are no checks for
out-of-bounds movements.  I would recommend opening the source
(joymove.a) in BBEdit or the like so that the long comments don't wrap
around, or chaging your font to something relatively small.

One word for DAsm users:  You will need to change all byte and word
commands from "byte" and "word" to ".byte" and ".word".  Sorry about
that.  There are only two "words" at the end of this file.

Here's the main portion of code for reading SWCHA.  It seems to have
lost some of its formatting in the paste.  Let me know what you think!

 ; **********This is the routine to read the Player Zero
joystick**********
 ; One important thing to note is that this simple routine does NOT
check for
 ; out of bounds movements.  If you move the sprite too far down off of
the
 ; screen, I don't know what would happen!


 ; SWCHA dissection:

 ;  Player Zero      Player One
 ;---------------  --------------
 ;  D7 D6 D5 D4      D3 D2 D1 D0
 ;  R  L  U  Dwn     R  L  U  Dwn

 lda #$00
 sta HMP0   ; This is perhaps not the most elegant way to achieve
      ; this, but I want to make sure the sprite does not move
      ; in the horizontal or x-direction if the joystick doesn't
      ; point that way, so I'm init'n HMP0 now.  As the porgram
      ; stands now, "a" already equals zero, but it won't
      ; hurt to be prepared for a code change above.

 lda SWCHA    ; load the byte that holds the joystick input
 bmi next   ; if D7 is a 1, P0 stick doesn't point right
 ldy #%11110000  ; this will be a -1 movement (to the right)
 sty HMP0   ; store in Horizontal Movement Player Zero

next
 rol     ; shuffle the bits to the left.
 bmi next2   ; if D6 isn't zero, head to the next check
 ldy #%00010000  ; switching D7 from 1 to a 0 makes this a +1 movement
 sty HMP0   ; (to the left) put this in HMP0  Note that it is physically

      ; impossible to latch both D6 and D7 with a joystick, but
      ; if some hacker did, the end result would be a move to
      ; the left with this set-up.  Try it in an emulator!
next2
 rol
 bmi next3
 inc ypos   ; if D5 is latched (ie, equals zero), move the sprite up
 inc ypos   ; two scan lines.  Change the y position two scans

      ; Why two scans?  B/c one is painfully slow!

next3
 rol
 bmi endofchk  ; if D4 isn't latched, that's the last bit in SWCHA that
      ; deals with player zero.  Go ahead and skip out of this
      ; joystick check routine if that's the case.
 dec ypos   ; Otherwise the joystick is pressing down, and the ypos
 dec ypos   ; of the sprite should be changed accordingly.

endofchk
 nop     ; There's no reason for this No Operation cmd other than
      ; I was an English major and hate to see any heading without
      ; an entry!  ;)



Attachment: joymove.bin
Description: .MPW Shell Document

  include "6502"
  include "vcs.h"

ypos    		equ $80
p0graph 		equ	$81


; rasm -p -l JBPF2.asm >demo.lst
;    PF0  |     PF1       |      PF2
;  4 5 6 7|7 6 5 4 3 2 1 0|0 1 2 3 4 5 6 7
;

	org $F000
       


Start

	SEI  ; Disable interrupts, if there are any.
	CLD  ; Clear BCD math bit.

	LDX  #$FF
	TXS  ; Set stack to beginning.

	LDA #0
B1      STA 0,X
	DEX
	BNE B1
	
	lda #$50
	sta ypos  			; init ypos
	
	JSR  GameInit ; this just starts the game as if the reset switch was hit. -R

MainLoop
	JSR  VerticalBlank ;Execute the vertical blank.
	JSR  GameCalc      ;Do calculations during Vblank
	JSR  DrawScreen    ;Draw the screen
	JSR  OverScan      ;Do more calculations during overscan
	JMP  MainLoop      ;Continue forever.

VerticalBlank  ;*********************** VERTICAL BLANK HANDLER
	LDX  #0
	LDA  #2
	STA  WSYNC  
	STA  WSYNC
	STA  WSYNC
	STA  VSYNC ;Begin vertical sync.
	STA  WSYNC ; First line of VSYNC
	STA  WSYNC ; Second line of VSYNC.

	LDA  #44
	STA  TIM64T

	LDA #0
	STA CXCLR	; collison register

	STA  WSYNC ; Third line of VSYNC.
	STA  VSYNC ; (0)
	RTS  



GameCalc ;******************************* GAME CALCULATION ROUTINES
	lda #%10001000		; hopefully this is mid-lum blue
	sta COLUP0			; this is the temp color for the bean
	lda #%00110110		; 
	sta COLUPF			; this is the pf (platform) color
	lda #%11011000		; mid green
	sta COLUP1			; temp color for goals
	lda #%00000000	    ; bkgd test color
	sta COLUBK			; store it in the background
	
	lda #%00000000		; un-mirrored playfield
	sta CTRLPF
	
	lda #%10100101		; temp sprite graphic
	sta p0graph
	
	; **********This is the routine to read the Player Zero joystick**********	
	; One important thing to note is that this simple routine does NOT check for
	; out of bounds movements.  If you move the sprite too far down off of the
	; screen, I don't know what would happen! 
	
	
	; SWCHA dissection:
	
	;  Player Zero      Player One
	;---------------  --------------
	;  D7 D6 D5 D4      D3 D2 D1 D0
	;  R  L  U  Dwn     R  L  U  Dwn
	
	lda #$00
	sta HMP0			; This is perhaps not the most elegant way to achieve
						; this, but I want to make sure the sprite does not move
						; in the horizontal or x-direction if the joystick doesn't
						; point that way, so I'm init'n HMP0 now.  As the porgram
						; stands now, "a" already equals zero, but it won't
						; hurt to be prepared for a code change above.
	
	lda SWCHA 			; load the byte that holds the joystick input
	bmi next			; if D7 is a 1, P0 stick doesn't point right
	ldy #%11110000		; this will be a -1 movement (to the right)
	sty HMP0			; store in Horizontal Movement Player Zero

next
	rol					; shuffle the bits to the left.  
	bmi next2			; if D6 isn't zero, head to the next check
	ldy #%00010000		; switching D7 from 1 to a 0 makes this a +1 movement 
	sty HMP0			; (to the left) put this in HMP0  Note that it is physically 
						; impossible to latch both D6 and D7 with a joystick, but 
						; if some hacker did, the end result would be a move to 
						; the left with this set-up.  Try it in an emulator!
next2
	rol
	bmi next3
	inc ypos			; if D5 is latched (ie, equals zero), move the sprite up
	inc ypos			; two scan lines.  Change the y position two scans
	
						; Why two scans?  B/c one is painfully slow!
	
next3
	rol
	bmi endofchk		; if D4 isn't latched, that's the last bit in SWCHA that
						; deals with player zero.  Go ahead and skip out of this
						; joystick check routine if that's the case.
	dec ypos			; Otherwise the joystick is pressing down, and the ypos
	dec ypos			; of the sprite should be changed accordingly.
						
endofchk
	nop					; There's no reason for this No Operation cmd other than
						; I was an English major and hate to see any heading without
						; an entry!  ;)
						
	
	
DrawScreen ;**************************** SCREEN DRAWING ROUTINES
	LDA INTIM
	BNE DrawScreen ; Whew!
	STA WSYNC
	STA VBLANK  ;End the VBLANK period with a zero. +2

	ldx #$1   ; +2 
	ldy $AA
	
Stall	
	sta WSYNC
	lda $B2
	sta PF2
	lda $B1
	sta PF1

EOSchk 				; End of Screen check	
	inx
	cpx #$C1
	beq Scan3
	
	
	cpx ypos		; is this where the sprite should be drawn?
	beq drawchar	; if this is the sprite's scanline, go draw it
	sta WSYNC		; if not, wait for sync,
	jmp EOSchk		; check for EOS and either start the next line or go to Scan3
	
	
drawchar
	ldy #$01
	sta RESMP0
	sta WSYNC
EOSchk2	
	inx
	cpx #$C1
	beq Scan3
	
	iny
	lda p0graph		; holds the player0 graphic
	sta GRP0		; putting the with the graphic into GRP0 "enables" the
					; sprite and makes it visible.
	sta WSYNC
	cpy #$10		; let the sprite run over $10 or 16 scan lines.
	bne EOSchk2
	lda #$00
	sta GRP0		; turn Player Zero's sprite off so it doesn't run to the bottom
					; of the screen!
	jmp EOSchk
	
	
	
	
	
Scan3			; this is where your code should kick out when the screen is 
				; finished
	
	LDA #$02
	STA WSYNC  ;Finish this scanline.
	STA VBLANK ; Make TIA output invisible,
	; Now we need to worry about it bleeding when we turn
	; the TIA output back on.
	; X will be now zero.
	LDX #$00
	STX PF0
	STX PF1
	STX PF1
	STX GRP0
	STX GRP1
	STX ENAM0
	STX ENAM1
	STX ENABL
	sta HMOVE			; don't know what I'm doing
	RTS


;
OverScan   ;***************************** OVERSCAN CALCULATIONS
	LDX #30
KillLines
	 STA WSYNC
	 DEX
	 BNE KillLines
	RTS

;
; GameInit could conceivably be called when the Select key is pressed,
; or some other event.
;
GameInit
	
	RTS

	
	org $FFFC
	word Start
	word Start

	


Current Thread