It is currently Sun Jan 20, 2019 12:19 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 
Offline

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:

Code:
ReadController1:
  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
  LSR A
  STA controller1
.loop:
  LDA controller1
  LSR A
  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
  AND DPAD_BUTTONS
  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
SkipResetDASTimer:
  ;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
  AND #DPAD_BUTTONS
  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
  CMP #BUTTON_ACTIVE_DELAY1
  BCC SkipIncrementDASTimer
  TXA
  STA dpad_delay_auto_shift_active

SkipIncrementDASTimer:

  RTS



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.

Code:
MoveShip:

  INC sustained_movement_counter

ReadUp:
  LDA buttons_pressed
  AND #UP_BUTTON
  BNE MoveShipUp

  LDA dpad_delay_auto_shift_active
  AND #UP_BUTTON
  BEQ EndReadUp


  LDA sustained_movement_counter
  CMP #BUTTON_ACTIVE_DELAY2
  BCC EndReadUp

MoveShipUp:
  LDA shipTile1Y
  SEC
  SBC #$08
  STA shipTile1Y
  STA shipTile2Y
  STA shipTile3Y

  LDA shipTile4Y
  SEC
  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
EndReadUp:


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:
https://github.com/buschi8282/nes-tutor ... torial.asm

Thanks everyone for the help and advice!


Top
 Profile  
 
PostPosted: Fri Dec 21, 2018 10:11 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21004
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):
Code:
REPEATABLE_KEYS = KEY_LEFT|KEY_RIGHT

.zeropage
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

.code
;;
; 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
  and #REPEATABLE_KEYS
  beq no_restart_das
  sta das_keys,x
  lda #DAS_DELAY
  bne have_das_timer
no_restart_das:

  ; 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
have_das_timer:
  sta das_timer,x
no_das:
  rts
.endproc


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


Top
 Profile  
 
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: Google [Bot] and 1 guest


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