Jump to content
IGNORED

Reading the paddle controlers


Recommended Posts

SpiceWare wrote these great macros:

 

		MAC READ_PADDLE_1
	lda INPT0	; 3   - always 9
	bpl .save	; 2 3
	.byte $2c	; 4 0
.save   sty Paddle1	 ; 0 3
	ENDM

	MAC READ_PADDLE_2
	lda INPT1	; 3   - always 9
	bpl .save	; 2 3
	.byte $2c	; 4 0
.save   sty Paddle2	 ; 0 3
	ENDM

 

call them in your kernel and use Paddle1 and Paddle2 for the sprite's position. You also have to assign Paddle1 and 2 a location in RAM.

 

EDIT:

 

you also have to charge/discharge the paddle cap. At the beginning of the frame, store $82 to VBLANK. Then just before your kernel, store $00 to VBLANK. After the Kernel, store $82 again

Edited by Wickeycolumbus
Link to comment
Share on other sites

SpiceWare wrote these great macros

 

It should be mentioned that the Y register is assumed to hold the scanline counter in those macros (hence, sty Paddle1&2). The "always 9" mentioned is the cycle time taken by each macro...9 cycles regardless of if the branch is taken. Basically...the more times that these macros execute in a display frame, the higher resolution of the value.

  • Like 1
Link to comment
Share on other sites

SpiceWare wrote these great macros:

 

		MAC READ_PADDLE_1
	lda INPT0; 3   - always 9
	bpl .save; 2 3
	.byte $2c; 4 0
.save   sty Paddle1	; 0 3
	ENDM

	MAC READ_PADDLE_2
	lda INPT1; 3   - always 9
	bpl .save; 2 3
	.byte $2c; 4 0
.save   sty Paddle2	; 0 3
	ENDM

 

call them in your kernel and use Paddle1 and Paddle2 for the sprite's position. You also have to assign Paddle1 and 2 a location in RAM.

 

EDIT:

 

you also have to charge/discharge the paddle cap. At the beginning of the frame, store $82 to VBLANK. Then just before your kernel, store $00 to VBLANK. After the Kernel, store $82 again

I did what you said with the $82 VBLANK, $00 VBLANK, $82 VBLANK stuff and it still doesn't work. I added the paddle reading code from the Stella Advance Programmers Guide and when i use the -lc Paddles option in Stella, the screen rolls but when i omit the -lc option it just stretches the missiles and ball. Any ideas?

 

Sincerely,

 

6502Pong

6502Pong.zip

Link to comment
Share on other sites

Ok, that didn't solve my problem as my kernal is very different then yours.

	processor 6502

; Then we have to include the "vcs.h" file
; that includes all the "convenience names"
; for all the special atari memory locations...

include "vcs.h"

include "macro.h"

;**************************************************************************

SEG.U vars		; tells dasm that the proceding instructions are variable declarations
	  
ORG $80			; tells dasm to start placing our variables in memory location 0080

missile0x = $80			; player0's x position

missile0y = $81			; player0's y position

visiblemissile0line = $82	; current visible line for player 0

missile1x = $83			; player0's x position

missile1y = $84			; player0's y position

visiblemissile1line = $85	; current visible line for player 0

ballx = $86			; ball's x position

bally = $87			; ball's y position

ballvx = $88			; ball's x velocity

ballvy = $89			; ball's y velocity

visibleballline = $8a		; line where ball is drawn

leftplayerscore = $8b		; left player's score

rightplayerscore = $8c		; right player's score

	SEG code

; tell DASM where in the memory to place
; all the code that follows...$F000 is the preferred
; spot where it goes to make an atari program

	ORG $F800

; we'll call the start of our program "Start".
Start

sei			; Disable Any Interrupts

cld			; Clear BCD math bit.

ldx #$FF		; put X to the top...

txs			; ...and use it reset the stack pointer

			; Clear RAM and all TIA registers

lda #0			; Put Zero into A, X is at $FF

Clear	sta 0,x			; Now, this doesn't mean what you think...

dex			; decrement X (decrease X by one)

bne Clear		; if the last command resulted in something
			; that's "N"ot "Equal" to Zero, branch back
			; to "Clear"

;---------------------
; One Time Initiations

lda #$00

sta COLUBK		; set the background color to black

lda #$0F

sta COLUPF		; set the playfield color to white

sta COLUP0		; set player 0's color to white

sta COLUP1		; set player 1's color to white

lda #%00100001		; turn on playfield reflections and make the ball 4 ticks wide

sta CTRLPF

lda #%00010000

sta NUSIZ0		; set player 0 width to 4 ticks wide

sta NUSIZ1		; set player 1 width to 4 ticks wide

;---------------------
; Start New Game

StartNewGame

lda #2

sta missile0x		; player0's initial x position

lda #150

sta missile1x		; player1's initial x position

lda #95

sta missile0y		; player0's initial y position

sta missile1y		; player1's initial y position

sta bally		; ball's initial y position

lda #75

sta ballx		; ball's initial x position

lda #0

sta leftplayerscore	; set the left player's score to 0

sta rightplayerscore	; set the right player's score to 0

GameLoop

;*********************** VERTICAL SYNC HANDLER

lda #$82

sta VBLANK		; perform a vertical blank and discharge the caps
			; on the paddle controllers

lda  #2

sta VSYNC		; Sync it up you damn dirty television!
			; and that vsync on needs to be held for three scanlines...
			; count with me here,

sta WSYNC		; one... (our program waited for the first scanline to finish...)

sta WSYNC		; two...

sta WSYNC		; three...

lda  #43		;load 43 (decimal) in the accumulator

	sta  TIM64T		;and store that in the timer

	lda #0			; Zero out the VSYNC

	sta  VSYNC		; cause that time is over

;*************************** Paddle Input
; Here we check for left and right paddle
; paddle controller input and check if
; the reset game switch is depressed

lda #%00000001		; a 0 in bit D0 means the reset switch was pressed

bit SWCHB		; was the reset switch pressed?

bne SkipResetSwitchPressed; if bit D0 isn't equal to 0 then jump to SkipResetSwitchPressed

jmp StartNewGame	; if it was then start a new game

SkipResetSwitchPressed

lda missile0x		; load the millile 0's position into the accumulator

ldx #2			; set the sprite to be positioned as missile 0

jsr PositionSprite	; jump to our Position Sprite Subroutine to position player 0

sta WSYNC		; wait for sync

lda ballx		; load the ball's x position into the acumulator

ldx #4			; set the sprite to be positioned to ball

jsr PositionSprite	; jump to our Position Sprite Subroutine to position ball

sta WSYNC		;wait for sync

lda missile1x		; load player 1's x position into the accumulator

ldx #3			; set the sprite to be positioned as missile 1

jsr PositionSprite	; jump to our Position Sprite Subroutine to position player 1

ButtonNotPressed

;*********************** VERTICAL BLANK WAIT-ER
WaitForVblankEnd

lda INTIM		; load timer...

bne WaitForVblankEnd	; killing time if the timer's not yet zero

ldy #191		; Y is going to hold how many lines we have to do
			; ...we're going to count scanlines here. theoretically
			; since this example is ass simple, we could just repeat
			; the timer trick, but often its important to know
			; just what scan line we're at.

sta WSYNC		; We do a WSYNC just before that so we don't turn on

sta VBLANK		; End the VBLANK period with the zero and start charging
			; the paddle controllers capasitors

;*********************** Scan line Loop

ScanLoop

lda INPT0		; read the charge from the first paddle controller

bmi paddle0		; if paddle 0 is charged

.byte $2c		; paddle 0 wasn't charged so waste 2 cycles

paddle0

sty missile0y		; then set player 0's y position
			; based on it's readout

lda INPT1		; read the charge from the first paddle controller

bmi paddle1		; if paddle 1 is charged

.byte $2c		; paddle 1 wasn't charged so waste 2 cycles

paddle1

sty missile1y		; then set player 1's y position
			; based on it's readout

lda #2

sta WSYNC		; Wait for the previous line to finish

cpy missile0y		; is Missile 0's y position the same as the current scanline?

bne SkipActivateMissile0; if it isn't then don't set Missile 0's visible lines

lda #20			; otherwise set Missile 0's visible lines to 20

sta visiblemissile0line	; and store it in the visiblemissile0line

SkipActivateMissile0

lda visiblemissile0line	; if the visiblemissile0line is zero

beq FinishMissile0	; don't draw Missile 0

lda #2			; otherwise set the accumulator to 2		

dec visiblemissile0line	; and decrement the visiblemissile0line by 1

FinishMissile0

sta ENAM0		; enable/disable Missile 0
			; if the visiblemissile0line is non zero,
			; we're drawing it

cpy bally		; is ball's y position the same as the current scanline?

bne SkipActivateBall	; if it isn't then don't set ball's visible lines

lda #8			; otherwise set the ball's visible lines to 4

sta visibleballline	; and store it in the visibleballline

SkipActivateBall

lda visibleballline	; if the visibleballline is zero

beq FinishBall		; don't draw the ball

lda #2			; otherwise set the accumulator to 2		

dec visibleballline	; and decrement the visibleballline by 1

FinishBall

sta ENABL		; enable/disable the ball
			; if visibleballline is non, zero,
			; we're drawing it

cpy missile1y		; is Missile 1's y position the same as the current scanline?

bne SkipActivateMissile1; if it isn't then don't set Missile 1's visible lines

lda #20			; otherwise set Missile 1's visible lines to 20

sta visiblemissile1line	; and store it in the visiblemissile1line

SkipActivateMissile1

lda visiblemissile1line	; if the visibleballline is zero

beq FinishMissile1	; don't draw Missile 1

lda #2			; otherwise set the accumulator to 2		

dec visiblemissile1line	; and decrement the visiblemissile1line by 1

FinishMissile1

sta ENAM1		; enable/disable Missile 1
			; if the visibleballline is non zero,
			; we're drawing it

dey				; subtract one off the line counter thingy

bne ScanLoop		; and repeat if we're not finished with all the scanlines.

lda #2			;#2 for the VBLANK...

sta WSYNC		;Finish this final scanline.

lda #$82

;sta VBLANK		; Make TIA output invisible for the overscan,
			; (and keep it that way for the vsync and vblank)

;***************************** OVERSCAN CALCULATIONS
;I'm just gonna count off the 30 lines of the overscan.
;You could do more program code if you wanted to.

ldx #30   ;store 30

OverScanWait

sta WSYNC		; wait for VSync

dex			; decrement the x register

bne OverScanWait	; if it hasn't been 30 scanlines jump to OverScanWait

jmp  GameLoop		;Continue this loop forver! Back to the code for the vsync etc

PositionSprite

sta HMCLR

sec

sta WSYNC
	
PositionSpriteLoop

sbc	#15

bcs	PositionSpriteLoop

eor	#7

asl

asl

asl

asl			  

sta.wx HMP0,X	

sta	RESP0,X  

sta	WSYNC	  

sta	HMOVE	

rts

;*************************************************************************
; Interrupt Vectors

ORG $FFFA

InterruptVectors

.word Start			; NMI

.word Start			; RESET

.word Start			; IRQ

I removed the last VBLANK from my previous code and still am having problems. Any ideas?

 

Sincerely,

 

6502Pong

Link to comment
Share on other sites

Yup...best case (where the shortest path is always taken) ends up using 70 cycles + 3 for WSYNC. Worst case (where the longest path is always taken) ends up using a whopping 100 cycles + 3 for WSYNC.

 

It's probably a good idea to keep cycle time listed in areas that are time-critical. For kernel use, also a running total of cycle times for best-case/worst case scenarios. Commonly, this is preceded by the @ symbol in the comments.

 

Here's your kernel with timing listed. A WSYNC resets the count, so begin there and wrap if a branch to earlier lines occur...

 

ScanLoop ; this tag is reached @50/80 cycles.
   lda INPT0                ;3 @53/83 read the charge from the first paddle controller
   bmi paddle0              ;2 @55/85 if paddle 0 is charged
   .byte $2c                ;4 @59/89 paddle 0 wasn't charged so waste 2 cycles
paddle0
   sty missile0y            ;3 @59/89 then set player 0's y position
                            ;         based on it's readout
   lda INPT1                ;3 @62/92 read the charge from the first paddle controller
   bmi paddle1              ;2 @64/94 if paddle 1 is charged
   .byte $2c                ;4 @68/98 paddle 1 wasn't charged so waste 2 cycles
paddle1
   sty missile1y            ;3 @68/98 then set player 1's y position
                            ;         based on it's readout
   lda #2                   ;2 @70/100!
   sta WSYNC                ;Wait for the previous line to finish
;--------------------------
   cpy missile0y            ;3 @3 is Missile 0's y position the same as the current scanline?
   bne SkipActivateMissile0 ;2 @5 if it isn't then don't set Missile 0's visible lines
   lda #20                  ;2 @7 otherwise set Missile 0's visible lines to 20
   sta visiblemissile0line  ;3 @10 and store it in the visiblemissile0line
SkipActivateMissile0
   lda visiblemissile0line  ;3 @9/13 if the visiblemissile0line is zero
   beq FinishMissile0       ;2 @11/15 don't draw Missile 0
   lda #2                   ;2 @13/17 otherwise set the accumulator to 2
   dec visiblemissile0line  ;5 @18/22 and decrement the visiblemissile0line by 1
FinishMissile0
   sta ENAM0                ;3 @15/25 enable/disable Missile 0
                            ;         if the visiblemissile0line is non zero,
                            ;         we're drawing it
   cpy bally                ;3 @18/28 is ball's y position the same as the current scanline?
   bne SkipActivateBall     ;2 @20/30 if it isn't then don't set ball's visible lines
   lda #8                   ;2 @22/32 otherwise set the ball's visible lines to 4
   sta visibleballline      ;3 @25/35 and store it in the visibleballline
SkipActivateBall
   lda visibleballline      ;3 @24/38 if the visibleballline is zero
   beq FinishBall           ;2 @26/40 don't draw the ball
   lda #2                   ;2 @28/42 otherwise set the accumulator to 2        
   dec visibleballline      ;5 @33/47 and decrement the visibleballline by 1
FinishBall
   sta ENABL                ;3 @30/50 enable/disable the ball
                            ;         if visibleballline is non, zero,
                            ;         we're drawing it
   cpy missile1y            ;3 @33/53 is Missile 1's y position the same as current scanline?
   bne SkipActivateMissile1 ;2 @35/55 if it isn't then don't set Missile 1's visible lines
   lda #20                  ;2 @37/57 otherwise set Missile 1's visible lines to 20
   sta visiblemissile1line  ;3 @40/60 and store it in the visiblemissile1line
SkipActivateMissile1
   lda visiblemissile1line  ;3 @39/63 if the visibleballline is zero
   beq FinishMissile1       ;2 @41/65 don't draw Missile 1
   lda #2                   ;2 @43/67 otherwise set the accumulator to 2        
   dec visiblemissile1line  ;5 @48/72 and decrement the visiblemissile1line by 1
FinishMissile1
   sta ENAM1                ;3 @45/75 enable/disable Missile 1
                            ;         if the visibleballline is non zero,
                            ;         we're drawing it
   dey                      ;2 @47/77 subtract one off the line counter thingy
   bne ScanLoop             ;2 @49/79 and repeat if we're not finished with all the scanlines.

Link to comment
Share on other sites

You can save one more cycle, if you make sure that the *address* of e.g. paddle1 is an 1 byte opcode, e.g. $ea (nop) or $d8 (cld).

	  MAC READ_PADDLE_1
	lda INPT0 ; 3   - always 8
	bmi .save+1; 2/3
.save   sty paddle1; 3/2
  ENDM

 

Thats very clever :thumbsup:

I remember you posting that when I was writing Vong, but I never really understood it. It makes sense now though :)

Edited by Wickeycolumbus
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...