It is currently Thu May 23, 2019 2:34 pm

All times are UTC - 7 hours

Post new topic Reply to topic  [ 17 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Fri Dec 21, 2018 9:52 am 

Joined: Tue Dec 11, 2018 9:47 am
Posts: 8
Just wanted to post an update, I incorporated the feedback to differentiate between buttons that are pressed vs buttons that are held. I'm trying to mimic the "delayed auto shift" mechanic from Tetris, so in addition to that I also keep track of whether the D-Pad button has been held long enough. This is tracked separately for the different d-pad buttons - if d-pad buttons are held for enough frames this delay auto shift mode will be active for the button that is being held. Here is my code for reading controller input, tracking which buttons are pressed and which are held, as well as identifying whether buttons held have been held long enough to activate the "delayed auto shift" state where the sprites enter a sustained movement:

  LDX buttons_held ;register x saves buttons held from last frame
  LDY buttons_pressed ; register y saves buttons initially pressed last frame

  LDA #$01
  STA controller1
  STA current_controller_state
  STA controller1
  LDA controller1
  ROL current_controller_state
  BCC .loop

  ;wipe out buttons_held and buttons_pressed for any button not currently active
  LDA buttons_held
  AND current_controller_state
  STA buttons_held
  LDA buttons_pressed
  AND current_controller_state
  STA buttons_pressed

  ;wipe out delay auto shift status for any D-Pad button not active
  LDA dpad_delay_auto_shift_active
  AND current_controller_state
  STA dpad_delay_auto_shift_active
  BEQ SkipResetDASTimer
  ; reset counter to 0 if no dpad buttons are active
  LDA #$00
  STA dpad_delay_auto_shift_counter
  ;pressed buttons from last frame that are still pressed are now held
  TYA ; fetch last frame button pressed from Y register
  AND current_controller_state ; clear any buttons not currently active
  ORA buttons_held
  STA buttons_held

  ;buttons that are currently active but not held should be considered pressed
  ;assuming buttons_held is still in accumulator a
  EOR current_controller_state
  STA buttons_pressed

  ;calculate delay auto shift status for d-pad
  LDA buttons_held
  TAX ; store this currently held dpad buttons in case we need it later
  BEQ SkipIncrementDASTimer ; skip if no d-pad buttons are held
  LDA dpad_delay_auto_shift_active
  CMP #$00
  BNE SkipIncrementDASTimer ; if DAS is already active, don't increment
  INC dpad_delay_auto_shift_counter
  LDA dpad_delay_auto_shift_counter
  BCC SkipIncrementDASTimer
  STA dpad_delay_auto_shift_active



In a different method I move the ship based on whether the d-pad button is in pressed state, or if the button is in the state where delay auto shift is active. I have a counter in this part of the code to track whether to move the sprites while in the delay auto shift state, this is to slow the movement of the sprites.


  INC sustained_movement_counter

  LDA buttons_pressed
  BNE MoveShipUp

  LDA dpad_delay_auto_shift_active
  BEQ EndReadUp

  LDA sustained_movement_counter
  BCC EndReadUp

  LDA shipTile1Y
  SBC #$08
  STA shipTile1Y
  STA shipTile2Y
  STA shipTile3Y

  LDA shipTile4Y
  SBC #$08
  STA shipTile4Y
  STA shipTile5Y
  STA shipTile6Y

  ;set counter to zero since we're about to go into DAS
  LDA #$00
  STA sustained_movement_counter

I know there's opportunities for optimization here, but I think I'm going to move on to the next part of the project. This is where the full code for my implementation is: ... torial.asm

Thanks everyone for the help and advice!

PostPosted: Fri Dec 21, 2018 10:11 am 

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21397
Location: NE Indiana, USA (NTSC)
For something like Tetris, you really only need to handle autorepeat for left and right directions and ensure that other button presses (such as A or B for rotate) won't interrupt autorepeat. This means you don't need a separate counter per button, just the set of which buttons are repeating and the time left until the next repeat. Here's working autorepeat code that I've used in Concentration Room, RHDE, robotfindskitten, and 240p Test Suite (source):

cur_keys:  .res 2  ; Buttons held this frame
new_keys:  .res 2  ; Buttons held this frame and not last
das_keys:  .res 2  ; Buttons being held
das_timer: .res 2  ; time left until next autorepeat

; Computes autorepeat (delayed-auto-shift) on the gamepad for one
; player, ORing result into the player's new_keys.
; @param X which player to calculate autorepeat for
.proc autorepeat
  ; If no keys are held, skip all autorepeat processing
  lda cur_keys,x
  beq no_das

  ; If any keys were newly pressed, set the eligible keys among them
  ; as the autorepeating set.  For example, changing from Up to
  ; Up+Right sets Right as the new autorepeating set.
  ; (Quirk: Going from 0 to Up+Right in one frame sets Up+Right
  ; as the autorepeating set.)
  lda new_keys,x
  beq no_restart_das
  sta das_keys,x
  lda #DAS_DELAY
  bne have_das_timer

  ; If time has expired, merge in the autorepeating set
  dec das_timer,x
  bne no_das
  lda das_keys,x
  and cur_keys,x
  ora new_keys,x
  sta new_keys,x
  lda #DAS_SPEED
  sta das_timer,x

That is, unless you're trying to ensure bug-for-bug reproduction of a particular game's autorepeat behavior.

Pin Eight | Twitter | GitHub | Patreon

Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 17 posts ]  Go to page Previous  1, 2

All times are UTC - 7 hours

Who is online

Users browsing this forum: No registered users and 12 guests

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group