Welcome to Data Crystal's new home! Data Crystal is now part of the TCRF family (sort of).
The wiki has recently moved; please report any issues in Discord. Pardon the dust.

Super Mario Bros. 3/Notes: Difference between revisions

From Data Crystal
Jump to navigation Jump to search
m (Fixed comment)
(Added what flight duration timer gets set to (80 hex, 128 decimal))
 
(13 intermediate revisions by 5 users not shown)
Line 1: Line 1:
=Disassembly notes=
{{notes|game=Super Mario Bros. 3}}
Various important bits of code follow below. Unless marked as "subroutine" you can NOT jump directly to these addresses, and even then there might be side effects.
=Disassembly/reverse engineering notes=
 
* NN: all values are hexadecimal and at least two digits (e.g. 0F, not F) unless noted otherwise.
* $NN or $NNNN: a memory address.
* Countdown timer: a byte in memory set to some value, decremented every frame and when it reaches 0 something is usually set up to happen. Many timers are cyclic, meaning that they are being re-set and reused immediately after reaching 0.


==Player physics/movement==
==Player physics/movement==
===Horizontal movement===
* If the player holds L/R the horizontal velocity $BD will start to increase (to-do: what's the exact increment?) at around 1 per frame. The same acceleration is always used when walking/running/dashing.
* abs($BD) can at most reach a limit that varies depending on things below.
* If WALKING, the limit is 18.
* If player holds B,
** The limit is raised to 28 and $BD is allowed to increase again. This is RUNNING.
** When abs($BD) is >= 28, you are DASHING and the P-timer $515 cycles from 7. Every time it elapses an arrow is added to the P-meter.
** When the P starts blinking, the player is in "flight mode":
*** 1) The limit is raised to 38 and $BD is allowed to increase again.
*** 2) The P-timer is LOCKED to the value 0F (don't know if the exact value has significance).
*** 3) Pressing A at this point launches the player into flight/super-jump, indicated by $57B being set to 1.
*** 4) The flight duration timer $56E is set to 80 and decrements every other frame.
** Player exits "flight-mode" ($57B = 0) when one of the following happens: (to-do: incomplete)
*** 1) Player touches ground.
*** 2) Flight-limit timer $56E elapses.
*** 3) Player lets go of the A button.
** Once no longer in "flight-mode", the P-timer $515 cycles from 23. Every time it elapses an arrow is removed from the P-meter.
** You can only refill the P-meter again by accelerating to abs($BD) >= 28 as above. (If $515 hasn't had time to elapse, i.e. the P-meter hasn't decreased, you can stay "eligible" for $57B flight-mode by doing short hops of flight and staying at >= 28.)


===$AC5A Jump power===
===$AC5A Jump power===
  $AC5A:A5 BD    LDA $00BD = #$34 ; Load player horz velocity
  $AC5A:A5 BD    LDA $00BD ; Load player horz velocity
  $AC5C:10 03    BPL $AC61 ; If negative,
  $AC5C:10 03    BPL $AC61 ; If negative,
  $AC5E:20 0F DD  JSR $DD0F ; take absolute value
  $AC5E:20 0F DD  JSR $DD0F ; take absolute value
Line 13: Line 36:
  $AC64:4A        LSR
  $AC64:4A        LSR
  $AC65:AA        TAX ; X = A, going to use it as an index
  $AC65:AA        TAX ; X = A, going to use it as an index
  $AC66:AD 47 A6  LDA $A647 = #$C8 ; Load default jump velocity
  $AC66:AD 47 A6  LDA $A647 ; Load default jump velocity
  $AC69:38        SEC
  $AC69:38        SEC
  $AC6A:FD 48 A6  SBC $A648,X @ $A64B = #$08 ; Subtract from the jump velocity (remember lower means more power) using the table 00,02,04,08.
  $AC6A:FD 48 A6  SBC $A648,X ; Subtract from the jump velocity (remember lower means more power) using the table 00,02,04,08.
  ; Thus a higher horizontal speed means a more powerful jump.
  ; Thus a higher horizontal speed means a more powerful jump.
  $AC6D:85 CF    STA $00CF = #$00 ; Store as new vertical velocity.
  $AC6D:85 CF    STA $00CF ; Store as new vertical velocity.


----
----
Line 23: Line 46:
===$ACA1 Application of gravity===
===$ACA1 Application of gravity===
  $ACA1:A0 05    LDY #$05 ; Y = default falling gravity
  $ACA1:A0 05    LDY #$05 ; Y = default falling gravity
  $ACA3:A5 CF    LDA $00CF = #$0D ; Load current vertical velocity
  $ACA3:A5 CF    LDA $00CF ; Load current vertical velocity
  $ACA5:C9 E0    CMP #$E0 ;  
  $ACA5:C9 E0    CMP #$E0 ;  
  $ACA7:10 0D    BPL $ACB6 ; If currently rising and v vel is still faster than E0,
  $ACA7:10 0D    BPL $ACB6 ; If currently rising and v vel is still faster than E0,
  $ACA9:AD 79 05  LDA $0579 = #$00 ; Don't know what 0579 is... unused? Debugger never sees a nonzero value.
  $ACA9:AD 79 05  LDA $0579 ; Don't know what 0579 is... unused? Debugger never sees a nonzero value.
  $ACAC:D0 0D    BNE $ACBB
  $ACAC:D0 0D    BNE $ACBB
  $ACAE:A5 17    LDA $0017 = #$00 ; Read gamepad. 80 is jump key, so value will appear negative!
  $ACAE:A5 17    LDA $0017 ; Read gamepad. 80 is jump key, so value will appear negative!
  $ACB0:10 04    BPL $ACB6 ; If jump pressed,
  $ACB0:10 04    BPL $ACB6 ; If jump pressed,
  $ACB2:A0 01    LDY #$01 ; Y = jump gravity (lower than normal)
  $ACB2:A0 01    LDY #$01 ; Y = jump gravity (lower than normal)
  $ACB4:D0 05    BNE $ACBB ;  
  $ACB4:D0 05    BNE $ACBB ;  
  $ACB6:A9 00    LDA #$00 ; This is run if jump key is NOT pressed
  $ACB6:A9 00    LDA #$00 ; This is run if jump key is NOT pressed
  $ACB8:8D 79 05  STA $0579 = #$00 ; So what does it do?  
  $ACB8:8D 79 05  STA $0579 ; So what does it do?  
  $ACBB:98        TYA ; A=Y
  $ACBB:98        TYA ; A=Y
  $ACBC:18        CLC ;
  $ACBC:18        CLC ;
  $ACBD:65 CF    ADC $00CF = #$0D ; Add gravity to current vertical velocity
  $ACBD:65 CF    ADC $00CF ; Add gravity to current vertical velocity
  $ACBF:85 CF    STA $00CF = #$0D ; And store back
  $ACBF:85 CF    STA $00CF ; And store back


So, jumps are aborted either by the user releasing the button (bit 7 in 0017 is zero) or the 00CF is more positive than E0. Since SOME gravity is always applied, this ensures jumps are aborted.
So, jumps are aborted either by the user releasing the button (bit 7 in 0017 is zero) or the 00CF is more positive than E0. Since SOME gravity is always applied, this ensures jumps are aborted.
Line 44: Line 67:


===$BFCC (Subroutine) Clamp Y velocity to the maximum===
===$BFCC (Subroutine) Clamp Y velocity to the maximum===
  $BFCC:A5 CF    LDA $00CF = #$05 ; Load current vertical velocity
  $BFCC:A5 CF    LDA $00CF ; Load current vertical velocity
  $BFCE:30 08    BMI $BFD8 ; Negative? Then skip clamping.
  $BFCE:30 08    BMI $BFD8 ; Negative? Then skip clamping.
  $BFD0:C9 40    CMP #$40 ; #$40 is the maximum fall vel (note: gravity is added afterwards so the effective value is 45)  
  $BFD0:C9 40    CMP #$40 ; #$40 is the maximum fall vel (note: gravity is added afterwards so the effective value is 45)  
  $BFD2:30 04    BMI $BFD8 ; Less than this? Then skip clamping.
  $BFD2:30 04    BMI $BFD8 ; Less than this? Then skip clamping.
  $BFD4:A9 40    LDA #$40 ; Replace $00CF with the maximum fall vel.
  $BFD4:A9 40    LDA #$40 ; Replace $00CF with the maximum fall vel.
  $BFD6:85 CF    STA $00CF = #$05
  $BFD6:85 CF    STA $00CF
  $BFD8:A2 12    LDX #$12 ; UNKNOWN
  $BFD8:A2 12    LDX #$12 ; UNKNOWN
  $BFDA:20 93 BF  JSR $BF93 ; UNKNOWN
  $BFDA:20 93 BF  JSR $BF93 ; UNKNOWN
  $BFDD:60        RTS
  $BFDD:60        RTS
{{Internal Data|game=Super Mario Bros. 3}}

Latest revision as of 22:59, 18 May 2024

Chip tiny.png The following article is a Notes Page for Super Mario Bros. 3.

Disassembly/reverse engineering notes

  • NN: all values are hexadecimal and at least two digits (e.g. 0F, not F) unless noted otherwise.
  • $NN or $NNNN: a memory address.
  • Countdown timer: a byte in memory set to some value, decremented every frame and when it reaches 0 something is usually set up to happen. Many timers are cyclic, meaning that they are being re-set and reused immediately after reaching 0.

Player physics/movement

Horizontal movement

  • If the player holds L/R the horizontal velocity $BD will start to increase (to-do: what's the exact increment?) at around 1 per frame. The same acceleration is always used when walking/running/dashing.
  • abs($BD) can at most reach a limit that varies depending on things below.
  • If WALKING, the limit is 18.
  • If player holds B,
    • The limit is raised to 28 and $BD is allowed to increase again. This is RUNNING.
    • When abs($BD) is >= 28, you are DASHING and the P-timer $515 cycles from 7. Every time it elapses an arrow is added to the P-meter.
    • When the P starts blinking, the player is in "flight mode":
      • 1) The limit is raised to 38 and $BD is allowed to increase again.
      • 2) The P-timer is LOCKED to the value 0F (don't know if the exact value has significance).
      • 3) Pressing A at this point launches the player into flight/super-jump, indicated by $57B being set to 1.
      • 4) The flight duration timer $56E is set to 80 and decrements every other frame.
    • Player exits "flight-mode" ($57B = 0) when one of the following happens: (to-do: incomplete)
      • 1) Player touches ground.
      • 2) Flight-limit timer $56E elapses.
      • 3) Player lets go of the A button.
    • Once no longer in "flight-mode", the P-timer $515 cycles from 23. Every time it elapses an arrow is removed from the P-meter.
    • You can only refill the P-meter again by accelerating to abs($BD) >= 28 as above. (If $515 hasn't had time to elapse, i.e. the P-meter hasn't decreased, you can stay "eligible" for $57B flight-mode by doing short hops of flight and staying at >= 28.)

$AC5A Jump power

$AC5A:A5 BD     LDA $00BD			; Load player horz velocity
$AC5C:10 03     BPL $AC61			; If negative,
$AC5E:20 0F DD  JSR $DD0F			; 	take absolute value
$AC61:4A        LSR				; Divide by 16
$AC62:4A        LSR
$AC63:4A        LSR
$AC64:4A        LSR
$AC65:AA        TAX				; X = A, going to use it as an index
$AC66:AD 47 A6  LDA $A647			; Load default jump velocity
$AC69:38        SEC				
$AC6A:FD 48 A6  SBC $A648,X			; Subtract from the jump velocity (remember lower means more power) using the table 00,02,04,08.
						; Thus a higher horizontal speed means a more powerful jump.
$AC6D:85 CF     STA $00CF			; Store as new vertical velocity.

$ACA1 Application of gravity

$ACA1:A0 05     LDY #$05		; Y = default falling gravity
$ACA3:A5 CF     LDA $00CF		; Load current vertical velocity
$ACA5:C9 E0     CMP #$E0		; 
$ACA7:10 0D     BPL $ACB6		; If currently rising and v vel is still faster than E0,
$ACA9:AD 79 05  LDA $0579		; 	Don't know what 0579 is... unused? Debugger never sees a nonzero value.
$ACAC:D0 0D     BNE $ACBB
$ACAE:A5 17     LDA $0017		; 	Read gamepad. 80 is jump key, so value will appear negative!
$ACB0:10 04     BPL $ACB6		; 	If jump pressed,
$ACB2:A0 01     LDY #$01		; 		Y = jump gravity (lower than normal)
$ACB4:D0 05     BNE $ACBB		; 
$ACB6:A9 00     LDA #$00		; This is run if jump key is NOT pressed
$ACB8:8D 79 05  STA $0579		; 	So what does it do? 
$ACBB:98        TYA			; A=Y
$ACBC:18        CLC			;
$ACBD:65 CF     ADC $00CF		; Add gravity to current vertical velocity
$ACBF:85 CF     STA $00CF		; And store back

So, jumps are aborted either by the user releasing the button (bit 7 in 0017 is zero) or the 00CF is more positive than E0. Since SOME gravity is always applied, this ensures jumps are aborted.


$BFCC (Subroutine) Clamp Y velocity to the maximum

$BFCC:A5 CF     LDA $00CF			; Load current vertical velocity
$BFCE:30 08     BMI $BFD8			; Negative? Then skip clamping.
$BFD0:C9 40     CMP #$40			; #$40 is the maximum fall vel (note: gravity is added afterwards so the effective value is 45) 
$BFD2:30 04     BMI $BFD8			; Less than this? Then skip clamping.
$BFD4:A9 40     LDA #$40			; Replace $00CF with the maximum fall vel.
$BFD6:85 CF     STA $00CF
$BFD8:A2 12     LDX #$12			; UNKNOWN
$BFDA:20 93 BF  JSR $BF93			; UNKNOWN	
$BFDD:60        RTS