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.