This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Super Mario Brothers Sprite 0

Super Mario Brothers Sprite 0
by on (#228356)
I'm trying to better understand how the sprite 0 hits are handled in SMB (And, really, all early NES titles that use it for mid screen splits). Mostly out of curiosity and hacking in general.

I poked around the SMB disassembly: https://gist.github.com/1wErt3r/4048722 (I should also point out that I only understand the basic concepts of assembly -- I'm a DB engineer by trade...)
And found the byte data for sprite 0 is $18, $ff, $23, $58
Sniffing the memory I can see that data at 0x001200 and I can edit it (Using the emulator fceux). I wanted to see what it would do to the screen if it scrolled midscreen or at the top.
Why? Dunno, just like hacking. If I set the value to something like 66 for the first byte, it will move sprite 0 down to the middle of the screen and split it in half. But it then crashes the game once you scroll too far forward. Also, certain values just cause it to crash instantly.

My questions are (And I apologize if these are too basic), what is causing it to crash sporadically? Any other fun things I can do with hacking sprite 0 in early games?

Thank you for your time.
Re: Super Mario Brothers Sprite 0
by on (#228357)
The program determines that sprite 0 has been drawn by reading the sprite 0 hit flag (bit 6 of a memory-mapped I/O register at $2002).
Code:
  ; 1. wait for 0 (which happens at end of vblank)
@wait_s0_clear:
  bit $2002  ; copy bit 6 into V flag
  bvs @wait_s0_clear

  ; 1. wait for 1 (when sprite 0 pixel overlaps opaque BG pixel)
@wait_s0_set:
  bit $2002  ; copy bit 6 into V flag
  bvc @wait_s0_set

But when sprite 0 doesn't overlap an opaque part of the background, that bit never becomes true, leaving the CPU in an infinite loop at @wait_s0_set.

It's possible to make a sprite 0 reading routine that is more tolerant of errors, but early games didn't bother. The following routine also allows vblank to end the loop. This will produce a graphical glitch instead of freezing.
Code:
  ; 1. wait for 0 (which happens at end of vblank)
@wait_s0_clear:
  bit $2002  ; copy bit 6 into V flag
  bvs @wait_s0_clear

  ; 2. wait for either sprite 0 or vblank flag to become 1
  lda #$C0  ; bit 7: vblank; bit 6: sprite 0
@wait_s0_set:
  bit $2002  ; copy !(A & [$2002]) into Z flag
  beq @wait_s0_set
  bmi @vblank_hit_instead
Re: Super Mario Brothers Sprite 0
by on (#228358)
A sprite zero hit only happens when an opaque pixel in sprite 0 overlaps an opaque pixel in the background. SMB is full of transparent background areas (e.g. the sky), and if the sprite ends up in one of those areas, the game locks up waiting for a sprite 0 hit that never happens.
Supermario picasso
by on (#233060)
I synth charts of mario and join to the assembled (dissambled mario)
Attachment:
mpv-shot0004.jpg
mpv-shot0004.jpg [ 38.79 KiB | Viewed 2809 times ]