MAMEWorld >> EmuChat
View all threads Index   Flat Mode Flat  

Rotwang
Life is too short to be little...
Reged: 03/21/17
Posts: 109
Send PM
Re: Digging into the secrets of SFII: Rainbow Edition (Fireballs)
01/12/21 08:24 AM


> Documented in MAME:
> https://github.com/mamedev/mame/commit/c51c7e743c0b62015c2d45bfe3a2bb695451bc3d

Thank you for adding this. I'm glad this research, however esoteric it may be, contributed in some way to Mame. While you're labeling dip switches, however...

New entry in what I hope will be an ongoing series:

This is the instruction in the original code that was overwritten with a jump to sf2rb's turbo mode.


Code:


000C86 btst #$0, ($88, A5) ; Test dip switch C1



Normally when a hack overwrites an instruction like this in order to hijack the program, the original behavior is replicated somewhere in the destination. However this instruction does not appear anywhere in sf2rb's new turbo code. So what does it do? It tests dip switch 1 on bank C. This switch is unused according to sf2ce's original manual. Here, however, it comes after a test of a byte in RAM at $FF82DE. I'm not entirely sure what this address does, but setting it to a non zero value forces the game into test mode. When you access test mode via the service button, this byte is not set. However, if somehow this byte gets set and undocumented switch C1 is set, you will enter test mode with sf2ce's built in turbo mode on full blast. Obviously a leftover debug feature, but I'm unsure what purpose it fulfilled.

This trivia segues nicely into the next difference between sf2rb and the original game. The hackers didn't just omit that instruction in the turbo code because it was an obsolete debug feature, but because they utilized dip switch C1 to toggle between two different fireball modes. When switch C1 is off, any fireballs you throw will home in on your opponent and track them, even if they try to jump out of the way. When switch C1 is on, fireballs will move in a consistent zigzag pattern along the ground. So how does it work?

The fireball handler in sf2ce calls subroutine $2302 to apply the fireball's movement on each frame. At this point in the code, address register A0 contains a pointer to an entry on a table of signed values to be added to the fireball's x and y positions, driving it across the screen. Fireballs are not the only entities to use this directional movement subroutine, however. Other entities that need to travel a specific distance in a specific direction, such as the airplane on the world map, also use this subroutine and table.

So when our intrepid hackers decided to change the way fireballs move in sf2rb, what did they do? They did what any sensible person would do and created a whole bunch of nested comparisons to figure out which kind of fireball was moving around on the screen.


Code:


rb_fireballs:
0E5216 btst #$0, ($88,A5) ; Test Dip C1
0E521C bne rb_fireballs_swc1_set ; Branch to zigzag fireball code if set
0E5220 movem.l D1-D3/A2, -(A7)
0E5224 move.w (-$6ed0,A5), D3 ; $FF1130. This is a counter that
; resets every time a new fireball
; is made. This controls the delayed
; speed increases of certain fireballs.
0E5228 move.w #$100, D2 ; fireball horizontal speed (xpos mod)
0E522C cmpa.l #$10f038, A0 ; A0 contains pointer to original game's
; fireball speed tables. This code is
; trying to figure out what kind of
; fireball this is by comparing A0 to
; known fireball types. They did not
; include a check for Sagat's fast tiger
; shot ($10F07A)
; it has no special behavior applied,
; and is now slower than the medium
; tiger shot.
;
; $10F038 = Slow hadoken/sonic boom/tiger shot/yoga fire, Right facing
0E5232 beq rb_fireballs_homing_movecalc
0E5236 cmpa.l #$10f048, A0 ; $10F048 = Medium hadoken/sonic boom/tiger, Right facing
0E523C bne rb_fireballs_homing_movecalc_tryfast
0E5240 cmpi.w #$10, D3 ; Keep slow speed for #$10 frames
0E5244 bls rb_fireballs_homing_movecalc
0E5248 move.w #$800, D2 ; Then go 8x faster
0E524C bra rb_fireballs_homing_movecalc

rb_fireballs_homing_movecalc_tryfast:
0E5250 cmpa.l #$10f05c, A0 ; $10F05C = Medium tiger shot, Fast hadoken/yoga fire/sonic boom, Right facing
0E5256 bne rb_fireballs_homing_movecalc_leftfacing ; Test all left facing fireballs if none of the right facing ones
0E525A cmpi.w #$4, D3 ; Keep slow speed for 4 frames
0E525E bls rb_fireballs_homing_movecalc
0E5262 move.w #$1000, D2 ; Then go 16x faster
0E5266 bra rb_fireballs_homing_movecalc

rb_fireballs_homing_movecalc_leftfacing
0E526A move.w #$ff00, D2
0E526E cmpa.l #$10f03c, A0 ; $10F03C = Slow hadoken/tiger shot/yoga fire/sonic boom, Left facing
0E5274 beq rb_fireballs_homing_movecalc
0E5278 cmpa.l #$10f04c, A0 ; $10F04C = Medium hadoken/yoga fire/sonic boom, left facing
0E527E bne rb_fireballs_homing_movecalc_leftfacing_tryfast
0E5282 cmpi.w #$10, D3 ; Keep slow speed for #$10 frames
0E5286 bls rb_fireballs_homing_movecalc
0E528A move.w #$f800, D2 ; Then go 8x faster
0E528E bra rb_fireballs_homing_movecalc

rb_fireballs_homing_movecalc_leftfacing_tryfast:
0E5292 cmpa.l #$10f060, A0 ; $10F060 = Medium tiger shot, Fast hadoken/yoga fire/sonic boom, left facing
0E5298 bne rb_fireballs_homing_normalmove
0E529C cmpi.w #$4, D3 ; Keep slow speed for 4 frames
0E52A0 bls rb_fireballs_homing_movecalc
0E52A4 move.w #$f000, D2 ; Then go 16x faster
0E52A8 bra rb_fireballs_homing_movecalc

rb_fireballs_homing_normalmove:
0E52AC move.w (A0)+, D0 ; Same fireball movement code
; as unmodified game. This is
; a copy of the code that was
; overwritten by the hijack.
;
; Any projectiles or other
; entities not caught by the
; above comparisons will wind
; up here.
0E52AE ext.l D0
0E52B0 asl.l #8, D0
0E52B2 add.l D0, ($6,A6) ; Write Xpos
0E52B6 move.w (A0), D0
0E52B8 ext.l D0
0E52BA asl.l #8, D0
0E52BC add.l D0, ($a,A6) ; Write Ypos
0E52C0 movem.l (A7)+, D1-D3/A2
0E52C4 rts

rb_fireballs_homing_movecalc:
0E52C6 move.w ($a,A2), D1 ; Opponent's Y-pos
0E52CA addi.w #$30, D1
0E52CE move.w ($a,A6), D0 ; Fireball's Y-pos
0E52D2 cmp.w D1, D0
0E52D4 blt rb_fireballs_homing_moveup ; Projectile's Ypos < Opponent's
0E52D8 bhi rb_fireballs_homing_movedown ; Projectile's Ypos > Opponent's
0E52DC bra rb_fireballs_homing_applymove ; Projectile's Ypos == Opponent's

rb_fireballs_homing_moveup:
0E52E0 addq.w #2, D0
0E52E2 bra rb_fireballs_zigzag_apply ; Use the zigzag apply movement code.
; This code does not increment the
; delayed speed counter, so if a fireball
; is thrown at an enemy who is higher in
; the air, the fireball will stay slow
; until their heights are equal or
; greater.

rb_fireballs_homing_movedown:
0E52E6 subq.w #2, D0

rb_fireballs_homing_applymove:
0E52E8 move.w D0, ($a,A6) ; Write projectile ypos
0E52EC move.w D2, D0
0E52EE ext.l D0
0E52F0 asl.l #8, D0
0E52F2 add.l D0, ($6,A6) ; Write projectile xpos
0E52F6 addq.w #1, (-$6ed0,A5) ; increment delayed speed counter
0E52FA movem.l (A7)+, D1-D3/A2
0E52FE rts

rb_fireballs_swc1_set:
0E5300 movem.l D1-D3/A2, -(A7) ; Fireballs move in a zigzag pattern.
; Tests same pointers as with homing fireballs.
; Fast tiger shot is also missed in this code.
0E5304 move.w #$100, D2
0E5308 cmpa.l #$10f038, A0 ; $10F038 = Slow hadoken/sonic boom/tiger shot/yoga fire, Right facing
0E530E beq rb_fireballs_zigzag_findslot
0E5312 cmpa.l #$10f048, A0 ; $10F048 = Medium hadoken/sonic boom/tiger, Right facing
0E5318 bne rb_fireballs_zigzag_findslot_tryfast
0E531C move.w #$600, D2 ; Not as much of a speed increase as homing fireball
0E5320 bra rb_fireballs_zigzag_findslot

rb_fireballs_zigzag_findslot_tryfast:
0E5324 cmpa.l #$10f05c, A0 ; $10F05C = Medium tiger shot, Fast hadoken/yoga fire/sonic boom, Right facing
0E532A bne rb_fireballs_zigzag_findslot_leftfacing
0E532E move.w #$a00, D2 ; Again, not as much of a speed increase
0E5332 bra rb_fireballs_zigzag_findslot

rb_fireballs_zigzag_findslot_leftfacing:
0E5336 move.w #$ff00, D2
0E533A cmpa.l #$10f03c, A0 ; $10F03C = Slow hadoken/tiger shot/yoga fire/sonic boom, Left facing
0E5340 beq rb_fireballs_zigzag_findslot
0E5344 cmpa.l #$10f04c, A0 ; $10F04C = Medium hadoken/yoga fire/sonic boom, left facing
0E534A bne rb_fireballs_zigzag_findslot_leftfacing_tryfast
0E534E move.w #$fa00, D2
0E5352 bra rb_fireballs_zigzag_findslot

rb_fireballs_zigzag_findslot_leftfacing_tryfast:
0E5356 cmpa.l #$10f060, A0 ; $10F060 = Medium tiger shot, Fast hadoken/yoga fire/sonic boom, left facing
0E535C bne rb_fireballs_zigzag_normalmove
0E5360 move.w #$f600, D2
0E5364 bra rb_fireballs_zigzag_findslot

rb_fireballs_zigzag_normalmove:
0E5368 move.w (A0)+, D0 ; Duplicate of rb_fireballs_homing_normalmove
0E536A ext.l D0
0E536C asl.l #8, D0
0E536E add.l D0, ($6,A6) ; Write Xpos
0E5372 move.w (A0), D0
0E5374 ext.l D0
0E5376 asl.l #8, D0
0E5378 add.l D0, ($a,A6) ; Write Ypos
0E537C movem.l (A7)+, D1-D3/A2
0E5380 rts

rb_fireballs_zigzag_findslot_findslot:
0E5382 move.w #$98b6, D1 ; Base address of last fireball RAM slot
0E5386 move.w #$0, D3

rb_fireballs_zigzag_findslot_findslot_loop:
0E538A cmp.w A6, D1 ; Cycles through the projectile RAM slots
; to match one with the current entity.
0E538C beq rb_fireballs_zigzag_slotfound
0E5390 subi.w #$c0, D1 ; Subtract length of a fireball RAM slot
; to test on next pass of loop
0E5394 addq.w #2, D3 ; All this loop does is find the numerical
; position of this fireball RAM slot.
0E5396 cmpi.w #$12, D3
0E539A blt rb_fireballs_zigzag_findslot_findslot_loop

rb_fireballs_zigzag_slotfound:
0E539C move.w ($a,A6), D0 ; Fireball's ypos
0E53A0 lea $ff1a10.l, A2 ; table of fireball zigzag direction switches.
; 1 = up, 2 = down
; Word length entries for some reason.
0E53A6 adda.w D3, A2 ; Offset for this projectile slot
0E53A8 move.w (A2), D3
0E53AA tst.w D3
0E53AC bne rb_fireballs_zigzag_directioncalc
0E53B0 move.w #$1, D3 ; if empty, init with 1 (move up)
0E53B4 move.b ($1c,A5), D1 ; load frame counter
0E53B8 andi.w #$1, D1 ; mask for alternating frames
0E53BC add.w D1, D3 ; On an odd frame, fireball begins by moving down
0E53BE move.w D3, (A2) ; Store to direction table

rb_fireballs_zigzag_directioncalc:
0E53C0 cmpi.w #$1, D3 ; Comparison determines if fireball goes up or down
0E53C4 bne rb_fireballs_zigzag_movedown
0E53C8 addq.w #4, D0 ; Add 4 to ypos
0E53CA cmpi.w #$90, D0 ; Switch to downward movement if above #$90
0E53CE bls rb_fireballs_zigzag_apply
0E53D2 move.w #$2, (A2) ; Switch to downward direction
0E53D6 bra rb_fireballs_zigzag_apply

rb_fireballs_zigzag_movedown:
0E53DA subq.w #4, D0 ; Subtract 4 from ypos
0E53DC cmpi.w #$30, D0 ; Switch to upward movement if below #$30
0E53E0 bgt rb_fireballs_zigzag_apply
0E53E4 move.w #$1, (A2) ; Switch to upward direction
0E53E8 bra rb_fireballs_zigzag_apply

rb_fireballs_zigzag_apply:
0E53EC move.w D0, ($a,A6) ; Apply ypos
0E53F0 move.w D2, D0
0E53F2 ext.l D0
0E53F4 asl.l #8, D0
0E53F6 add.l D0, ($6,A6) ; Apply xpos
0E53FA movem.l (A7)+, D1-D3/A2
0E53FE rts



Hopefully the comments speak for themselves. I will summarize the main takeaways.

- Fast tiger shots are NOT affected by either of the new fireball code due to an oversight by the hackers. They will simply fly straight across the screen at the same speed as always, and will not track the opponent or zigzag around. They now travel slower than a medium tiger shot.
- Medium and fast homing fireballs have a brief delay at their start before picking up speed while slow fireballs stay slow for their entire duration.
- If a homing fireball is thrown at an enemy who is higher in the air than the fireball, it will not pick up speed until it is at least at level height with the enemy.
- Zigzag fireballs will begin angled up on even frames and angled down on odd frames.
- Zigzag fireballs will not stay high up in the air if you throw one while jumping. They always seek out the same distances from the ground every time.


Code:


DIP SWITCH BANK C 1
==========================
PROJECTILE TYPE |
----------------|
Homing | OFF
Zigzag | ON



Edited by Rotwang (01/14/21 08:39 PM)







Entire thread
Subject Posted by Posted on
* Digging into the secrets of SFII: Rainbow Edition Rotwang 01/01/21 08:41 PM
. * Re: Secrets of SFII' Rainbow (CPU opponents, in-air moves, title colors) Rotwang  01/28/21 08:48 PM
. * Re: Digging into the secrets of SFII: Rainbow Edition fortuna_chan  01/13/21 09:25 PM
. * Re: Digging into the secrets of SFII: Rainbow Edition Rotwang  01/14/21 05:07 AM
. * Re: Digging into the secrets of SFII: Rainbow Edition fortuna_chan  01/14/21 11:58 PM
. * Re: Digging into the secrets of SFII: Rainbow Edition Vas Crabb  01/11/21 06:41 PM
. * Re: Digging into the secrets of SFII: Rainbow Edition (Fireballs) Rotwang  01/12/21 08:24 AM
. * Re: Digging into the secrets of SFII: Rainbow Edition (Fireballs) Vas Crabb  01/12/21 10:32 AM
. * Re: Digging into the secrets of SFII: Rainbow Edition (Fireballs) CiroConsentino  01/14/21 01:02 PM
. * Re: Digging into the secrets of SFII: Rainbow Edition Vas Crabb  01/02/21 05:33 AM
. * Re: Digging into the secrets of SFII: Rainbow Edition Rotwang  01/02/21 10:06 PM
. * Re: Digging into the secrets of SFII: Rainbow Edition Haze  01/02/21 10:24 PM
. * Re: Digging into the secrets of SFII: Rainbow Edition Rotwang  01/03/21 07:37 AM
. * Re: Digging into the secrets of SFII: Rainbow Edition RobbbertModerator  01/05/21 01:07 PM

Extra information Permissions
Moderator:  Robbbert, Tafoid 
1 registered and 353 anonymous users are browsing this forum.
You cannot start new topics
You cannot reply to topics
HTML is enabled
UBBCode is enabled
Thread views: 1199