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

Author Topic: What code causes SMAS SMB brick physics to be different from the original SMB?  (Read 1473 times)

HTV04

  • Newbie
  • *
  • Posts: 3
    • View Profile
The title really explains it, but here's my lengthy backstory:

As you may know, the SMAS SMB brick physics are different from SMB. Mario hovers a little after hitting a brick before descending back down in SMAS, rather than falling straight down. I've been trying to recreate this behavior in the original SMB (for fun), but to no avail. After a lot of experimenting with the disassemblies for both games, I found out that "NOP-ing" the code for NYSpd (according to the comprehensive SMB disassembly) made it so that Mario hovers when hitting into bricks, just like in SMAS. The only problem is, Mario is now able to jump through blocks, which is definitely not akin to the behavior in SMAS. Something is causing NYSpd to not be called when hitting a brick as big Mario in SMAS. I have tried to look at the disassemblies for both games to look for any differences in the code, but I found nothing relating to the brick physics.

I even tried looking at the patch for SMAS that restores the brick functionality, but then I found out that the patch just injects some code into the BrickShatter subroutine (also according to the comprehensive SMB disassembly) for a subroutine added by the patch into an unused part of the ROM to set Mario's Y speed to 1. This is not what SMB does, as the BrickShatter subroutine is mostly the same between versions, just with some additional code relating to not playing the brick shatter sound when other sounds are playing in SMAS. This addition does not seem to affect the brick physics at all.

:banghead:

So why are Mario's brick physics different in SMAS SMB? Has anyone else researched this?

Cyneprepou4uk

  • Sr. Member
  • ****
  • Posts: 400
  • I am the baldest romhacker
    • View Profile
You probably should set a write breakpoint to Y speed
iromhacker.ru - NES ROM hacking tutorials for beginners. Please use Google Translate browser extension

Vanya

  • Hero Member
  • *****
  • Posts: 1672
    • View Profile
IIRC the SMAS patch that fixes this issue explains that is was a reversed value or some such.

I suggest checking out that patch to see what it does.

https://www.romhacking.net/hacks/167/

Yeap, IRC! It's "just a case of a reversed Y velocity."
That would explain why it only affects Big Mario.

HTV04

  • Newbie
  • *
  • Posts: 3
    • View Profile
I did, but it just wrote a subroutine to an unused part of the ROM to set Mario's Y speed to 1. NYSpd also does this, but isn't called when Big Mario hits a brick for some odd reason.

Vanya

  • Hero Member
  • *****
  • Posts: 1672
    • View Profile
Can you post the code for all of this?
The NES, SNES, and Fixed versions?

It would help to see what we're dealing with exactly.

Right now I suspect that either NYSpd is missing something it needed to be doing, or something about how the code is being executed is different between the two platforms.

HTV04

  • Newbie
  • *
  • Posts: 3
    • View Profile
Can you post the code for all of this?
The NES, SNES, and Fixed versions?

It would help to see what we're dealing with exactly.

Right now I suspect that either NYSpd is missing something it needed to be doing, or something about how the code is being executed is different between the two platforms.
Sure:
SMB: https://gist.github.com/1wErt3r/4048722
SMAS SMB: https://github.com/Ersanio/SMAS-Disassembly/blob/master/Assembly/SMB1/code/b03/_b03.asm

For the SMAS SMB disassembly, NYSpd is the CODE_03E39C subroutine.

The fixed version isn't important. It has nothing to do with NYSpd, it affects the BrickShatter (CODE_03BFA1) subroutine.

assassin

  • Full Member
  • ***
  • Posts: 143
    • View Profile
    • My Barren Webpage
i would investigate the angle that XKeeper raised here:
https://tcrf.net/Talk:Super_Mario_All-Stars

anyway, if you think it's related to Y_Speed, then set breakpoints in the two games' BrickShatter routines, followed by setting write breakpoints on Y_Speed to see divergences in how it's modified going forward.

also known as:
You probably should set a write breakpoint to Y speed


June 10, 2020, 03:05:32 am - (Auto Merged - Double Posts are not allowed before 7 days.)
1) in the main GameEngine routine (aka "CODE_03AD8F"), "JSR CODE_03C084" has been moved down a little from the original "jsr BlockObjMT_Updater".  could be consequential, regardless of whether it's relevant to this issue, and it probably wasn't done lightly...

2) as far as trying to mimic the SMAS behavior in original SMB1: perhaps giving a larger negative Y Speed (e.g. FCh or F6h instead of FEh) in BrickShatter will overcome any version differences that hinder and then reverse upward velocity -- provided they're subtle enough -- and let the player continue upward momentarily?

----------

second update:

if i'm right on #1 being the cause of this, the most direct way to achieve SMAS functionality would be to move that function downward, after the two "jsr BlockObjectsCore"s.  you'd probably want to make sure that there were no side effects (e.g. variables BlockObjMT_Updater alters that BlockObjectsCore or its callers read from), or at least none in excess of what SMAS has.

if you're looking to be less invasive to current NES functionality (yet have more additional code and free space usage), i think that introducing a custom variable would be the best route:

- mark a Brick_was_smashed_last_interval in the BrickShatter routine, and clear it on regular intervals.  if NYSpd detects this variable is set, clear it, and abstain from setting Y Speed to 1.  so you're creating a loophole in behavior.  ideally, you'd verify that Mario's head is still at/in the broken brick before branching, so as to limit the size of the loophole, but i dunno how to do this.
-OR-
- have BlockObjectsCore (and maybe BrickShatter) instead set a Prepare_to_Set_Block_RepFlag , which BlockObjMT_Updater would then detect, clear, and if it was set, mark the actual Block_RepFlag and proceed as normal.  it'll then be handled on the NEXT call to the function.  the downside is that with this being an indexed variable, you'd need to create a custom one for each possible block, consuming a fair amount of RAM space.  unless you take advantage of the fact that Block_RepFlag is currently just 0 or 1, rework all existing modifications to operate on only Bit 0, and then claim one of the other bits for your custom flag.

anyway, it's worth verifying whether the reordering in GameEngine / CODE_03AD8F discussed in #1 is actually responsible for the brick physics difference before pursuing any of this. :P
« Last Edit: June 15, 2020, 01:11:48 pm by assassin »