It is currently Thu Jul 20, 2017 7:39 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Mon Jan 16, 2017 11:31 am 
Offline

Joined: Sat Jan 14, 2017 8:40 am
Posts: 23
Hi All!

I'm still working on these Nerdy Nights tutorials and I'm almost done : ) I'm having some trouble though working out a feature. Any help would be appreciated. I'm trying to add a timer to the release of the ball. For example, currently when the play screen is loaded the ball immediately begins moving towards a paddle. I instead would like the play screen to load, and the ball NOT appear for a few seconds to allow the players to ready themselves. To achieve this, I came up with a timer that I insert before the ball sprite initialization code. I have separated the code into sections to make this easier to read. Here is the timer. The amount of time the timer waits is controlled by the Constant SETREADYFRAMES

Code:
ReadyTimer:
  LDX #$00
  ReadyTimerInnerLoop:
  LDA #$00
  STA ReadyFrameCount
  ReadyTimerInc:
  INC ReadyFrameCount
  LDA ReadyFrameCount
  CMP #SETREADYFRAMES ;;Currently Set to 200
  BNE ReadyTimerInc
  INX
  CPX #$0A
  BNE ReadyTimerInnerLoop


I then try to combine the timer with the subroutine LoadInitialBallstats. This subroutine stores the initial stats that the program needs to update the sprite positions in order to move the ball on screen.

Code:
LoadInitialBallStats:
  ReadyTimer:
  LDX #$00
  ReadyTimerInnerLoop:
  LDA #$00
  STA ReadyFrameCount
  ReadyTimerInc:
  INC ReadyFrameCount
  LDA ReadyFrameCount
  CMP #SETREADYFRAMES
  BNE ReadyTimerInc
  INX
  CPX #$0A
  BNE ReadyTimerInnerLoop
;Timer Done. Now Set The Initial Ball Stats and Starting Paddle Position
  LDA #$01
  STA balldown
  STA ballright
  LDA #$00
  STA ballup
  STA ballleft

  LDA #$50
  STA bally

  LDA #$80
  STA ballx

  LDA #$01
  STA ballspeedx
  STA ballspeedy
LoadInitialBallStatsDone:
  RTS


Unfortunately, my timer just isn't doing what I want it to do. When I test the timer in the FCEUX debugger it is counting up the way I want it too, so in theory I think it should work, but in practice it isn't. When I set the timer to a lower framecount using SETREADYFRAMES, like below 200, the ball immediately moves on the screen without the delay I want. When I set the timer at 200 or above, the ball will not appear at all.

Any help with this problem would be very much appreciated : )

Thanks All!

-Hundo


Top
 Profile  
 
PostPosted: Mon Jan 16, 2017 5:39 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
Code executes as fast as the CPU can run it. Your 'ReadyTimerInc' loop is not waiting any significant amount of time --- each iteration does not represent a 'frame' like you seem to want it to.

To wait for a full frame to pass, the general approach is to wait for an NMI to trigger. Another approach is to spin on a $2002 read loop until the vblank flag raises -- but that is imperfect and can cause some frames to be missed (ie: you might end up waiting longer than you want)


Top
 Profile  
 
PostPosted: Mon Jan 16, 2017 6:09 pm 
Offline

Joined: Sat Jan 14, 2017 8:40 am
Posts: 23
Disch wrote:
Code executes as fast as the CPU can run it. Your 'ReadyTimerInc' loop is not waiting any significant amount of time --- each iteration does not represent a 'frame' like you seem to want it to.

To wait for a full frame to pass, the general approach is to wait for an NMI to trigger. Another approach is to spin on a $2002 read loop until the vblank flag raises -- but that is imperfect and can cause some frames to be missed (ie: you might end up waiting longer than you want)


OK, how then would you suggest that I go about constructing something to wait for say 120 frames (2 seconds to pass) by utilizing the NMI. Is there a DOC you can point me to that would be helpful to read. BTW I read your document on NMI and VBLANK (3 times actually). Super interesting, and probably what I need to solve this problem, however I'm not experienced enough yet to pull out the knowledge I need to construct this timer.

Can you give me a small code example so I can get started in the right direction?

Thank You
Hundo


Top
 Profile  
 
PostPosted: Mon Jan 16, 2017 6:12 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5393
Location: Canada
A common way is to change some value in the NMI routine, and then make a loop that checks that value until it changes.
Code:
; nmi routine, address placed in vector table at end of ROM
nmi:
   inc frame
   rti

; wait routine
wait_nmi:
   lda frame
:
   cmp frame
   beq :-
   rts

; call when you need to wait:
   jsr wait_nmi


Top
 Profile  
 
PostPosted: Mon Jan 16, 2017 7:54 pm 
Offline

Joined: Sat Jan 14, 2017 8:40 am
Posts: 23
rainwarrior wrote:
A common way is to change some value in the NMI routine, and then make a loop that checks that value until it changes.
Code:
; nmi routine, address placed in vector table at end of ROM
nmi:
   inc frame
   rti

; wait routine
wait_nmi:
   lda frame
:
   cmp frame
   beq :-
   rts

; call when you need to wait:
   jsr wait_nmi


Thank you Rainwarrior and Disch! Your suggestions helped immensly!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 6 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