Page 1 of 2

DELAYS??

Posted: Wed Jul 05, 2006 5:19 am
by nineTENdo
WHats a good way to slow down movement of sprites on button presses.

Code: Select all

       lda X_POS
	ADC #20
	
	ASL a
	asl a
	sTA X_POS

	lda Y_POS
	ADC #80
	
	ASL a
	asl a
	sTA Y_POS
        BNE infinite
This code gets the sprite to move crazy is there any way i could input a delay so that im able to see each increment. The infinite just goes though Vblank and joy stobes

Thanks in Advance
EL

Re: DELAYS??

Posted: Wed Jul 05, 2006 6:17 am
by Disch
nineTENdo wrote:WHats a good way to slow down movement of sprites on button presses.
Don't be constantly checking button presses. NMIs will occur at a steady 60 FPS. If you want your game to move at a constant, steady rate, let NMIs drive your program logic.

What does that mean? Well -- Strobe joypad and move the player (as well as do any other logic) only ONCE per frame:

1) Wait for VBlank
2) Strobe Joypad, move player, etc (only once!)
3) Wait for another VBlank
4) do step 2 again
5) wait for another VBlank
5) etc

if you move the player 1 pixel per frame, he'll move 60 pixels per second (which isn't blazing fast).

Posted: Wed Jul 05, 2006 7:14 am
by nineTENdo
Would it be best if use the waitvblank as a subroutine so i can leave it apart from strobing and moving. Heres what i have. Could i fit more vblanks to make it even slower.

Code: Select all

infinite
waitblank: 
	       
	lda $2002  
	bpl waitblank 

	lda #$00   ; these lines tell $2003
	sta $2003  ; to tell
	lda #$00   ; $2004 to start
	sta $2003  ; at $0000.

	lda #40 ; load Y value
	sta $2004 ; store Y value
	
	lda #$02 ; tile number 0
	sta $2004 ; store tile number
	
	lda #$00 ; no special junk
	sta $2004 ; store special junk
	
	lda X_Pos ; load X value
	sta $2004 ; store X value
	; and yes, it MUST go in that order.

 	lda #$01	; directly loads the Accumulator with 1
 	sta $4016	; stores the Accumulator value (1) into $4016
 	lda #$00	; directly loads the Accumulator with 0
 	sta $4016 
	
	
	lda $4016
	and #1
	bne KEYDN
	
	lda $4016 
	lda $4016  
	lda $4016  

	lda $4016
	lda $4016 
	lda $4016  
	lda $4016
	JMP infinite

Posted: Wed Jul 05, 2006 9:13 am
by tokumaru
It's best that you don't actually "wait" for VBlanks. It has been confirmed that code like this

Code: Select all

waitblank:
   lda $2002 
   bpl waitblank
will miss a few VBlanks along the way. NMI's are the way to make use of all VBlanks.

You should be sure to let NMI's enabled, and somewhere inside the NMI routine (preferably after all PPU operations) you read the controllers and update the character's coordinates accordingly.

After you do that, you'll be reading keys and processing them 60 times per second. If you're not carefull, even that may still be too much for you. To prevent things from moving insanely fast, you could turn your coordinates into fixed point values. And later, insert animation tables defining how many NES frames should each animation frame last, so that animation doesn't go too fast. Anyway, that's in the future.

Posted: Wed Jul 05, 2006 10:03 am
by blargg
Take a look at my multithreading demo for more straight forward approach, where you can have each thread sit and wait until enough NMIs have gone by.

Posted: Wed Jul 05, 2006 10:06 am
by tepples
It could look like this:

Code: Select all

.segment "ZEROPAGE"
vblanked: .res 1

.segment "CODE"
nmiHandler:
  inc vblanked
  rti

waitVblank:
  lda vblanked
  beq waitVblank
  lda #0
  sta vblanked
  lda $2002  ; reset $2006 sub address
  rts

question

Posted: Wed Jul 05, 2006 5:17 pm
by lord_Chile
reading $2002 reset 1st/2nd write flip flop (for $2005 and $2006). Also "the in vblank flag" is cleared. but for what it miss frames???, if NMI doesnt be affected by it no?

Posted: Wed Jul 05, 2006 8:03 pm
by tepples
If vblank happens at the exact same cycle (?) as a $2002 read, then the vblank bit of $2002 never gets set for that frame.

Posted: Wed Jul 05, 2006 9:09 pm
by Disch
Snippits from the readme included with blargg's VBL test ROMs:
2.vbl_timing
------------
Tests timing of VBL being set, and special case where reading VBL flag
as it would be set causes it to not be set for that frame.

8) Reading 1 PPU clock before VBL should suppress setting



5.nmi_suppression
-----------------
Tests timing of NMI suppression when reading VBL flag just as it's set,
and that this doesn't occur when reading one clock before or after.

3) Reading flag when it's set should suppress NMI
6) Reading flag 1 PPU clock after set should suppress NMI
9) Reading flag 1 PPU clock before set should suppress NMI

The bottom line:

You do not want to rely on $2002 polling for VBlank waiting (since you have roughly a 1 in 7 chance of a frame being skipped due to the flag suppresion). It's fine for the "warm up" time you have to do when the system powers up, but after that you should always fall back to good old reliable NMIs, which will never miss a frame (as long as they're enabled, and as long as you're not dicking with $2002 around the start of VBlank).

Re: DELAYS??

Posted: Thu Jul 06, 2006 5:08 pm
by nineTENdo
Disch wrote:let NMIs drive your program logic.
Great idea!! That will help with experimenting. But i cant seem to get an NMI to run. Do i need certain conditions to run it? Do you know of a simple algorithm to just add X of a sprite movement?

Thanks
EL

Posted: Thu Jul 06, 2006 9:22 pm
by tepples
NMI will execute if bit 7 of PPUCTRL ($2000) is set.

Posted: Thu Jul 06, 2006 10:05 pm
by nineTENdo
OOOOOHHHH ok i forgot! Does it matter if i set it before or after the code in the code of the NMI routine. and when i set it do i have to turn it back off?

Posted: Fri Jul 07, 2006 1:29 am
by Bregalad
I think it is up to you to found the best way to use the hardware. Usually you'd want to disable the NMIs at reset, to have the reset procedure execute normally. Then, once you're done and your game is ready to start, you'd want to enable NMI and keep them enabled always exept when loading a new level or something in that genre.
Since you have to write to $2000 in each VBlank in order to get proper scrolling values, you'd want a variable that contain the value to write to $2000 at the end of VBlank. It would first be initialised with NMI enabled, wich pattern tables use BG and Sprites, etc... and only its two low bits would be modified by the scrolling programm to change nametables.

Posted: Fri Jul 07, 2006 1:42 am
by nineTENdo
Bregalad wrote: you'd want to enable NMI and keep them enabled always exept when loading a new level or something in that genre.
Does that include updating Sprite positions?

Just wanted to say that The Hex Editor in FCEUXD has changed my entire view of reading/writing code!!!!!

Thanks FCEUXD!!!!!!

Posted: Fri Jul 07, 2006 2:02 am
by Bregalad
Yes, I also had been very happy when I discovered all the debuggin features of FCEUXD. It really rocks.

I recommand to do you sprite position calculating outise of the NMI in the game logic, but it is up to you to know.
For example, most Konami and Nintendo games like to do EVERYTHING in NMI and just do infinite jumps outside of NMI. After some experitmenation I think it is the worst way to work, but they still did it.
Square seems to like do NOTHING in NMI, just return and continue the previous code that was just waiting a VBlank trigger.
Most other game companies (Capcom, Enix, HAL, etc...) seems to do timing critical routine in NMI plus other things like sound, and the game logic outinde of the NMI, wich is definitely the best way, for my viewpoint.