Sonic 1 has no spin dash; standing on the ground, Sonic_MdNormal checks only for a jump, the slope, the d-pad, and a roll. | s2.asm L36514–36515 | Code |
Sonic_Jump takes off at $680 subpixels per frame (6.5 px/frame), $800 as Super Sonic, and $380 underwater, the same take-off as Sonic 1. | s2.asm L37400–37407s2.asm L37409–37418 | Code |
ObjectMoveAndFall adds $38 subpixels/frame to Sonic's downward speed each airborne frame, and underwater the air modes take $28 back, leaving $10. | s2.asm L30216–30217s2.asm L36575–36582 | Code |
With no jump button held, Sonic_JumpHeight cuts a rise faster than 4 px/frame to exactly -$400 (-$200 underwater), as in Sonic 1. | s2.asm L37465–37475 | Code |
Obj01_Init sets Sonic's top speed to $600, his acceleration to $C, and his deceleration to $80 subpixels, Sonic 1's values; speed shoes and Super Sonic swap in others. | s2.asm L36232–36234s2.asm L36364–36366 | Code |
Holding forward no longer pulls a faster Sonic down to the top speed on the ground; Sonic_MoveRight undoes the frame's acceleration and keeps the speed he had. | s2.asm L36998–37004 | Code |
In the air Sonic_ChgJumpDir adds twice the acceleration, $18, either way and still caps at the top speed even when Sonic was already faster, as Sonic 1 does. | s2.asm L37204–37228 | Code |
Sonic 2 keeps Sonic 1's air drag; Sonic_JumpPeakDecelerate is instruction for instruction Sonic 1's Sonic_AirDrag, taking X speed shifted right 5 bits while Y speed is from −$400 to −1. | s2.asm L37241–37264 | Code |
Sonic 2 has no grace window after a ledge: only the grounded modes, Obj01_MdNormal and Obj01_MdRoll, call Sonic_Jump. | s2.asm L36514–36516s2.asm L36556–36559s2.asm L36539–36543 | Code |
The spin dash starts when a jump button is pressed while Sonic shows his ducking animation; Sonic_CheckSpindash runs before Sonic_Jump and skips the rest of the frame. | s2.asm L37600–37613 | Code |
Each jump press while charging adds $200 to the spin dash counter, capped at $800, and each frame the counter loses 1/32 of itself. | s2.asm L37711–37729 | Code |
Releasing Down sets Sonic's ground speed from the counter's high byte, $800 plus $80 a step, from 8 px/frame uncharged to 12 at full charge (Super Sonic $B00 to $F00). | s2.asm L37633–37647s2.asm L37688–37708 | Code |
On a slope Sonic's ground speed gains the sine of the angle times $20 a frame while he runs and $50 while he rolls downhill (a quarter of that uphill), with nothing while he stands; the code matches Sonic 1's. | s2.asm L37754–37768s2.asm L37787–37803 | Code |
On a wall or ceiling below $280 (2.5 px/frame) ground speed, Sonic_SlopeRepel zeroes the speed, drops Sonic off, and locks the d-pad for 30 frames, as in Sonic 1. | s2.asm L37832–37841 | Code |
Rolling, Sonic slows by half his acceleration ($6) a frame, by $20 more against the d-pad, and his X speed is clamped to $1000 (16 px/frame). | s2.asm L37057–37059s2.asm L37137–37143 | Code |
Sonic curls into a roll when Down is held without Left or Right and his ground speed is at least $80 either way, as in Sonic 1. | s2.asm L37345–37352 | Code |
A hit throws Sonic up at -$400 and away from the object at $200 (half both underwater), and the hurt routine's gravity is $30. | s2.asm L85677–85690s2.asm L38222–38223 | Code |
A hit sets invulnerable_time to $78 (120) and landing sets it to 120 again; it counts down only in the control routine, so Sonic has 120 frames of blinking invulnerability after he lands. | s2.asm L85696s2.asm L38262–38271s2.asm L36325–36330s2.asm L85633–85636 | Code |
| Hit without a shield, Sonic drops his rings, at most 32 of them as bouncing rings, and the count goes to 0; with no rings he dies. | s2.asm L85650–85664s2.asm L25178–25181s2.asm L25240–25243 | Code |
Sonic 2's one shield takes a hit in place of the rings; HurtCharacter skips the ring drop, clears the shield, and knocks Sonic back as usual. | s2.asm L85658–85678 | Code |
| Against objects Sonic is a 16 px wide box whose half-height is his height radius minus 3: 32 px tall standing, 22 px curled up. | s2.asm L85229–85250s2.asm L36226–36227 | Code |
In the No-Intro Sonic The Hedgehog 2 (World) (Rev B) ROM, Sonic's object (Obj01) is the code s2disasm builds with gameRevision = 2, item for item, apart from absolute addresses, RAM variables at other addresses, branch displacements, and offset table entries, and less one jump table entry the build has after Sonic_HurtStop; the collision routines it calls (AnglePos up to Obj79), CalcSine and CalcAngle with their tables, ObjectMoveAndFall, ObjectMove, and ReadJoypads are that build's bytes. The build as a whole is not this ROM byte for byte. | s2.asm L20s2.asm L40s2.asm L38274–38280 | Code |
A frame-by-frame model of Obj01_MdNormal_Checks, Obj01_MdNormal, Obj01_MdRoll, and the air modes, with Sonic_Animate's timing for the standing and blinking animations, matches Sonic the Hedgehog 2 itself, run in MAME with Sonic alone on a floor built of Emerald Hill Act 1's blocks, on every frame of the movement lab's flat-ground presets, eleven scripts of Sonic 2's own moves, and 100 random input scripts. | s2.asm L36280–36305s2.asm L36488–36582s2.asm L36515–36519s2.asm L36596–37046s2.asm L37054–37270s2.asm L37342–37490s2.asm L37600–37743s2.asm L37934–38200s2.asm L1381–1386 | Verified |
| On stages built in Emerald Hill Act 1 from the act's full flat 16 × 16 block, solid on the collision path Sonic starts on, the movement lab's Sonic 2 model matches Sonic the Hedgehog 2 itself, run in MAME, on every frame of 100 random stages with random input scripts, three in four with floating blocks, and of the lab's stage presets, until a fall into a pit kills him at the bottom boundary or he nears the end of the built floor. | s2.asm L43051–43186s2.asm L43459–43530s2.asm L43476–43477s2.asm L43990–44235s2.asm L44371–44575s2.asm L37934–38200 | Verified |
Sonic dies once his Y position is more than 224 px below the camera's bottom boundary, checked by Sonic_LevelBound before each move, as in Sonic 1, but with fixBugs off Sonic 2 checks the boundary where it is (Camera_Max_Y_pos) and Sonic 1 the target it's moving to. In Emerald Hill Act 1, run in MAME, each of 18 falls into a pit killed him on the first frame after his center passed row 1024. | s2.asm L37299–37315s2.asm L37317–37323 | Verified |
With neither Left nor Right held and the sliding status clear, a standing Sonic's ground speed moves 12 ($C, his acceleration) toward 0 each frame and stops at 0, as in Sonic 1; while sliding, Sonic_Move goes straight to Obj01_Traction, with no d-pad and no friction. | s2.asm L36826–36834s2.asm L36600–36603 | Code |
Turning against his motion on flat ground, Sonic skids (the stopping animation, still facing his old direction of motion) when his ground speed before the turning step is at least $480 going right or $381 going left, as in Sonic 1: the angle check overwrites the low byte of the speed it then compares. | s2.asm L36966–36974s2.asm L37031–37035 | Code |
Sonic's level collision radii are 9 × 19 px standing and 7 × 14 curled, set by Obj01_Init, the jump, the roll, and the spin dash, and his wall sensors sit 10 px from his center: Sonic 1's sizes. | s2.asm L36226–36227s2.asm L37436–37440s2.asm L44375–44376s2.asm L44566–44567 | Code |
Sonic 2's level collision is 16 × 16 px blocks whose layout words carry solidity bits for two collision paths; Sonic starts on the first, testing bit $C for floors and $D for walls and ceilings. As in Sonic 1, each search looks in the sensor's block and at most one more. | s2.asm L36239–36240s2.asm L43459–43472s2.asm L43474–43479s2.asm L37934–37940 | Code |
On flat ground and not on an object, after each ground move AnglePos sets both angle buffers to 3, then reads two floor sensors at his feet, X ± his width radius, each writing its buffer when it meets a block; the nearer distance counts, and a floor up to 14 px above his feet lifts him onto it. Standing on an object, it sets both buffers to 0 and reads no sensors; on a wall or a ceiling it turns the sensors to match (Sonic_WalkVertL, Sonic_WalkCeiling, Sonic_WalkVertR). | s2.asm L43058–43067s2.asm L43087–43093s2.asm L43094–43106s2.asm L43122–43129s2.asm L43166–43172 | Code |
When both floor sensors are above the floor after a ground move, AnglePos moves Sonic down onto it if it's within his X speed's whole pixels plus 4, at most 14; any farther and he's in the air. Sonic 1 reaches down 14 px at every speed. | s2.asm L43135–43156 | Code |
On the ground, the wall check looks from where this frame's X speed will put him, 10 px ahead of his center and 8 px below it on flat ground, as in Sonic 1 (whose 10 px is sonic_quick_size). | s2.asm L43997–44012s2.asm L44031–44036 | Code |
| On the ground with nonzero ground speed, a wall found ahead (the sensor of wall-sensors inside a block) cuts this frame's X speed so he stops beside it, and sets his ground speed to 0, as in Sonic 1. | s2.asm L36886–36890s2.asm L36899–36901 | Code |
In the air Sonic_DoLevelCollision picks one of four checks by the direction of his speed: CalcAngle of X and Y speed less $20, to a quarter, as in Sonic 1, with the same angle table. | s2.asm L37941–37951s2.asm L4049–4060 | Code |
| In the air, a wall sensor 10 px from his center inside a block pushes Sonic out by whole pixels and sets his X speed to 0; moving mostly sideways, that ends the frame's checks, as in Sonic 1. | s2.asm L37952–37962s2.asm L38012–38019 | Code |
Falling mostly down, Sonic lands only if one floor sensor is no deeper in the floor than his Y speed's whole pixels plus 8, as in Sonic 1; moving mostly sideways he lands at any depth while not rising, with fixBugs off. | s2.asm L37964–37977s2.asm L38035–38040s2.asm L38058–38061 | Code |
| Moving mostly up, a head sensor inside a block moves Sonic down out of it and sets his Y speed to 0 on a flat ceiling; moving mostly sideways it moves him down and stops a rise, and skips the floor check that frame, as in Sonic 1. | s2.asm L38023–38033s2.asm L38081–38091 | Code |
| On the ground nothing checks above Sonic except a jump press; standing or rolling into a block's underside leaves him inside it, as in Sonic 1. | s2.asm L36515–36527s2.asm L36557–36565 | Code |
A jump press jumps only if both head sensors find 6 px or more of room above his head, as in Sonic 1; the check writes $80 to both angle buffers first. | s2.asm L37394–37399s2.asm L44061–44066 | Code |
Standing on flat ground, not on an object, not sliding, and with d-pad control (move_lock 0), with ground speed 0 after the left and right steps and the floor under his center 12 px or more below his feet, Sonic balances on the side whose floor sensor met no block last frame (the right first). He turns to face that side only when he faces away from it and the floor 6 px back from his center is also 12 px or more below; Sonic 1 turns him at any such edge. | s2.asm L36600–36603s2.asm L36614–36623s2.asm L36698–36724s2.asm L36727–36748s2.asm L36297–36298 | Code |
| A jump adds nothing to Sonic's X speed on flat ground, and the rest of that frame's mode (the move and the floor snap) doesn't run, as in Sonic 1. | s2.asm L37409–37421 | Code |
A jump from a roll sets the roll-jump flag, and while it's set Sonic_ChgJumpDir skips the d-pad, as in Sonic 1; the drag near the top of the jump still applies. | s2.asm L37434–37435s2.asm L37446–37447s2.asm L37207–37208 | Code |
With fixBugs off, a jump sets the standing collision radii before checking for a roll, so a roll jump keeps them while curled, and lands 5 px early; landing then lifts his center 5 px more, as in Sonic 1. | s2.asm L37426–37440s2.asm L38179–38185 | Code |
| Landing on flat ground sets his ground speed to his X speed and his Y speed to 0, and clears the jump, roll-jump, and in-air flags, as in Sonic 1; out of pinball mode it also uncurls him (the standing radii, his center 5 px up), as Sonic 1 always does. | s2.asm L37975–37977s2.asm L37990–37993s2.asm L38168–38171s2.asm L38179–38185s2.asm L38187–38191 | Code |
Letting go of Down while charging curls Sonic (Y + 5), sets his ground speed from the counter's high byte (spindash-speeds, or SpindashSpeedsSuper as Super Sonic), negated facing left, and ends the frame after the floor snap with his X speed unchanged, so he starts moving the next frame. | s2.asm L37633–37647s2.asm L37648–37651s2.asm L37677–37685s2.asm L37732–37743 | Code |
| After Sonic has stood in his waiting animation to its 30th frame (about 175 frames), each frame with nothing held skips his movement, and the first frame with the d-pad or a jump button held but no jump press only starts a blink, which skips two more frames; from its 172nd frame he gets up instead, which skips five frames in all. | s2.asm L36493–36511s2.asm L36531–36533s2.asm L38769–38771s2.asm L38747–38759s2.asm L38432–38461 | Code |
| Sonic 2's movement on flat ground is Sonic 1's with five changes: the spin dash, a ground speed above the top kept while forward is held, a blink after standing that skips up to five frames of input, balancing that turns him only when he's far over the edge, and a floor snap that reaches down his X speed's whole pixels plus 4 rather than 14 px. | s2.asm L36515–36519s2.asm L43135–43143 | Code |
MoveSprite adds $38 subpixels/frame to a falling player's speed, Sonic 1's and Sonic 2's gravity, and underwater the air modes take $28 back. | s2.asm L30217 | Code |
Sonic_Init sets the top speed to $600, the acceleration to $C, and the deceleration to $80 subpixels, the values of Sonic 1 and Sonic 2. | s2.asm L36232–36234s2.asm L36998–37004 | Code |
In the air Sonic_ChgJumpDir still adds $18 a frame, but a Sonic already faster than the top speed keeps his speed; Sonic 1 and Sonic 2 pulled him down to it. | s2.asm L37214–37219 | Code |
The spin dash is Sonic 2's, with the same $200 a press to $800, the same 1/32 decay, and the same release speeds from $800 to $C00. | s2.asm L37688–37697s2.asm L37714–37729 | Code |
Unlike Sonic 1 and Sonic 2, a standing player slides on a slope whose push, sine × $20, is at least $D; the walking and rolling factors stay $20 and $50. | s2.asm L37763–37764 | Code |
Below $280 ground speed on a steep slope the player now slips, a $80 push along the slope and a 30-frame d-pad lock, and falls off only near walls and ceilings; Sonic 1 and 2 dropped him from any slope past 45°. | s2.asm L37832–37841 | Code |
Rolling keeps Sonic 2's numbers, friction of half the acceleration ($6), $20 more against the d-pad, and X speed clamped to $1000. | s2.asm L37057–37059s2.asm L37137–37139 | Code |
| Against objects the player is still a 16 px wide box whose half-height is his height radius minus 3, and ducking no longer shrinks it. | s2.asm L85229–85250 | Code |
A hit throws the player up at -$400 and away from the object at $200 (half both underwater), the speeds of Sonic 1 and Sonic 2. | s2.asm L85678–85679 | Code |
| The invulnerability count is now a byte but still 120, set by the hit and again on landing, and still blinks the sprite. | s2.asm L85696s2.asm L38271 | Code |
With neither Left nor Right held, Sonic_Move takes the current acceleration off a standing or running Sonic's ground speed each frame, stopping at 0, as Sonic 2 does; that is $C out of water and without speed shoes (ground-speeds), and $C for Super Sonic. With the infinite-inertia flag some objects set (bit 7 of status_secondary), it skips the d-pad and the friction both. | s2.asm L36826–36846 | Code |
Sonic 3 & Knuckles keeps Sonic 2's skid bug: on flat ground, not mid-flip (flip_type not negative), a reversal skids (stopping animation, facing his motion) when the slowed speed is at least $400 moving right but only $301 moving left, because the angle read overwrites the speed's low byte. | s2.asm L36966–36974 | Code |
| Standing, Sonic's floor and ceiling sensors sit 19 px above and below his center and 9 px to each side, a 19 × 39 px box; curled up, 14 and 7, 15 × 29 px; his wall sensors sit 10 px to either side. These are Sonic 2's sizes. | s2.asm L37368–37371s2.asm L36226–36227s2.asm L44376s2.asm L44567 | Code |
With Down held, neither Left nor Right, and no infinite-inertia flag (bit 7 of status_secondary), Sonic curls into a roll at a ground speed of $100 or more either way, twice Sonic 2's $80; slower than that, unless he stands on an object, he crouches, where Sonic 2 and Sonic 3 alone crouch only from Sonic_Move's standstill branch. | s2.asm L37345–37352s2.asm L36788–36791 | Code |
Outside pinball mode (spin_dash_flag set on a roll) and without the infinite-inertia flag, a roll ends once friction and the d-pad leave the ground speed under $80 either way, and the speed left is kept; Sonic 2 and Sonic 3 alone unroll only at 0. Standing up moves his center 5 px up with normal gravity. In pinball mode a positive flag sets the speed to $400 in his facing direction instead, and a negative one skips the d-pad, friction, and this check. | s2.asm L37097–37106 | Code |
Crouching (animation 8), a press of A, B, or C starts the spin dash's charge at 0; while Down stays held, each frame first takes 1/32 of the counter (rounded down) and a press adds $200, to $800; letting go of Down releases it, curling him (5 px down) and setting the ground speed from the counter's high byte (spindash; Super Sonic's table is faster), negated facing left. On the start, charge, and release frames he doesn't move, and the floor sensors still run. The charge's decay, step, and cap are Sonic 2's. | s2.asm L37714–37729 | Code |
A jump from a roll sets the roll-jump flag, and while it is set Sonic_ChgJumpDir skips the d-pad: no steering and no turning, though the air drag still runs. Landing clears it, as Sonic 2's Sonic_ResetOnFloor does; unlike Sonic 2, whose Sonic_JumpHeight only caps the rise, a jump press once his rise is no faster than 4 px/frame (2 underwater) clears it too (insta-shield-motion), as in Sonic 3 alone. | s2.asm L37207–37208s2.asm L38188–38191s2.asm L37461–37479 | Code |
| A jump from a roll resets Sonic's sensors to the standing size, 19 px below his center, while his ball stays drawn, so he lands 5 px higher than a standing jump would, and landing moves him by the difference, 0. Sonic 2 has the same order of instructions. | s2.asm L37431–37435 | Code |
| On flat ground, not on an object, when both floor sensors find the floor more than |X speed's high byte| + 4 px below, at most 14, Sonic leaves the ground with his speeds as they are, unless stick_to_convex is set; closer than that, he moves down to it. Sonic 2 has the same rule; Sonic 1 used a flat 14 px. | s2.asm L43135–43143 | Code |
| Moving mostly down or up, both side sensors push Sonic out of a wall and stop his X speed; moving mostly left or right, only that side's does, and it also sets his ground speed to his Y speed. Unlike Sonic 2, a push moving left or right doesn't end the checks: the ceiling and then the floor are still tested. | s2.asm L38012–38019s2.asm L38106–38113 | Code |
| Sonic's head sensors are read in the air only while he moves mostly up, left, or right. Inside a ceiling he moves down by the depth; moving up under a flat ceiling his Y speed becomes 0, moving sideways only if he was rising, and the floor isn't tested that frame. Moving mostly left, a head 20 px or more inside a ceiling is instead pushed off a wall on his right, a check Sonic 2 lacks. | s2.asm L38022–38029 | Code |
| Standing on flat ground, not on an object, not Super or Hyper, with no move_lock or infinite-inertia flag, with ground speed 0 after the left and right steps, and the floor under his center 12 px or more below his feet, Sonic turns to face right if last frame's right floor sensor met no block, or else left if the left one met none, and balances; otherwise Down crouches. Sonic 2 turned him only if the floor 6 px back the other way was also that far down. | s2.asm L36717–36724 | Code |
On flat ground, Sonic 3 & Knuckles changes when Sonic rolls and stands: Down curls him only from $100, not Sonic 2's $80, and, off objects, crouches him while he is still moving slower, where Sonic 2 crouched only from a standstill; a roll stands up under $80 with that speed kept, where Sonic 2's rolls on to 0 (both outside pinball mode). In the air he keeps a speed above the top while steering, where Sonic 2 pulled him down to it; a second press after a roll jump gives back steering, which Sonic 2's jump never did; a wall push moving sideways no longer ends the frame's checks; and a head 20 px into a ceiling moving left is pushed off a right wall instead, a check Sonic 2 lacks. Standing over a drop, not Super, he turns toward it at once, where Sonic 2 turned only if the floor 6 px the other way was also low. | s2.asm L37345–37347s2.asm L36788–36791s2.asm L37097–37102s2.asm L37214–37219s2.asm L37461–37479s2.asm L38016–38019s2.asm L38022–38029s2.asm L36717–36724 | Code |
Boost mode starts from a run held at the top speed. Holding forward on the ground at 6 px/frame or faster, Player_HandleGroundMovement leaves the speed as it is and adds the frame's acceleration to boostSpeed, in the branch where Sonic 2's Sonic_MoveRight keeps a speed above the top and Sonic 1's cuts it back to the top. At the start of each frame Player_HandleBoostState turns boost mode on once boostSpeed reaches the ring bracket's entry in playerBoostThresholdTable: Q(8) (2048) with 10 rings or fewer, 2040 with 11 to 49, 1680 with 50 to 99, 1440 with 100 to 149, and 1080 with 150 or more. In the air or below the top speed it sets boostSpeed back to 0. With each bracket's acceleration that is 256, 170, 120, 90, and 60 frames of holding forward at the top speed, and half as many with the speed-up item (computed). | s2.asm L36998–37004 | Code |
While the spin dash charges, each jump press adds Q(2.0) (512) to qSpindashAccel and then raises it to at least Q(8.0) (2048) with MAX, so one press is a full charge, the starting press included: Player_TryInitSpindash runs Player_InitSpindash and then Player_Spindash in the same frame. Each frame Down stays held first takes 1/32 off the charge. Releasing Down sets the ground speed from sSpinDashSpeeds at the charge's whole part, capped at 8: 6 px/frame plus 3/8 a step, up to 9, so a release on the frame after a press always gives 9 px/frame (computed). In Sonic 2 the starting press sets spindash_counter to 0, and each later press adds $200 up to a cap of $800, so a full charge takes five presses in all (computed); its release speeds run from 8 to 12 px/frame. | s2.asm L37605–37613s2.asm L37726–37729s2.asm L37688–37697 | Code |
| The table the end-of-Act results screen reads for the next Act chains the one-player game's eleven zones in twenty Acts, two Acts to a zone but three in Metropolis and one in each of the last three, from Emerald Hill to a last zone after Wing Fortress. | s2.asm L28086–28138s2.asm L28026–28035s2.asm L27842 | Code |
| Two-player mode's zone select offers Emerald Hill, Mystic Cave, and Casino Night, and its level-order table chains Emerald Hill to Casino Night to Mystic Cave, two Acts each, ending after Mystic Cave's second Act. | s2.asm L28141–28193s2.asm L11925–11929 | Code |
| The ending credits name Masaharu Yoshii as director, Yuji Naka as chief programmer, Hirokazu Yasuhara as game planner, and Yasushi Yamaguchi as character designer and chief artist, with Hayao Nakayama and Shinobu Toyoda as executive producers, Masato Nakamura of Dreams Come True as composer, and among the rest Bill Willis as an assistant programmer, Carol Ann Hanshaw for the special stage, and Craig Stitt, Brenda Ross, Jina Ishiwatari, Tom Payne, and Phenix Rie as zone artists. | s2.asm L14581–14596s2.asm L14598–14612s2.asm L14616–14618 | Code |