It is currently Tue Nov 13, 2018 9:33 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 3 posts ] 
Author Message
PostPosted: Thu Nov 01, 2018 7:37 pm 
Offline

Joined: Thu Nov 01, 2018 7:25 pm
Posts: 1
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.


Top
 Profile  
 
PostPosted: Thu Nov 01, 2018 8:06 pm 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20763
Location: NE Indiana, USA (NTSC)
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


Top
 Profile  
 
PostPosted: Thu Nov 01, 2018 8:59 pm 
Online
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10959
Location: Rio de Janeiro - Brazil
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.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: Google Adsense [Bot], tepples 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