News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: Screen shaking (NES)  (Read 5865 times)

PolishedTurd

  • Full Member
  • ***
  • Posts: 188
    • View Profile
Screen shaking (NES)
« on: January 15, 2011, 01:44:54 am »
How can I make the screen appear to jitter and shake in an NES game? Yes, it's Ninja Gaiden. I guess all that would happen is pixels being shifted left-right and up-down by a few pixels, with some kind of time and distance parameters. I want it to seem as though the castle is crumbling as the time winds down, so ideally, I could increase the amplitude and/or frequency of shaking as the timer runs down. I would like for the map tiles and sprites to jiggle while the HUD remains stationary, if possible.

Is this feasible?

Dwedit

  • Sr. Member
  • ****
  • Posts: 307
    • View Profile
    • Dwedit's Website
Re: Screen shaking (NES)
« Reply #1 on: January 15, 2011, 09:14:32 am »
I've investigated the game a little.  Looks like all levels are horizontally scrolling, and there's no built-in vertical scrolling split.
You could still pull off an earthquake effect as long as you don't need the sprites to move along with it.
What the game normally does is waste about 40 scanlines of time waiting for a sprite 0 hit.  The sprite 0 hit happens at scanline #54, at pixel 186-202.  Then a little later, it performs the horizontal scrolling.
You would need to go into the ASM code and add a couple PPU Address writes to select the correct vertical scrolling location after the sprite 0 hit.
Then to perform the vertical shaking, you could move sprite #0 up and down as needed to select the location the split half of the screen gets drawn at.  Or change the PPU address writes and leave sprite 0 in the same place.

Split scrolling on the NES is a little complicated for people who aren't familiar with how it works.
"We are merely sprites that dance at the beck and call of our button-pressing overlord."

PolishedTurd

  • Full Member
  • ***
  • Posts: 188
    • View Profile
Re: Screen shaking (NES)
« Reply #2 on: January 21, 2011, 11:07:06 pm »
Hmm, seems like it's a bit more over my head than I thought. How much simpler does it become if I forego the HUD split and just shake the whole screen?


Can you explain (or point me to a good resource for) what is meant by...

- a sprite 0 hit. Is this the first sprite the game draws on each cycle? (Not sure if cycle is the right term here). Is it always the same sprite? Always the player 1 sprite, or the leftmost or topmost sprite?

- a scanline of time, and "wasting" 40 of them. How have you determined that the sprite 0 hit happens at scanline #54, pixel 186-202?

If I imagine correctly, moving sprite 0 would make the player look as though he's shaking, whereas changing the PPU address writes with sprite 0 in the same place would make the world look like it's shaking while the player sprite remains at the same screen coordinates. Do I have that right?

Do your instructions apply to horizontal shaking as well?

Thanks for investigating and helping.

Dwedit

  • Sr. Member
  • ****
  • Posts: 307
    • View Profile
    • Dwedit's Website
Re: Screen shaking (NES)
« Reply #3 on: January 22, 2011, 09:06:20 am »
"Sprite 0" has nothing to do with player sprites, and all to do with the special sprite #0 from the sprite table.
Sprite #0 is special, because it can signal to the game that the screen should split there.  The sprite is always placed in a fixed position in the top status bar.
Whenever the non-transparent sprite pixels overlap the non-transparent background pixels, the "sprite collision" flag is set for the entire frame.  The sprite collision flag is Cleared at the end of vblank.
So what the game does is first wait for the flag to become clear:

07:F5A2:2C 02 20  BIT $2002
07:F5A5:70 FB     BVS $F5A2

Then waits for the flag to become set:

07:F5A7:2C 02 20  BIT $2002
07:F5AA:50 FB     BVC $F5A7

Then it has reached scanline #54, so it's ready to split the screen.
I looked at the asm, first it does a couple of MMC1 CHR ROM bankswitches:

Code: [Select]
07:F5AC:A5 5A     LDA $005A
07:F5AE:8D FF DF  STA $DFFF
07:F5B1:4A        LSR
07:F5B2:8D FF DF  STA $DFFF
07:F5B5:4A        LSR
07:F5B6:8D FF DF  STA $DFFF
07:F5B9:4A        LSR
07:F5BA:8D FF DF  STA $DFFF
07:F5BD:4A        LSR
07:F5BE:8D FF DF  STA $DFFF
07:F5C1:A5 57     LDA $0057
07:F5C3:8D FF BF  STA $BFFF
07:F5C6:4A        LSR
07:F5C7:8D FF BF  STA $BFFF
07:F5CA:4A        LSR
07:F5CB:8D FF BF  STA $BFFF
07:F5CE:4A        LSR
07:F5CF:8D FF BF  STA $BFFF
07:F5D2:4A        LSR
07:F5D3:8D FF BF  STA $BFFF

Then it writes the scrolll
Code: [Select]
07:F5D6:A5 A3     LDA $00A3
07:F5D8:8D 05 20  STA $2005
07:F5DB:A5 A9     LDA $00A9   ;this second scroll write to 2005 is worthless and doesn't do anything
07:F5DD:8D 05 20  STA $2005  ;
07:F5E0:A5 4C     LDA $004C
07:F5E2:29 01     AND #$01
07:F5E4:05 1C     ORA $001C
07:F5E6:8D 00 20  STA $2000

By the time the actual scrolling starts, we're at scanline #55.

More to come...

"We are merely sprites that dance at the beck and call of our button-pressing overlord."