Ceres Ridley is E13F
Norfair Ridley is E17F
Apparently most of this code is compatible for either one, though this disassembly is mainly for Norfair Ridley
0020 4FE1 5046 A000 0800 0800 A6 08 0000 0500 F5A0 0100 0000 27B2 0F80 97B2 4180 8AB2 0000 00000000 B2DF 000000000000 2380 8ADF 000000 94B0 02 4CF4 B2F1 0000
^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ xx yy ^^yy xxyy ^^^^ xxyy xxyy xxyy xxyy xxyy xxyy xxyy ^^yy xxyyxxyy xxyy xxyyxxyyxxyy xxyy xxyy xxyyxx ^^^^ yy ^^^^ ^^^^ ^^^^
tile pal hp dmg wide high Bank # of hurt Boss AI Part Norm Grap Hurt Froz XRay die PB Tch. Beam tile | | | |
get ptr Ptr "hurt" snd. num Init Cnt. Move AI AI AI or anim Pntr Pntr Pntr set | | | name pointer
lgth frames 0=>1 AI? Rsrv | | pointer to enemy resistances
??? AI | pointer to enemy drop chances
background/foreground
Graphic commands (0F92)
E538: Initialization (draws and avoids crashing)
17 E5 42 E5 0C 00 83 E9 2F 81
0C 00 A5 E9 2F 81
E690: Opening roar and close mouth
17 E5 AE E6 06 00 83 E9 BE E4 08 00 C7 E9 60 00 E9 E9 08 00 C7 E9 CA E4 01 00 83 E9 2F 81
06 00 A5 E9 BE E4 08 00 0B EA 60 00 2D EA 08 00 0B EA CA E4 01 00 A5 E9 2F 81
E6C8: Death roar
17 E5 DE E6 06 00 83 E9 BE E4 08 00 C7 E9 10 00 E9 E9 CA E4 2F 81
06 00 A5 E9 BE E4 08 00 0B EA 10 00 2D EA CA E4 2F 81
E91D: Fly up and start main AI, I guess
17 E5 45 E9 03 00 83 E9 1F E5 01 00 F4 FF 04 00 4F EA 1F E5 FC FF F8 FF 05 00 71 EA 69 E9 11 00 4F EA 11 00 83 E9 2F 81
03 00 A5 E9 1F E5 FF FF F4 FF 04 00 93 EA 1F E5 04 00 F8 FF 05 00 B5 EA 76 E9 11 00 93 EA 11 00 A5 E9 2F 81
E6F0: Turn from left to right
27 E7 01 00 83 E9 08 00 D7 EA 2F E7 01 00 D7 EA 01 00 A5 E9 2F 81
E706: Turn from right to left
27 E7 01 00 A5 E9 08 00 D7 EA 1C E7 01 00 D7 EA 01 00 83 E9 2F 81
E73A: Fireballing
17 E5 B4 E7 D2 E4 AC E7 08 00 83 E9 BE E4 08 00 C7 E9 02 00 E9 E9 4D E8 04 E9 05 00 E9 E9 4D E8 09 E9 05 00 E9 E9 4D E8 09 E9 05 00 E9 E9 4D E8 09 E9 30 00 E9 E9 08 00 C7 E9 D2 E4 AC E7 20 00 83 E9 BE E4 08 00 C7 E9 02 00 E9 E9 4D E8 04 E9 05 00 E9 E9 4D E8 09 E9 05 00 E9 E9 4D E8 09 E9 05 00 E9 E9 4D E8 09 E9 30 00 E9 E9 08 00 C7 E9 CA E4 01 00 83 E9 2F 81
D2 E4 20 E8 08 00 A5 E9 BE E4 08 00 0B EA 02 00 2D EA 4D E8 04 E9 05 00 2D EA 4D E8 09 E9 05 00 2D EA 4D E8 09 E9 05 00 2D EA 4D E8 09 E9 30 00 2D EA 08 00 0B EA D2 E4 20 E8 20 00 A5 E9 BE E4 08 00 0B EA 02 00 2D EA 4D E8 04 E9 05 00 2D EA 4D E8 09 E9 05 00 2D EA 4D E8 09 E9 05 00 2D EA 4D E8 09 E9 30 00 2D EA 08 00 0B EA CA E4 01 00 A5 E9 2F 81
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
Check left/right, Draw facing current direction Aim fireball Aim fireball Aim fireball Aim fireball Close mouth Close mouth+Wait Open mouth Open mouth Aim fireball Aim fireball Aim fireball Aim fireball Close mouth Close mouth
Check Norfair/Health Open mouth Fire lead fireball Fire trailing fireball Fire trailing fireball Fire trailing fireball Fire lead fireball Fire trailing fireball Fire trailing fireball Fire trailing fireball End sound
Play roar sound Wait Check Norfair/Health Play roar Wait End AI
(Left has an extra aim fireball instruction, 4D E8, here. Removed from these comments to keep Left and Right aligned)
Graphic command routines
812F: Stop and wait on this command
E4BE: Put 59 in 781E and JSL to 8090CB. Plays roar sound
E4CA: STZ $7E:781E (No sound playing?)
E4D2: 2 byte argument. If in Norfair or Samus is below 30 health, go to next instruction. Else go to argument, and set main AI script timer to 8
E517: 2 byte argument. Move on to next command if Ridley is facing left, else go to argument.
E51F: 4 byte argument. Add the following bytes to Ridley's X / Y position.
E71C: Set 7E:7820 to 0 (Ridley is facing left) and JSR to D3F9 (Updates a bunch of tail values. Includes JSR $D3B4: Copy 7 entries from (X) to 7E:(Y), 7E:(Y+14), 7E:(Y+28), 7E:(Y+3C), etc.)
E727: Set 7E:7820 to 1 (Ridley is facing forward / turning)
E72F: Set 7E:7820 to 2 (Ridley is facing right) and JSR to D3F9 (Updates a bunch of tail values. Includes JSR $D3B4: Copy 7 entries from (X) to 7E:(Y), 7E:(Y+14), 7E:(Y+28), 7E:(Y+3C), etc.)
E84D: Calculate fireball angle and X/Y speeds
E904: Fires lead fireball ($1995 = 0, LDY #$9642, JSL $868097)
E909: Fires following fireball ($1995 = E, LDY #$9642, JSL $868097)
E969: Set Ridley's main AI to A6AF, and vertical speed to FEA0. (Ceres)
E976: Set Ridley's main AI to B2F3, and vertical speed to FEA0. (Norfair)
Graphic Draw Tiles
E983: Ridley facing left
E9A5: Ridley facing right
E9C7: Ridley facing left, mouth half open
E9E9: Ridley facing left, mouth open
EA0B: Ridley facing right, mouth half open
EA2D: Ridley facing right, mouth open
EA4F: Ridley facing left, legs half extended
EA71: Ridley facing left, legs extended
EA93: Ridley facing right, legs half extended
EAB5: Ridley facing right, legs extended
EAD7: Ridley facing forward
Ridley's RAM
$0FA8 - Pointer to current Main AI assembly
A35B: Startup, 1st run. Moves on to next
A377: Startup, initial wait. Moves on to next
A389: Startup, eyes appear + wait. Moves on to next
A3DF: Startup, main body appears. Moves on to next
A455: Startup, Ridley roars. Moves on to next
A478: Startup, color background in Norfair, start main AI. Moves on to next
A354: Clear speeds, that's it (doesn't move on to anything)
A6AF: Startup liftoff, facing left (Ceres)
A6C8: Startup liftoff, facing left and slowing down (Ceres)
A6E8: Ceres main AI? Not disassembling in this doc.
B2F3: Startup liftoff, facing right
B321: Get new AI script (main battle engine)
B3EC: Initailize movement to center
B3F8: Move to center side (goes to B321)
B441: Chose to do a U swoop
B455: Fly to U swoop start
B493: U swoop, first dive
B4D1: U swoop, dive to half point
B516: U swoop, climb after half point
B554: U Swoop, still climbing
B594: U Swoop End (Chooses BAB7 for next script if Samus is not spinjumping, else B321)
B5C4: Consider tailbouncing
B5E5: Considering tailbouncing
B613: Hover since Samus is spinjumping
B6A7: Fly to start Tailbouncing
B6DD: Start tailbouncing
B70E: Main tailbouncing
B7B9: Tailbouncing, hit ground
BAB7: Check to do Deathswoop/Powerbomb dodge/Move-to-Center, or attempt to ram/grab Samus
BB8F: Ridley in position to grab Samus, no powerbombs
BBC4: Ridley is holding Samus, move towards target position then go to next script
BBF1: Drop Samus
BC2E: Short time after dropping Samus, before returning to B321
BD4E: Ridley is dodging a power bomb (may be holding Samus)
C538: Move Ridley towards 80,148, then go on
C53E: Final roar, go on
C551: Move to death spot, wait, then lower lava and go on
C588: Explosions for death. After a while, drop Samus if needed and go on
C5A8: Disable Ridley and go on
C5C8: Wait 20 frames and go on
C5DA: Wait 100 frames, then drop items, change music, and set boss bit
C600: Wait for deletion
$0FAA - X speed (1/100 pixels)
$0FAC - Y speed (1/100 pixels)
$0FAE - Unused
$0FB0 - Custom index? Only seen in intro
$0FB2 - AI script timer/counter
$0FB4 - Unused
$0FB6 - Unused
$0FEA - Not sure, used by hatchling in Ceres
7E:178C - 7E:178E Unknown, Ceres Ridley writes A6A2F2 here in main AI loop
Tail commentary:
2020,X tells if this tail part is rotating (8000) or not(0)
2024,X tells which direction this tail part is rotating in, clockwise (8000) or counterclockwise (0)
202A,X is the angle of the current tail part (3FC0 - 4000 - 4040 = left - down - right)
2014 is used by all tail parts as rotational speed (in 1/100th's of a revolution per frame)
2016 and 2018 are min (clockwise) and max (counterclockwise) angles. Upon reaching one of these angles, the tail starts rotating in the other direction
201A and 201C are clockwise and counterclockwise angle targets. Upon reaching one of these angles, the tail will stop, assuming the previous tail segment has stopped.
2022,X is a counter added to by 2014. Until it reaches 201E, this tail part is never moved/rotated? When reached, start rotation of next part (which also must reach this before it begins rotating)
201E is a threshhold to start rotation (staggers motion along Ridley's tail - without this, Ridley's tail would move all at once and so always be straight)
2026,X tells the distance from the previous tail part to this tail part
2028,X tells the target distance from the previous tail part to this tail part. 0 if unused. When reached, the tail will slowly return to its original position. NOTE: There are hardcoded limits to tail extension. If those limits are reached, the tail will stay at that limit, neither extending nor returning until this value is lowered or zeroed.
2012 is the tail extension speed (1/100th's of a pixel per frame)
202C,X and 202E,X are the current X/Y position of the tail part, inside the room.
2030,X and 2032,X are the current X/Y distances of this tail part from the previous tail part.
7E:2000 - 7E:2001 Tail control index, value is 0 through 8. 0 = inactive, 1 = flinging at Samus, 2 = start tailbouncing, 3 = continue start tailbouncing?, 4 = during tailbouncing, 5 = start extending during tailbouncing, 6 = continue extending during tailbouncing, 7 = strict tail bouncing, with extending, 8 = spin tail around madly
0 CB20: Do nothing, RTS
1 CBC0: Store CC39 to $12, JMP CBDC
2 CB33: Store 8 to 7E2014, JSR CB72, store 3 to 7E2000 (next)
3 CB45: Store 8 to 7E2014, JMP CB72
4 CBC7: Store CD24 to $12, JMP CBDC
5 CBCE: Store CDAA to $12, JMP CBDC
6 CB4E: Store 3 to 7E2014, JSR CB72, store 6 to 7E2000 (this)
7 CB60: Store 2 to 7E2014, JSR CB72, Store 7 to 7E2000 (this)
8 CBD5: Store CCBD to $12, JMP CBDC
CB72: Set 4000 to min (if facing left) or max (if facing right), run CBC7, set 2000 to 4 if nothing is rotating
CBDC: JSR $12, and update each tail section's angular motion, angle, and x/y position
CC39: Fling tail at Samus (or a nearby missile)
CCBD: Spin tail around (at Samus. Or a nearby missile. <_<)
CD24: Set min and max angles with CBFE, check if rotating with CC1E, If all tail parts are rotating, set optional min if one isn't in use yet and 8 tailspeed. Else if none are rotating, disable optional caps, set control to 5 if moving down, if an unknown timer is 0 (always is as far as I know), set tail to rotating at speed 8.
CDAA: Extend tail while tail bouncing
7E:2002 - 7E:2003 Unknown. Initialized to 1 by Ceres Ridley, otherwise never seen
7E:2004 - 7E:2005 Tail fling trigger
7E:200A - 7E:200B Sort of 1 byte signed with 200B. 1/2 number of revolutions to make when spinning Ridley's tail
7E:200C - 7E:200D Ridley's downwards acceleration when tailbouncing, moving down
7E:200E - 7E:200F Ridley's downwards acceleration when tailbouncing, moving up
7E:2010 - 7E:2011 Timer to start tail movement? It seems to always be 0
7E:2012 - 7E:2013 Tail extension speed. Initialized to F0
7E:2014 - 7E:2015 Angular speed of tail? Initialized to 1. Set to 1 if dodging a powerbomb, 8 if tailbouncing (?).
7E:2016 - 7E:2017 Minimum (clockwise) angle. Initialized to 3FF0, 3FF0 if left, 3FC0 if right.
7E:2018 - 7E:2019 Maximum (counterclockwise) angle. Initialized to 4040, 4040 if left, 4010 if right.
7E:201A - 7E:201B Optional clockwise target of 202A. Minus means unused. If used, store #$0C00 to 2028, 202A - 2014 = new 202A unless smaller than 201A. If smaller than 201A: If first tail segment, or previous segment isn't rotating, 202A = 201A, stop rotation, switch direction. Else STZ 2024 and 202A = 2016
7E:201C - 7E:201D Optional counterclockwise target of 202A. Minus means unused. If used, store #$0C00 to 2028, 202A + 2014 = new 202A unless larger than 201C. If larger than 201C: If first tail segment, or previous segment isn't rotating, 202A = 201C, stop rotation, switch direction. Else 2024 = #$8000 and 202A = 2018
7E:201E - 7E:201F Movement threshold. Initialized to 10, Ceres Ridley sometimes sets to a random number between 7 and 16 (hex)
;Tail 1 starts here
7E:2020 - 7E:2021 Initialized to 0. 8000 = Moving and/or rotating.
7E:2022 - 7E:2023 Initialized to 11. Counter to wait (must reach 201E, 2014 is added every frame 2020,X is set) till this tail segment actually starts rotating, and next tail segment's 2020,X is set to 8000
7E:2024 - 7E:2025 Which direction this tail segment is rotating. 8000 = clockwise (- angle), 0 = counterclockwise (+ angle)
7E:2026 - 7E:2027 Distance (sqrt(X^2 + Y^2)) from Ridley to this tail part.
7E:2028 - 7E:2029 Target distance from Ridley to this tail part. Not actually used for tail part 1, I think
7E:202A - 7E:202B Angle of this tail part (3FC0, left, to 4040, right) (Also used by next tail part to calculate its own absolute angle)
7E:202C - 7E:202D X position of Tail part 1. Set to Ridley's X position + $2030, +#$FFE0 if facing right
7E:202E - 7E:202F Y position of Tail part 1.
7E:2030 - 7E:2031 X distance from Ridley (possibly modified) to Tail part 1.
7E:2032 - 7E:2033 Y distance from Ridley to Tail part 1.
;Tail 2 starts here
7E:2034 - 7E:2035 Initialized to 0. 8000 = Moving and/or rotating.
7E:2036 - 7E:2037 Initialized to 11. Counter to wait (must reach 201E, 2014 is added every frame 2020,X is set) till this tail segment actually starts rotating, and next tail segment's 2020,X is set to 8000
7E:2038 - 7E:2039 Which direction this tail segment is rotating. 8000 = clockwise (- angle), 0 = counterclockwise (+ angle)
7E:203A - 7E:203B Distance (sqrt(X^2 + Y^2)) from previous tail part to this tail part.
7E:203C - 7E:203D Target distance from previous tail part to this tail part.
7E:203E - 7E:203F Angle of this tail part (3FC0, left, to 4040, right). Previous tail part's angle is also added to this angle to get the actual angle.
7E:2040 - 7E:2041 X position of this tail part
7E:2042 - 7E:2043 Y position of this tail part
7E:2044 - 7E:2045 X distance from previous tail part to this tail part
7E:2046 - 7E:2047 Y distance from previous tail part to this tail part
;Tail 3 starts here
7E:2048 - 7E:2049 Initialized to 0. 8000 = Moving and/or rotating.
7E:204A - 7E:204B Initialized to 11. Counter to wait (must reach 201E, 2014 is added every frame 2020,X is set) till this tail segment actually starts rotating, and next tail segment's 2020,X is set to 8000
7E:204C - 7E:204D Which direction this tail segment is rotating. 8000 = clockwise (- angle), 0 = counterclockwise (+ angle)
7E:204E - 7E:204F Distance (sqrt(X^2 + Y^2)) from previous tail part to this tail part.
7E:2050 - 7E:2051 Target distance from previous tail part to this tail part.
7E:2052 - 7E:2053 Angle of this tail part (3FC0, left, to 4040, right). Previous tail part's angle is also added to this angle to get the actual angle.
7E:2054 - 7E:2055 X position of this tail part
7E:2056 - 7E:2057 Y position of this tail part
7E:2058 - 7E:2059 X distance from previous tail part to this tail part
7E:205A - 7E:205B Y distance from previous tail part to this tail part
;Tail 4 starts here
7E:205C - 7E:205D Initialized to 0. 8000 = Moving and/or rotating.
7E:205E - 7E:205F Initialized to 11. Counter to wait (must reach 201E, 2014 is added every frame 2020,X is set) till this tail segment actually starts rotating, and next tail segment's 2020,X is set to 8000
7E:2060 - 7E:2061 Which direction this tail segment is rotating. 8000 = clockwise (- angle), 0 = counterclockwise (+ angle)
7E:2062 - 7E:2063 Distance (sqrt(X^2 + Y^2)) from previous tail part to this tail part.
7E:2064 - 7E:2065 Target distance from previous tail part to this tail part.
7E:2066 - 7E:2067 Angle of this tail part (3FC0, left, to 4040, right). Previous tail part's angle is also added to this angle to get the actual angle.
7E:2068 - 7E:2069 X position of this tail part
7E:206A - 7E:206B Y position of this tail part
7E:206C - 7E:206D X distance from previous tail part to this tail part
7E:206E - 7E:206F Y distance from previous tail part to this tail part
;Tail 5 starts here
7E:2070 - 7E:2071 Initialized to 0. 8000 = Moving and/or rotating.
7E:2072 - 7E:2073 Initialized to 11. Counter to wait (must reach 201E, 2014 is added every frame 2020,X is set) till this tail segment actually starts rotating, and next tail segment's 2020,X is set to 8000
7E:2074 - 7E:2075 Which direction this tail segment is rotating. 8000 = clockwise (- angle), 0 = counterclockwise (+ angle)
7E:2076 - 7E:2077 Distance (sqrt(X^2 + Y^2)) from previous tail part to this tail part.
7E:2078 - 7E:2079 Target distance from previous tail part to this tail part.
7E:207A - 7E:207B Angle of this tail part (3FC0, left, to 4040, right). Previous tail part's angle is also added to this angle to get the actual angle.
7E:207C - 7E:207D X position of this tail part
7E:207E - 7E:207F Y position of this tail part
7E:2080 - 7E:2081 X distance from previous tail part to this tail part
7E:2082 - 7E:2083 Y distance from previous tail part to this tail part
;Tail 6 starts here
7E:2084 - 7E:2085 Initialized to 0. 8000 = Moving and/or rotating.
7E:2086 - 7E:2087 Initialized to 11. Counter to wait (must reach 201E, 2014 is added every frame 2020,X is set) till this tail segment actually starts rotating, and next tail segment's 2020,X is set to 8000
7E:2088 - 7E:2089 Which direction this tail segment is rotating. 8000 = clockwise (- angle), 0 = counterclockwise (+ angle)
7E:208A - 7E:208B Distance (sqrt(X^2 + Y^2)) from previous tail part to this tail part.
7E:208C - 7E:208D Target distance from previous tail part to this tail part.
7E:208E - 7E:208F Angle of this tail part (3FC0, left, to 4040, right). Previous tail part's angle is also added to this angle to get the actual angle.
7E:2090 - 7E:2091 X position of this tail part
7E:2092 - 7E:2093 Y position of this tail part
7E:2094 - 7E:2095 X distance from previous tail part to this tail part
7E:2096 - 7E:2097 Y distance from previous tail part to this tail part
;Tail tip starts here
7E:2098 - 7E:2099 Initialized to 0. 8000 = Moving and/or rotating.
7E:209A - 7E:209B Initialized to 11. Counter to wait (must reach 201E, 2014 is added every frame 2020,X is set) till this tail segment actually starts rotating, and next tail segment's 2020,X is set to 8000
7E:209C - 7E:209D Which direction this tail segment is rotating. 8000 = clockwise (- angle), 0 = counterclockwise (+ angle)
7E:209E - 7E:209F Distance (sqrt(X^2 + Y^2)) from previous tail part to this tail part.
7E:20A0 - 7E:20A1 Target distance from previous tail part to this tail part.
7E:20A2 - 7E:20A3 Angle of this tail part (3FC0, left, to 4040, right). Previous tail part's angle is also added to this angle to get the actual angle.
7E:20A4 - 7E:20A5 X position of this tail part
7E:20A6 - 7E:20A7 Y position of this tail part
7E:20A8 - 7E:20A9 X distance from previous tail part to this tail part
7E:20AA - 7E:20AB Y distance from previous tail part to this tail part
;End of tail data
7E:20AC - 7E:20BF? Extra unused data written to by tail tip for the non-existent 'next tail part'
7E:7000?- 7E:77FF? Table of some sort for enemies. Related to graphics, I think.
7E:7006,X is where in vram the tiles are (I think)
7E:7008,X is which color pallete it uses.
7E:701E,X mirrors 7E:0F78, X
7E:7020,X mirrors 7E:0F7A, X
7E:7022,X mirrors 7E:0F7E, X
7E:7024,X mirrors 7E:0F92, X (Used by Chozo statues for orientation?)
7E:7026,X mirrors 7E:0F86, X
7E:7028,X mirrors 7E:0F88, X
7E:702A,X mirrors 7E:0FB4, X
7E:702C,X mirrors 7E:0FB6, X
7E:702E,X-7E:7038,X is the enemy's name, if it has one. Else #$0000
7E:7800 - 7E:7801 General use timer for main battle AI script
7E:7802 - 7E:7803 Initialized to 0. 1 = main battle AI is active, FFFF = Ded
7E:7804 - 7E:7805 Ridley is active? Initialized to 1 by Norfair Ridley, 0 by Ceres Ridley
7E:7806 - 7E:7807 Used for Hatchling Metroid's graphic draw, initialized to BF31 by Ceres Ridley
7E:7808 - 7E:7809 Used for Hatchling Metroid's graphic draw, initialized to 1 by Ceres Ridley
7E:780A - 7E:780B Pointer to next graphic entry for Ridley's ribs (pointer to next entry, or
7E:780C - 7E:780D Counter for animating Ridley's ribs
7E:780E - 7E:780F Wing flap frame
7E:7810 - 7E:7811 Wing flap speed
7E:7812 - 7E:7813 Wing flap counter (<0 means advance wingflap frame)
7E:7814 - 7E:7815 Ridley's current angle of motion (only for U swoops?) (0 = down, increase is counterclockwise)
7E:7816 - 7E:7817 Ridley's U Swoop speed (sqrt(X^2 + Y^2))
7E:7818 - 7E:7819 Wing/Tail pallete for Ridley?
7E:781A - 7E:781B Ridley's hit counter for Ceres? Initialized to 0
7E:781C - 7E:781D Ridley's tail sound counter: If moving at full speed for 10 frames, play spinjump-like sound.
7E:781E - 7E:781F Current sound playing?
7E:7820 - 7E:7821 Direction faced (0 = left, 1 = front, 2 = right). Initialized to 2 by Norfair Ridley, 0 by Ceres Ridley.
7E:7824 General use 'speed' byte set aside for Ridley?
7E:782E - 7E:782F Target X location when holding Samus
7E:7830 - 7E:7831 Target Y location when holding Samus
7E:7832 - 7E:7833 X component of speed to fire fireballs at
7E:7834 - 7E:7835 Y component of speed to fire fireballs at
7E:7836 - 7E:7837 Flag? Ridley is holding Samus?
7E:7838 - 7E:7839 Tail tip damage. Initialized to 78 by Norfair Ridley, F by Ceres Ridley
7E:783A - 7E:783B Never initialized, always 0.
7E:783E - 7E:783F Which wall was hit last frame: 0 = none, 1 = left, 2 = right, 4 = top, 8 = bottom. 4 and 8 take priority over 1 and 2, even though as bits they should allow overlap.
7E:8000 - 7E:8001 Initialized to 40 by Norfair Ridley, FFE0 by Ceres Ridley. Upmost allowed Y position
7E:8002 - 7E:8003 Initialized to 1A0 by Norfair Ridley, B0 by Ceres Ridley. Downmost allowed Y position
7E:8004 - 7E:8005 Initialized to 40 by Norfair Ridley, 28 by Ceres Ridley. Leftmost allowed X position
7E:8006 - 7E:8007 Initialized to E0 by both Ridleys, seperately. Rightmost allowed X position
7E:8008 - 7E:8009 Unknown timer. Never initialized, always 0, no effect.
7E:800A - 7E:800B Ridley's final attack swoop counter?
7E:800C - 7E:800D 'Counter', used to cause Ridley to start his fireball AI every other tailbounce
7E:800E - 7E:800F Timer for death explosions
7E:8010 - 7E:8011 Index for death explosions
7E:8800 - 7E:8801 JSRed to by Ceres Ridley's main code, initialized to BE9C by Ceres Ridley
7E:8804 - 7E:8805 X position of metroid hatchling
7E:8808 - 7E:8809 Y position of metroid hatchling
7E:C0E2 - 7E:C0FF Background color pallete
7E:C122 - 7E:C137 Mirror of Ridley's colors while appearing except eyes? (C1E2 - C1F7)
7E:C1E2 - 7E:C1EF Ridley's color pallete? \
7E:C1F0 - 7E:C1F7 Ridley's wing pallete? |- Exact offset groups are unknown
7E:C1F8 - 7E:C1FC Ridley's eye color pallete? /
7E:C2E2 - 7E:C2FF Unknown, initialized to 0 by Norfair Ridley
7E:C340 - 7E:C37F Unknown, initialized
7E:C3E2 - 7E:C3FF Unknown, initialized to 0
Main AI Scripts
A35B: Startup, Part 1
{
LDA $0797 ;Room transition flag
BNE BRANCH_ALPHA ;Skip until room transition is finished?
LDA #$A377
STA $0FA8 ;New AI script
LDA #$0200
LDY $079F ;Region number
CPY #$0002 ;Check if Norfair
BNE BRANCH_BETA
LDA #$00AA
BRANCH_BETA: ;Norfair: A = AA. Ceres: A = 200
STA $0FB2 ;Variable use timer
A377_SCRIPT: ;Startup, invisibility timer script?
DEC $0FB2
BPL BRANCH_ALPHA
LDA #$A389
STA $0FA8 ;New AI script
STZ $0FB0 ;Variable use index
STZ $0FB2 ;Timer?
BRANCH_ALPHA
RTS
}
A389: Startup, Eyes appear
{
LDA $0FB0 ;Variable use index (should be 0 first time coming here)
BMI BRANCH_ALPHA ;Never branches, I think
TAY
INC $0FB2 ;Variable use timer?
LDA $0FB2
CMP #$0001 ;Run script every 1 frame
BCC BRANCH_ALPHA ;
STZ $0FB2
TYX ;value is from $0FB0
LDA $E269, X ;1 byte values from F to 0 (10 values), then 30 more 00's, and finally an FF (41 values total)
AND #$00FF
CMP #$00FF
BEQ BRANCH_BETA ;Branches at X = 40
STA $12
ASL A
CLC
ADC $12
ASL A ;Multiplied by 6
TAY
INX
STX $0FB0 ;$0FB0 = $0FB0 + 1
LDX #$01F8
LDA $E2AA, Y ;Y = 6*(eye color index)
STA $7EC000, X ;Setting Ridley's eye color pallete?
LDA $E2AC, Y
STA $7EC002, X
LDA $E2AE, Y
STA $7EC004, X
BRANCH_ALPHA
RTS
BRANCH_BETA
STZ $0FB0 ;Zero out custom value
LDA #$A3DF
STA $0FA8 ;New AI script
LDA #$0001
STA $7E7804 ;Activate Ridley
RTS
}
A3DF:
{
INC $0FB2 ;Variable use timer, initialized to 0
LDA $0FB2
CMP #$0002 ;Run script every 2 frames
BCC BRANCH_ALPHA
STZ $0FB2 ;reset timer
LDY $0FB0 ;Custom value, starts as 0
LDA #$0122
STA $12
LDA #$01E2 ;Ridley's color pallete index
STA $14
LDA #$000B ;Run inside Beta loop B (11) times
BRANCH_BETA
PHA
LDA $E30A, Y
LDX $12
STA $7EC000, X ;Mirror of Ridley's colors while appearing?
LDX $14
STA $7EC000, X ;Update Ridley's colors
INY
INY
INC $12
INC $12
INC $14
INC $14
PLA
DEC A
BNE BRANCH_BETA
CPY #$0160 ;Y = #$0160 after $10 loops through here (20 frames)
BCS BRANCH_GAMMA
STY $0FB0
BRANCH_ALPHA
RTS
BRANCH_GAMMA
LDA $079F ;Region
CMP #$0002 ;Norfair
BNE BRANCH_DELTA
LDA #$0002
STA $0F9A ;Layer setting 2 (not sure what that means) if in Norfair
BRANCH_DELTA
LDA $0F86
AND #$FBFF
STA $0F86 ;Enable Samus/Enemy interaction
LDY #$0000
STY $0FB0 ;Clear index
LDA #$A455
STA $0FA8 ;Next main AI script
LDA #$0004
STA $0FB2 ;Set timer to 4
LDA #$0005
JSL $808FC1 ;Change music control to this
RTS
}
A455:
{
DEC $0FB2 ;Was initialized to 4
BPL BRANCH_ALPHA
LDA #$E690 ;Ridley roars
JSR $D467 ;STA to GraphicAI instruction (0F92), delay (0F94) = 1, STZ $0F90
STZ $0FB2 ;Pointless. It must be 0 because it's here.
LDA #$A478
STA $0FA8 ;Next main AI script
LDA $079F
CMP #$0002 ;Check if Norfair
BEQ BRANCH_ALPHA
LDA #$00FC
STA $0FB2 ;Set timer to FC if in Ceres
BRANCH_ALPHA
RTS
}
A478:
{
LDA $079F
CMP #$0002 ;Check if Norfair
BNE BRANCH_ALPHA
DEC $0FB2
BPL BRANCH_$132477 ;RTS
LDA #$0002
STA $0FB2 ;Every 2 frames
LDA $0FB0
INC A
STA $0FB0 ;Increment Index
DEC A
JSR $A4D6 ;Adjust background colors if necessary
{
ASL A
TAX ;X = 2*(old $0FB0)
LDY $A4EB, X ;Pointer to new background colors. Ends at a 0000
BNE BRANCH_ULTIMA
SEC
RTS
BRANCH_ULTIMA
LDX #$00E2
LDA #$000E
JSL $A9D2E4 ;Copy 2*A bytes from (Y) to 7E:C000,X. Specifically, colors the background.
CLC
RTS
}
BCC BRANCH_$132477 ;Loops till no more backgrounds to change
LDA #$01B8
STA $197A ;New lava height
LDA #$FFA0
STA $197C ;Lava speed
LDA #$0020
STA $1980 ;Delay before lava begins moving?
BRA BRANCH_BETA
BRANCH_ALPHA
DEC $0FB2
BPL BRANCH_$132477 ;RTS
BRANCH_BETA
STZ $0FB0
LDA #$E91D ;Fly up, start main AI?
JSR $D467 ;STA to GraphicAI instruction (0F92), delay (0F94) = 1, STZ $0F90
LDA #$0008
STA $7E7810 ;Wing flap speed
STA $7E7812 ;Wing flap counter
JSR $D3D9 ;Set all tail parts to moving
{
LDA #$8000
STA $7E2020
STA $7E2034
STA $7E2048
STA $7E205C
STA $7E2070
STA $7E2084
STA $7E2098
RTS
}
LDA #$0001
STA $7E2000 ;Set tail control index
LDA #$A354
STA $0FA8 ;Next main AI script
RTS
}
A6AF:
{
LDA $0FAC ;Ridley's Y speed
CLC
ADC #$FFF0 ;1/10 pixel per frame^2 acceleration upwards
STA $0FAC
LDA $0F7E ;Y position
CMP #$0070 ;7 blocks from roof
BMI BRANCH_ALPHA
RTS
BRANCH_ALPHA
LDA #$A6C8 ;New AI script
STA $0FA8
A6C8:
LDA $0FAC ;Ridley's Y speed
CLC
ADC #$0014 ;5/40 pixel per frame^2 acceleration downwards
STA $0FAC
LDA $0F7E ;Ridley's Y position
CMP #$0050 ;5 blocks from roof
BPL BRANCH_BETA
LDA #$A6E8 ;New AI script
STA $0FA8
LDA #$0001
STA $7E7802 ;Main battle AI is active
BRANCH_BETA
RTS
}
B2F3:
{
LDX #$0040
LDY #$0100
STX $12
STY $14
LDX #$0000
LDY #$000E
JSR $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
{
LDA #$0000
STA $1A
LDA $D61F, Y ;F entries, 1 byte each, counts from 10 to 1
AND #$00FF
STA $18
JSR $D5A9 ;Accelerates Ridley towards the desired X position ($12). Deceleration boost in $1A, acceleration divisor in $18, X is enemy's index
{
LDA $0F7A, X ;Ridley's X position
SEC
SBC $12
BEQ BRANCH_ALPHA ;RTS if at $12
BPL BRANCH_BETA ;Go here if right of $12
EOR #$FFFF
INC A ;Absolute distance from $12
STA $4204
SEP #$20
LDA $18
STA $4206 ;Divided by $18
REP #$20
XBA
XBA
NOP
NOP
LDA $4214
BNE BRANCH_GAMMA
INC A
BRANCH_GAMMA
STA $16 ;Result put in $16, minimum of 1
LDA $0FAA, X
BPL BRANCH_DELTA ;Branch if moving towards $12
CLC
ADC $1A ;Deceleration boost
CLC
ADC #$0008 ;Extra deceleration boost, I guess
ADC $16
BRANCH_DELTA
ADC $16 ;Acceleration gradient result (Closer to $12 = more acceleration)
CMP #$0500 ;Max speed allowed is 5 pixels per frame
BMI BRANCH_EPSILON
LDA #$0500 ;Cap at 5 pixels per frame
BRANCH_EPSILON
STA $0FAA, X ;Update speed
BRANCH_ALPHA
RTS
BRANCH_BETA
STA $4204 ;Distance from $12
SEP #$20
LDA $18
STA $4206 ;Divided by $18
REP #$20
XBA
XBA
NOP
NOP
LDA $4214
BNE BRANCH_ZETA
INC A
BRANCH_ZETA
STA $16 ;Result put in $16, minimum of 1
LDA $0FAA, X
BMI BRANCH_THETA ;Branch if moving towards $12
SEC
SBC $1A ;Deceleration boost
SEC
SBC #$0008 ;Extra deceleration boost, I guess
SBC $16
BRANCH_THETA
SBC $16 ;Acceleration gradient result (Closer to $12 = more acceleration)
CMP #$FB00 ;Max speed (er, min velocity) allowed is -5 pixels per frame
BPL BRANCH_IOTA
LDA #$FB00 ;Cap at -5 pixels per frame
BRANCH_IOTA
STA $0FAA, X ;Update speed
RTS
}
LDA $0F7E, X ;Ridley's Y position
SEC
SBC $14
BEQ BRANCH_ALPHA ;RTS if at $14
BPL BRANCH_BETA ;Go here if below $14
EOR #$FFFF
INC A ;Absolute distance from $14
STA $4204
SEP #$20
LDA $18 ;Divided by $18
STA $4206
REP #$20
XBA
XBA
NOP
NOP
LDA $4214
BNE BRANCH_GAMMA
INC A
BRANCH_GAMMA
STA $16 ;Result put in $16, minimum of 1
LDA $0FAC, X
BPL BRANCH_DELTA ;Branch if moving towards $14
CLC
ADC $1A ;Deceleration boost
CLC
ADC #$0008 ;Extra deceleration boost, I guess
ADC $16
BRANCH_DELTA
ADC $16 ;Acceleration gradient result (Closer to $14 = more acceleration)
CMP #$0500 ;Max speed allowed is 5 pixels per frame
BMI BRANCH_EPSILON
LDA #$0500 ;Cap at 5 pixels per frame
BRANCH_EPSILON
STA $0FAC, X ;Update speed
BRANCH_ALPHA
RTS
BRANCH_BETA
STA $4204 ;Distance from $14
SEP #$20
LDA $18 ;Divided by $18
STA $4206
REP #$20
XBA
XBA
NOP
NOP
LDA $4214
BNE BRANCH_ZETA
INC A
BRANCH_ZETA
STA $16 ;Result put in $16, minimum of 1
LDA $0FAC, X
BMI BRANCH_THETA ;Branch if moving towards $14
SEC
SBC $1A ;Deceleration boost
SEC
SBC #$0008 ;Extra deceleration boost, I guess
SBC $16
BRANCH_THETA
SBC $16 ;Acceleration gradient result (Closer to $14 = more acceleration)
CMP #$FB00 ;Max speed (er, min velocity) allowed is -5 pixels per frame
BPL BRANCH_IOTA
LDA #$FB00 ;Cap at -5 pixels per frame
BRANCH_IOTA
STA $0FAC, X ;Update speed
RTS
}
LDA #$0008
STA $16 ;X size of target area
STA $18 ;Y size of target area
JSL $A9EF06 ;Really nice collision detection routine. I'll have to steal *this* one. Checks an enemy with index of X colliding with $12/$14 with a size of $16/$18
{
LDA $16
CLC
ADC $0F82, X ;Ridley's width
INC A
STA $1A ;So, $1A = Ridley's width + 9
LDA $12 ;Still an X position from earlier: 40
SEC
SBC $0F7A, X ;Ridley's position
BPL BRANCH_ALPHA
EOR #$FFFF
INC A
BRANCH_ALPHA ;A = absolute distance between Ridley and $12 (#$0040)
CMP $1A
BCS BRANCH_BETA ;Branch if Ridley isn't near #$0040
LDA $18
CLC
ADC $0F84, X ;Ridley's height
INC A
STA $1A ;So, $1A = Ridley's height + 9
LDA $14 ;Still a Y position from earlier: 100
SEC
SBC $0F7E, X ;Ridley's position
BPL BRANCH_GAMMA
EOR #$FFFF
INC A
BRANCH_GAMMA ;A = absolute distance between Ridley and $14 (#$0100)
CMP $1A
BRANCH_BETA ;Carry Set: No collision. Carry Clear: Collision
RTL
}
BCC BRANCH_ALPHA
RTS
BRANCH_ALPHA
LDA #$0001
STA $7E7802 ;Ridley's main battle AI is active
LDA #$B321 ;Next main AI script
STA $0FA8
B321:
JSR $B335 ;Get new AI script
{
LDA $0A1F ;Samus's movement type
AND #$00FF
CMP #$0003 ;Spin jump
BNE BRANCH_ALPHA
LDA #$B3CC
STA $12 ;Pointer to a set of new AI scripts to run: 8/8 B5C4
RTS
BRANCH_ALPHA
LDA $0F8C ;HP
BNE BRANCH_BETA
LDA #$B3DC ;Pointer to a set of new AI scripts to run: 8/8 BAB7
STA $12
LDA $7E800A
INC A
STA $7E800A ;Death swoop counter
RTS
BRANCH_BETA
CMP #$3840 ;Compare HP to 14400
BPL BRANCH_GAMMA
LDY #$B38C ;Pointer to a set of new AI scripts to run: 4/8 B6A7 and 4/8 B441
STY $12
RTS
BRANCH_GAMMA
JSR $BD20 ;Check if Y is below #$0160
BCC BRANCH_DELTA ;Branch if above
LDY #$B3BC ;Pointer to a set of new AI scripts to run: 8/8 B6A7
STY $12
RTS
BRANCH_DELTA
JSR $BCF1 ;CLC if spin jump, grappling, or spin back from hurt
BCC BRANCH_EPSILON
LDY #$B3AC ;Pointer to a set of new AI scripts to run: 6/8 BAB7 and 2/8 B6A7
STY $12
RTS
BRANCH_EPSILON
LDY #$B38C ;Pointer to a set of new AI scripts to run: 4/8 B6A7 and 4/8 B441
LDA $0F8C ;HP
CMP #$2328 ;Compare HP to 9000
BPL BRANCH_ZETA ;A previous check confirmed over 14400 hp. Ergo, this always branches. Not that it much matters
LDY #$B39C ;Pointer to a set of new AI scripts to run if below 9000 HP: 4/8 B441, 4/8 B6A7
BRANCH_ZETA
STY $12
RTS
}
JSL $808111 ;RNG
AND #$0007
ASL A
TAY
LDA ($12), Y ;Grab 1 of 8 random AI scripts,
STA $0FA8 ;set as current main AI script,
JMP ($0FA8) ;and run it
}
B3EC: Initailize movement to center
{
LDA #$B3F8
STA $0FA8 ;Next main AI script
LDA #$0080
STA $0FB2 ;AI script timer
B3F8: Move to center side
DEC $0FB2
BMI BRANCH_ALPHA
LDX #$00C0
LDA $7E7820 ;Direction facing
BEQ BRANCH_BETA ;Branch if facing left
LDX #$0060
BRANCH_BETA
STX $12
LDY #$0100
STY $14
JSR $B42E ;Y = 4, 8, A, or C, depending on general speed byte
LDX #$0000
JSR $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
LDA #$0008
STA $16
STA $18
JSL $A9EF06 ;Checks an enemy with index of X colliding with $12/$14 with a size of $16/$18, CLC if collided
BCC BRANCH_ALPHA
RTS
BRANCH_ALPHA
LDA #$B321
STA $0FA8 ;Next main AI script
RTS
}
B441: Chose to do a U swoop
{
LDA #$B455 ;Main AI loop for
STA $0FA8
LDA #$000A
STA $7E7800 ;Initialize timer
LDA #$0000
STA $7E7814 ;Initialize movement direction
B455: Fly to U swoop start
LDX #$00C0
LDA $7E7820 ;Facing direction (0 = left, 2 = right)
BEQ BRANCH_ALPHA
LDX #$0040
BRANCH_ALPHA
STX $12 ;X = Target X position = C0 if facing left, 40 if facing right
LDY #$0080
STY $14 ;Target Y position = 80
LDX #$0000
LDY #$0001
JSR $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
LDA #$0008
STA $16 ;Target area X size
STA $18 ;Target area Y size
JSL $A9EF06 ;Checks an enemy with index of X colliding with $12/$14 with a size of $16/$18, CLC if collided
BCS BRANCH_BETA
LDA #$B493
STA $0FA8 ;Next main AI loop
LDA #$0020
STA $7E7800 ;Initialize timer
LDA #$0000
STA $7E7814 ;Initialize movement direction
BRANCH_BETA
RTS
}
B493: U swoop, first dive
{
LDA $7E7820 ;Facing direction (0 = left, 2 = right)
BNE BRANCH_ALPHA
LDA #$FFE0
STA $12 ;Angular speed
LDA #$FE00
STA $14 ;Target angle of motion
BRA BRANCH_BETA
BRANCH_ALPHA
LDA #$0020
STA $12 ;Angular speed
LDA #$0200
STA $14 ;Target angle of motion
BRANCH_BETA
LDA #$0480
STA $16 ;Target U Swoop speed (sqrt(X^2 + Y^2))
JSR $D800 ;Update Ridley's U Swoop speed and U Swoop angle, and calculate current X and Y speed
{
LDA $16 ;Target U Swoop speed
CMP $7E7816 ;U Swoop speed (sqrt(X^2 + Y^2))
BEQ BRANCH_ALPHA
BPL BRANCH_BETA
LDA $7E7816
SEC
SBC #$0020 ;Acceleration is fixed at 20
CMP $16
BPL BRANCH_GAMMA
LDA $16
BRANCH_GAMMA
STA $7E7816
BRA BRANCH_ALPHA
BRANCH_BETA
LDA $7E7816
CLC
ADC #$0020 ;Acceleration is fixed at 20
CMP $16
BMI BRANCH_THETA
LDA $16
BRANCH_THETA
STA $7E7816
BRANCH_ALPHA
LDA $12 ;Angular speed
BMI BRANCH_DELTA
CLC
ADC $7E7814 ;Angle of motion (0 = down, increase moves counterclockwise, 1 loop = 10000)
CMP $14 ;Target angle of motion
BMI BRANCH_EPSILON
BRA BRANCH_ZETA
BRANCH_DELTA
CLC
ADC $7E7814 ;Angle of motion (0 = down, increase moves counterclockwise, 1 loop = 10000)
CMP $14 ;Target angle of motion
BPL BRANCH_EPSILON
BRANCH_ZETA
LDA $14
BRANCH_EPSILON
STA $7E7814
XBA
AND #$00FF
STA $12 ;$12 = high byte of current angle of motion
LDA $7E7816
JSL $86C26C ;A * sin ($12 * 360/256)
STA $0FAA ;Ridley's X speed
LDA $7E7816
JSL $86C272 ;A * cos ($12 * 360/256)
STA $0FAC ;Ridley's Y speed
RTS
}
LDA $7E7800 ;Timer for current main AI script
BEQ BRANCH_GAMMA
DEC A
STA $7E7800
RTS
BRANCH_GAMMA
LDA #$B4D1 ;Next main AI script
STA $0FA8
LDA #$0014
STA $7E7800 ;New timer
RTS
}
B4D1: U swoop, dive to half point
{
LDA $7E7820 ;Direction facing. 0 = Left, 2 = Right
BNE BRANCH_ALPHA
LDA #$FEC0
STA $12 ;Angular speed
LDA #$C000
STA $14 ;Target angle of motion
BRA BRANCH_BETA
BRANCH_ALPHA
LDA #$0140
STA $12 ;Angular speed
LDA #$4000
STA $14 ;Target angle of motion
BRANCH_BETA
LDA #$0500
STA $16 ;Target U Swoop speed (sqrt(X^2 + Y^2))
JSR $D800 ;Update Ridley's U Swoop speed and U Swoop angle, and calculate current X and Y speed
LDA $7E7800 ;Timer for current main AI script
BEQ BRANCH_GAMMA
DEC A
STA $7E7800
RTS
BRANCH_GAMMA
LDA #$B516
STA $0FA8 ;Next main AI script
LDA #$0010
STA $7E7800 ;New timer
LDA #$0001
STA $7E2004 ;Tail fling trigger
RTS
}
B516: U swoop, climb after half point
{
LDA $7E7820 ;Direction facing. 0 = Left, 2 = Right
BNE BRANCH_ALPHA
LDA #$FE00
STA $12 ;Angular speed
LDA #$8800
STA $14 ;Target angle of motion
BRA BRANCH_BETA
BRANCH_ALPHA
LDA #$0200
STA $12 ;Angular speed
LDA #$7800
STA $14 ;Target angle of motion
BRANCH_BETA
LDA #$0300
STA $16 ;Target U Swoop speed (sqrt(X^2 + Y^2))
JSR $D800 ;Update Ridley's U Swoop speed and U Swoop angle, and calculate current X and Y speed
LDA $7E7800 ;Current main AI script timer
BEQ BRANCH_GAMMA
DEC A
STA $7E7800
RTS
BRANCH_GAMMA
LDA #$B554
STA $0FA8 ;Next main AI script
LDA #$0020
STA $7E7800 ;New timer
RTS
}
B554: U Swoop, still climbing
{
LDA $7E7820 ;Direction facing. 0 = Left, 2 = Right
BNE BRANCH_ALPHA
LDA #$FC00
STA $12 ;Angular speed
LDA #$8800
STA $14 ;Target angle of motion
BRA BRANCH_BETA
BRANCH_ALPHA
LDA #$0400
STA $12 ;Angular speed
LDA #$7800
STA $14 ;Target angle of motion
BRANCH_BETA
LDA #$0300
STA $16 ;Target U Swoop speed (sqrt(X^2 + Y^2))
JSR $D800 ;Update Ridley's U Swoop speed and U Swoop angle, and calculate current X and Y speed
LDA $7E7800 ;Current main AI script timer
BEQ BRANCH_GAMMA
DEC A
STA $7E7800
RTS
BRANCH_GAMMA
LDA #$B594
STA $0FA8 ;Next main AI script
LDA #$0020
STA $7E7800 ;New timer
JMP $D955
...
D955:
LDA $7E7820 ;Direction facing. 0 = Left, 1 = Forward, 2 = Right
BEQ BRANCH_ALPHA
DEC A
BEQ BRANCH_BETA
LDA $0F79 ;Find which side of the room Ridley is on: plus = left, minus = right
BPL BRANCH_BETA
LDA #$E706
BRA BRANCH_GAMMA
BRANCH_ALPHA
LDA $0F79
BMI BRANCH_BETA
LDA #$E6F0
BRANCH_GAMMA
STA $0F92 ;If on the same side of room as facing, end up here and put in new graphic AI to turn around
LDA #$0002
STA $0F94 ;Graphic AI delay = 1 frame
STZ $0F90 ;Unknown
BRANCH_BETA
RTS
}
B594: U Swoop End
{
STZ $12 ;Angular speed
LDA #$8000
STA $14 ;Target angle of motion
LDA #$01C0
STA $16 ;Target U Swoop speed (sqrt(X^2 + Y^2))
JSR $D800 ;Update Ridley's U Swoop speed and U Swoop angle, and calculate current X and Y speed
LDA $7E7800 ;Main AI script timer
BEQ BRANCH_ALPHA
DEC A
STA $7E7800
RTS
BRANCH_ALPHA
JSR $BCF1 ;CLC if spin jump, grappling, or spin back from hurt
LDY #$B321 ;Choose a new AI script
BCC BRANCH_BETA
LDY #$BAB7 ;Powerbomb dodge...?
BRANCH_BETA
STY $0FA8 ;New main AI script
RTS
}
B5C4: Consider Tailbouncing
{
LDA #$000B
STA $7E201E ;Movement threshold
LDA #$0180
STA $7E2012 ;Tail extension rate
LDA #$B5E5
STA $0FA8 ;Next main AI script
LDA $05E5 ;Random number
AND #$001F
CLC
ADC #$0020 ;20 - 3F
STA $0FB2 ;Variable use timer
B5E5: Considering tailbouncing
LDA $7E7820 ;Facing direction. 0 = left, 1 = forward, 2 = right
ASL A
TAY
LDA $B60D, Y ;00C0, 0080, or 0040
STA $12
JSR $B641 ;Fly towards $12 (X position) / Samus's Y position. If Samus is not spin jumping, SEC before RTS. Else CLC and randomly fireball if allowed.
{
LDA $0AFA ;Samus's Y position
CMP #$0160
BMI BRANCH_ALPHA
LDA #$0160
BRANCH_ALPHA ;Maximum cap is 160
STA $14
LDX #$0000
JSR $B42E ;Y = 4, 8, A, or C, depending on general speed byte
{
LDA $7E7824 ;General speed byte
ASL A
TAY
LDA $B439, Y ;0004, 0008, 000A, 000C
TAY
RTS
}
JSR $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
LDA #$0001
STA $7E2004 ;Tail fling trigger
LDA $0A1F ;Samus's movement type
AND #$00FF
CMP #$0003 ;Spin jump
BNE BRANCH_BETA
LDA $05E5 ;Random number
AND #$00FF
CMP #$0080
BCC BRANCH_GAMMA ;50% chance of not fireballing
LDA $7E781E ;Current sound playing?
BNE BRANCH_GAMMA
LDA $7E7820 ;Facing direction
DEC A
BEQ BRANCH_GAMMA ;Branch if facing forward
LDA #$E73A ;Fireballing AI
JSR $D467 ;STA to GraphicAI instruction (0F92), delay (0F94) = 1, STZ $0F90
BRANCH_GAMMA
CLC
RTS
BRANCH_BETA
SEC
RTS
}
BCC BRANCH_ALPHA ;Branch if Samus is spinjumping
JMP $B68B
...
B68B:
LDA #$00F0
STA $7E2012 ;Tail extension rate
LDA #$0010
STA $7E201E ;Tail movement threshold
LDA #$0001
STA $7E2000 ;Tail control index
LDA #$B6A7
STA $0FA8 ;Next AI script
RTS
BRANCH_ALPHA
DEC $0FB2 ;Timer
BPL BRANCH_BETA
LDA #$B613
STA $0FA8 ;Next AI script
LDA #$0080
STA $0FB2 ;Timer
JMP $D955 ;Turn around if facing away from the center of the room (facing a wall)
BRANCH_BETA
RTS
}
B613: Hover since Samus is spinjumping
{
LDA $7E7820 ;Direction facing
ASL A
TAY
LDA $B63B, Y ;0040, 0080, or 00C0
STA $12
JSR $B641 ;Fly towards $12 (X position) / Samus's Y position. If Samus is not spin jumping, SEC before RTS. Else CLC and randomly fireball if allowed.
BCC BRANCH_ALPHA
JMP $B68B
{
LDA #$00F0
STA $7E2012 ;Tail extension speed
LDA #$0010
STA $7E201E ;Tail movement threshold
LDA #$0001
STA $7E2000 ;Tail control index
LDA #$B6A7
STA $0FA8 ;Set next main AI script
}
BRANCH_ALPHA
DEC $0FB2
BPL BRANCH_BETA
LDA #$B5E5 ;Considering tail bouncing
STA $0FA8 ;Use as next AI script
LDA #$0080
STA $0FB2
JMP $D955 ;Turn around if facing away from the center of the room (facing a wall)
BRANCH_BETA
RTS
}
B6A7: Fly to start Tail bouncing
{
LDA $0F7E ;Ridley's Y position
CMP #$0120
BMI BRANCH_$B6CE
LDA $7E7820 ;Facing direction
ASL A
TAY
LDA $B6C8, Y ;00B0, 0080, 0060
STA $12 ;Target X
LDA #$0120
STA $14 ;Target Y
LDX #$0000
LDY #$0000
JMP $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
...
B6CE:
JSR $D955 ;Turn around if facing away from the center of the room (facing a wall)
LDA #$B6DD
STA $0FA8 ;Next main AI script
B6DD: Start Tail bouncing
LDA #$0020
STA $0FB2 ;Timer
LDA $0F7A ;Ridley's X position
STA $12
LDA #$0120 ;Target Y position
STA $14
LDX #$0000
LDY #$0000
JSR $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
DEC $0FB2
BPL BRANCH_ALPHA
JSR $CB33 ; $134B33 IN ROM
{
LDA #$0008
STA $7E2014 ;Rotational speed of tail parts
JSR $CB72 ;
{
LDA $7E7820 ;Direction facing
BNE BRANCH_ALPHA
LDA #$4000 ;Setup left
STA $7E201C ;Optional counterclockwise target
LDA #$FFFF
STA $7E201A ;Optional clockwise target
BRA BRANCH_BETA
BRANCH_ALPHA
LDA #$4000 ;Setup right
STA $7E201A ;Optional clockwise target
LDA #$FFFF
STA $7E201C ;Optional counterclockwise target
BRANCH_BETA
JSR $CBC7 ; $134BC7 IN ROM
{
LDA #$CD24
STA $12
BRA $CBDC
CBDC:
PHB
PEA #$7E7E
PLB
PLB
PEA #$CBE7 ;Points to just before the LDA #$0007
JMP ($0012) ;Effectively JSR ($0012)
{
}
LDA #$0007
LDX #$0000
BRANCH_BETA
PHA
JSR $D09F ;Run once for each tail segment
{
LDA $2020, X ;Check if this segment is rotating?
BMI BRANCH_$D0C5
LDA $202A, X ;Angle of tail part
JMP $D16D
D0AA:
STZ $2020, X ;Not rotating
STZ $2022, X ;Clear counter
LDA $2024, X
EOR #$8000 ;Change direction
STA $2024, X
RTS
D0BA:
LDA $2022, X ;'Counter' for movement?
CLC
ADC $2014 ;Angular speed?
STA $2022, X
RTS
D0C5:
LDA $2022, X
CMP $201E ;Threshhold for rotation?
BCC BRANCH_$D0BA ;Branch if threshold hasn't been reached?
CMP #$FFFF
BEQ BRANCH_ALPHA ;Branch if threshold has already been reached earlier?
LDA #$FFFF
STA $2022, X ;At limit now?
LDA #$8000
STA $2034, X ;Tell next part to start rotating
LDA $2024, X ;Which way to rotate: 8000 = negative speed = clockwise, 0000 = positive speed = counterclockwise
STA $2038, X ;Copy to next part's direction
BRANCH_ALPHA
LDA $2024, X ;Angular direction
BMI BRANCH_BETA
LDA $201C ;Optional counterclockwise target for angle
BMI BRANCH_GAMMA ;Branch if unused
LDA #$0C00
STA $2028, X ;Target extension distance
LDA $202A, X ;Angle of tail part
CLC
ADC $2014 ;Add speed
CMP $201C ;Compare to optional maximum
BMI BRANCH_DELTA ;Branch if below optional maximum
TXA
BEQ BRANCH_EPSILON
LDA $200C, X
BNE BRANCH_ZETA
BRANCH_EPSILON ;Goes here if previous tail part isn't moving (or if first part)
LDA $201C ;Load optional counterclockwise target
STA $202A, X ;Set angle of tail part
JMP $D0AA ;Stop rotation and change direction
BRANCH_GAMMA
LDA $202A, X ;Angle of tail part
CLC
ADC $2014 ;Add speed
CMP $2018 ;Check with maximum
BMI BRANCH_DELTA ;Branch if below maximum
BRANCH_ZETA
LDA #$8000
STA $2024, X ;Set direction to clockwise
LDA $2018 ;Load cap
BRA BRANCH_DELTA
BRANCH_BETA
LDA $201A
BMI BRANCH_IOTA
LDA #$0C00
STA $2028, X ;Target extension distance
LDA $202A, X ;Angle of tail part
SEC
SBC $2014
DEC A
CMP $201A
BPL BRANCH_KAPPA
TXA
BEQ BRANCH_LAMBDA
LDA $200C, X
BNE BRANCH_MU
BRANCH_LAMBDA
LDA $201A
STA $202A, X ;Angle of tail part
JMP $D0AA
BRANCH_IOTA
LDA $202A, X ;Angle of tail part
SEC
SBC $2014
DEC A
CMP $2016
BPL BRANCH_KAPPA
BRANCH_MU
LDA #$0000
STA $2024, X
LDA $2016 ;Minimum allowed angle
BRA BRANCH_DELTA
BRANCH_KAPPA
INC A
BRANCH_DELTA
STA $202A, X ;Set angle of this tail part
D16D:
AND #$00FF
STA $12 ;Angle
TXA
BEQ BRANCH_THETA
LDA $12
CLC
ADC $2016, X ;Additional angle between previous tail part and this one
AND #$00FF
STA $12
BRANCH_THETA
LDA $2026, X ;Distance from previous tail part to this one, in 1/100th of a pixel
XBA
AND #$00FF
JSL $A9C460 ;A = (sin($12) * A) / 256. X is preserved
STA $2030, X ;X distance from previous tail part (Ridley if Tail 1) to this tail part
LDA $2026, X ;Distance from 1 tail part to next
XBA
AND #$00FF
JSL $A9C465 ;A = (cos($12) * A) / 256. X is preserved
STA $2032, X ;Y distance from previous tail part (Ridley if Tail 1) to this tail part
RTS
}
TXA
CLC
ADC #$0014
TAX
PLA
DEC A
BNE BRANCH_BETA
PLB
RTS
}
LDA $7E2020
ORA $7E2034
ORA $7E2048
ORA $7E205C
ORA $7E2070
ORA $7E2084
ORA $7E2098
BEQ BRANCH_GAMMA ;Branch if no tail parts are rotating
RTS
BRANCH_GAMMA
LDA #$0004
STA $7E2000 ;Set tail control index
RTS
}
LDA #$0003
STA $7E2000 ;Tail control index
RTS
}
JSR $B90F ;Set speeds for tailbouncing
{
LDA $05E5 ;Random number
AND #$0003
ASL A
TAY
LDA $B965, Y ;B975, B981, B98D, B999. Options for absolute X speed from tail bounces
STA $12
LDA $B96D, Y ;B9A5, B9B1, B9BD, B9C9. Options for Y speed from tail bounces
STA $14
LDA $7E7824 ;General speed byte (max is 3)
CLC
ADC #$0002 ;*cough*incinc*cough*
ASL A
TAY
LDA $B94D, Y ;20, 30, 40, 50
STA $7E200E
LDA $B959, Y ;40, 80, 400, 500
STA $7E200C ;For below: Each pair of parenthesis are the 4 speed choices for a single one of the above randomly chosen pointers.
LDA ($14), Y ;(FCE0, FC20, FA80, F980), (FC80, FBC0, FA60, F960), (FC60, FB80, FA40, F940), (FC40, FB60, FA20, F920)
STA $0FAC ;Ridley's Y speed
LDA ($12), Y ;(A0, A8, B0, B8), (C0, C8, D0, D8), (E0, E8, F0, F8), (100, 108, 110, 118)
LDX $0FAA ;Ridley's X speed
BPL BRANCH_ALPHA
EOR #$FFFF
INC A
BRANCH_ALPHA ;Keep sign from old X speed, magnitude from lookup
STA $0FAA
RTS
}
LDA #$B70E
STA $0FA8 ;Next AI script
LDA $05E5 ;Random number
AND #$003F
ADC #$0080
STA $0FB2 ;AI script timer. In this specific case, the timer is decremented every frame Ridley is moving up from tailbouncing.
BRANCH_ALPHA
RTS
}
B70E: Tailbouncing main (moving down)
{
JSR $B859 ;Attempt to grab Samus
{
JSR $BCF1 ;Check for spinjumping or spinback
{
LDA $0A1F
AND #$00FF ;Samus's movement type
PHX
TAX
BIT $BD03, X ;0's are: Spin jump, grappling, spinback, grabbed by draygon.
BMI BRANCH_ALPHA
PLX
CLC ;CLC if spinjumping or spinback
RTS
BRANCH_ALPHA
PLX
SEC ;else SEC
RTS
}
BCS BRANCH_ALPHA
RTS
BRANCH_ALPHA
LDX #$0004
LDY #$0004
STX $16
STY $18 ;Size of target is 8x8 pixels
LDA $7E7820 ;Direction facing
ASL A
TAY
LDA $B9D5, Y ;000C, 0000, FFF4
CLC
ADC $0F7A ;Ridley's X position
STA $12 ;Target grab X position
LDA $7E783A ;Unknown, not used aside for this
TAY
LDA $B9DB, Y ;0023, 002E, 0038
CLC
ADC $0F7E ;Ridley's Y position
STA $14 ;Target grab Y position
JMP $DF29 ;Efficient collision detection for Samus and $12/$14 (size of $12/$14 is $16/$18). SEC if collision
}
BCC BRANCH_ALPHA ;Branch if failed to grab Samus
JSR $B84D ;Store 1 to 7E:2000 and 7E:2014
JMP $B889 ;
{
LDA $0FAC ;Ridley's Y speed
BMI BRANCH_ALPHA
EOR #$FFFF
INC A
BRANCH_ALPHA ;Negative value
CMP #$FE00
BMI BRANCH_BETA ;Branch if moving less than 2 pixels per frame
LDA #$FE00
BRANCH_BETA
STA $0FAC ;Set Ridley to moving upwards, and at most 2 pixels per frame
JSR $B84D ;Store 1 to 7E:2000 and 7E:2014
LDA #$BB8F
STA $0FA8 ;Set next main AI script
JMP $BB8F ;'Samus grabbed' AI script, I'm assuming
}
BRANCH_GAMMA
RTS
BRANCH_ALPHA
LDA $0FAC ;Ridley's Y speed
CLC
ADC $7E200C ;40, 50, 400, or 500, depending on Ridley's speed. From previous AI script.
CMP #$0600 ;6 pixels per frame
BMI BRANCH_BETA
LDA #$0600 ;Cap at 6 pixels per frame
BRANCH_BETA
STA $0FAC ;Store as Ridley's speed, moving down
JSR $B7E7 ;
{
LDA $7E20A4 ;Tail tip X position
TAX
LDA $7E20A6 ;Tail tip Y position
CLC
ADC #$0010
TAY
JSL $A6D4F9 ;Check for collisions with blocks
BCS BRANCH_ALPHA
LDA $7E2090 ;Tail part 6 X position
TAX
LDA $7E2092 ;Tail part 6 Y position
CLC
ADC #$0012
TAY
JSL $A6D4F9
BCS BRANCH_ALPHA
LDA $7E207C ;Tail part 5 X position
TAX
LDA $7E207E ;Tail part 5 Y position
CLC
ADC #$0012
TAY
JSL $A6D4F9
BCS BRANCH_ALPHA
LDA $7E2068 ;Tail part 4 X position
TAX
LDA $7E206A ;Tail part 4 Y position
CLC
ADC #$0012
TAY
JSL $A6D4F9
BCS BRANCH_ALPHA
LDA $7E2054 ;Tail part 3 X position
TAX
LDA $7E2056 ;Tail part 3 Y position
CLC
ADC #$0012
TAY
JSL $A6D4F9
BCS BRANCH_ALPHA
NOP
BRANCH_ALPHA
RTS
}
BCC BRANCH_GAMMA ;Branch if no collisions with ground
LDA $7E20A4 ;Tail tip X position
STA $12
LDA $7E20A6 ;Tail tip Y position
CLC
ADC #$000C
STA $14
LDA #$0009
LDY #$E509
JSL $868097 ;Create sprite: smoke where tail tip hit the ground
LDA #$0076
JSL $8090CB ;Play sound
LDA #$000D
STA $183E ;Room shake type
LDA #$0004
STA $1840 ;Room shake duration
JSR $B8A9 ;
{
LDA $0FAA ;Ridley X speed
BNE BRANCH_ALPHA ;Branch if moving
LDA #$00C0
BIT $0F79 ;Low byte of Ridley's X position
BPL BRANCH_BETA ;Branch if Ridley is on the left half of the room
EOR #$FFFF
INC A
BRANCH_BETA ;Set Ridley to moving towards the center
STA $0FAA ;Set Ridley's speed to 0.C pixels per frame
BRANCH_ALPHA
LDA $0F7A ;Ridley's X position
SEC
SBC $0AF6 ;Samus's X position
EOR $0FAA ;Ridley's X speed
BMI BRANCH_GAMMA ;Branch if Ridley is moving towards Samus
LDA $0F7A ;Ridley's X position
CMP $7E8004 ;Leftmost allowed X position
BMI BRANCH_DELTA
CMP $7E8006 ;Rightmost allowed X position
BPL BRANCH_EPSILON
LDA $05E5 ;Random number
CMP #$0555 ;... 1 / 30 chance?
BCC BRANCH_ZETA
BRANCH_THETA
LDA $0FAA
EOR #$FFFF
INC A
STA $0FAA ;Reverse Ridley's X speed
BRANCH_ZETA
RTS ;Summary: If Ridley is within the room boundaries and moving away from Samus, 2F/30 times reverse directions
BRANCH_GAMMA
LDA $0F7A ;Ridley's X position
CMP $7E8004 ;Leftmost allowed X position
BMI BRANCH_DELTA
CMP $7E8006 ;Rightmost allowed X position
BPL BRANCH_EPSILON
LDA $05E5
CMP #$0555 ;1/30 chance
BCC BRANCH_THETA ;Switch directions (If Ridley is within the room boundaries and moving towards Samus, 1/30 times reverse directions
RTS
BRANCH_DELTA
LDA $0FAA ;Ridley is at the left room boundary. Reverse Ridley's X speed if moving left
BMI BRANCH_THETA
RTS
BRANCH_EPSILON
LDA $0FAA ;Ridley is at the right room boundary. Reverse Ridley's X speed if moving right
BPL BRANCH_THETA
RTS
}
JSR $B90F ;Set speeds for tailbouncing (depends on random and speed)
LDX #$D37C
LDY #$2026 ;Set standard distances between tail parts
JSR $D3B4 ;Copy 7 entries from (X) to 7E:(Y), 7E:(Y+14), 7E:(Y+28), 7E:(Y+3C), etc.
LDA #$0C00
STA $7E2028
STA $7E203C
STA $7E2050
STA $7E2064
STA $7E2078
STA $7E208C
STA $7E20A0 ;Set target extension distance to C pixels for all tail parts
LDA #$0004
STA $7E2000 ;Set tail control index
LDA $7E800C ;Not used before... a timer?
INC A
CMP #$0002
BMI BRANCH_DELTA
LDA $7E7820 ;Direction facing
DEC A
BEQ BRANCH_EPSILON ;Branch if facing forward
LDA #$E73A ;Fireballing AI
JSR $D467 ;STA to GraphicAI instruction (0F92), delay (0F94) = 1, STZ $0F90
BRANCH_EPSILON
LDA #$0000
BRANCH_DELTA
STA $7E800C
LDA #$B7B9
STA $0FA8 ;Store next AI script
RTS
}
B7B9: Tailbouncing, Hit Ground (moving up)
{
JSR $BD20 ;Check if Y is below #$0160
BCC BRANCH_ALPHA ;Branch if above
DEC $0FB2 ;AI script timer/counter (80 to BF)
BMI BRANCH_ALPHA ;Branch if it was at 0
LDA $0FAC ;Ridley's Y speed
CLC
ADC $7E200E ;20, 30, 40, or 50, depending on general speed byte. From tailbounce speed setup
STA $0FAC ;Ridley's Y speed
BMI BRANCH_BETA ;Branch if still moving up
LDA #$0000
STA $0FAC ;Stop Y movement
LDA #$B70E
STA $0FA8 ;Go back to main tailbouncing, moving down
BRANCH_BETA
RTS
BRANCH_ALPHA
JSR $B84D ;Store 1 to 7E:2000 and 7E:2014
LDA #$B321
STA $0FA8 ;Decide what to do next
RTS
}
BAB7: Check to do Deathswoop/Powerbomb dodge/Move, or attempt to ram/grab Samus
Deathswoop/Powerbomb dodge/Move if:
Samus is spinjumping, Ridley has collided with a wall, Samus is behind or above Ridley
{
JSR $BCF1 ;Check for spinjumping or spinback (CLC if so)
BCC BRANCH_$BA85
{
LDA $7E800A ;Death swoop counter
CMP #$000A ;10 swoops
BMI BRANCH_ALPHA ;Branch if not time to die yet
JSL $A6DFB7 ;Even though it's JSL, it's Ridley-specific.
{
LDA $0F8C ;Health
BNE BRANCH_ALPHA ;Branch if not 0 (doesn't happen)
LDA $7E7802 ;AI status
BMI BRANCH_ALPHA ;Branch if already set to dead
LDA #$FFFF
STA $7E7802 ;Set to dead
LDA $0F86
ORA #$0400
STA $0F86 ;Disable interaction with Samus
LDA #$C538
STA $0FA8 ;Set next AI script (Ridley specific)
BRANCH_ALPHA
RTL
}
LDA #$C53E
STA $0FA8 ;Set next AI script
JMP $C53E ;and run it. When that RTSes, it goes to Ridley's main AI loop.
BRANCH_ALPHA
LDA $0CEE ;Powerbomb timer
BEQ BRANCH_BETA
LDA #$BD4E
STA $0FA8 ;Set next AI script to dodge powerbombs
JMP $BD4E ;and run it. When that RTSes, it goes to Ridley's main AI loop.
BRANCH_BETA
LDA #$B3EC
STA $0FA8 ;Set the next AI script
LDA #$0001
STA $7E2004 ;Trigger for flinging Ridley's tail?
RTS ;Returns to Ridley's main AI loop.
}
LDA $7E783E ;Check collisions with walls (0 = none)
BNE BRANCH_$BA85 ;Deathswoop / Powerbomb / Else if collided with walls
LDA $7E7820 ;Direction facing
ASL A
TAY
LDA $BB48, Y ;0000, 0000, 8000
STA $12
LDA $0F7A ;Ridley's X position
SEC
SBC $0AF6 ;Samus's X position
STA $14
EOR $12
BPL BRANCH_ALPHA ;Branch if Ridley is facing Samus
LDA $14
BPL BRANCH_BETA
EOR #$FFFF
INC A
BRANCH_BETA ;Absolute distance between Samus and Ridley
CMP #$0020 ;2 blocks
BPL BRANCH_$BA85 ;Deathswoop / Powerbomb / Else if farther than 2 blocks away
BRANCH_ALPHA ;Ridley is facing Samus, or is less than 2 blocks away
LDA $0F7E ;Ridley's Y position
CLC
ADC #$0023
SEC
SBC $0AFA ;Samus's Y position
BPL BRANCH_$BA85 ;Deathswoop / Powerbomb / Else if Ridley is below Samus
;Ridley attempts to ram Samus with the following code
LDX #$FFF0
LDA $7E7820 ;Direction facing
BEQ BRANCH_GAMMA
LDX #$0010 ;X = 10 if facing right
BRANCH_GAMMA
TXA
CLC
ADC $0AF6 ;Samus's X position
STA $12
LDA $0AFA ;Samus's Y position
CLC
ADC #$FFFC
STA $14
LDX #$0000
LDA $7E7824 ;General speed byte
ASL A
TAY
LDA $BB4E, Y ;0001, 0003, 0007, 000A
TAY
JSR $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
LDA $7E7820 ;Direction facing
ASL A
TAY
LDA $B9D5, Y ;000C, 0000, FFF4
CLC
ADC $0F7A ;Ridley's X position
STA $12
LDA #$0023
CLC
ADC $0F7E ;Ridley's Y position
STA $14
LDA #$0008
STA $16
LDA #$000C
STA $18
JSR $DF29 ;Efficient collision detection for Samus and $12/$14 (size of $12/$14 is $16/$18). SEC if collision
BCS BRANCH_$BB56
RTS
...
BB56:
LDA $0FAC ;Ridley's Y speed
EOR #$FFFF
INC A
STA $0FAC ;Switch direction
LDA $0F8C ;Health
BEQ BRANCH_ALPHA
LDA $0CEE ;Power bomb timer
LDA $0CEE ;We heard you the first time
BEQ BRANCH_BETA ;Branch if no power bomb is active
JSR $BC68 ;Grab Samus
{
JSR $BA54 ;Set displacement for Ridley grabbing Samus
{
LDA $7E7820 ;Direction facing
ASL A
TAY
LDA $B9D5, Y ;000C, 0000, FFF4
ADC $0F7A ;Ridley's X position
SEC
SBC $0AF6 ;Samus's X position
EOR #$FFFF
INC A
STA $7E7828 ;X displacement for Ridley grabbing Samus
LDA $7E783A ;Unknown, only used for this
TAY
LDA $B9DB, Y ;0023, 002E, 0038
CLC
ADC $0F7E ;Ridley's Y position
SEC
SBC $0AFA ;Samus's Y position
EOR #$FFFF
INC A
STA $7E782A ;Y displacement for Ridley grabbing Samus
RTS
}
LDA $0F86
ORA #$0400
STA $0F86 ;Make Ridley intangible to Samus
LDA #$0001
STA $7E7836 ;Set Ridley holding Samus flag
DEC A
JSL $90F084 ;Put #$E713 into $0A42(Handle only Samus's projectiles and sound termination, the rest of Samus becomes static), #$E8DC into $0A44(Zeroes Samus' contact damage, runs minimap, the rest of Samus becomes static)
SEC ;Close claws
JMP $DA8B ;Writes to VRAM for Ridley's claws
...
DA8B:
LDX #$DAD0
BCC BRANCH_ALPHA
LDX #$DAD4 ;Get pointer to source address
BRANCH_ALPHA
LDY $0330
LDA #$B000
STA $00D3, Y
STA $00DA, Y ;Set source banks to B0
LDA $0000, X
STA $00D2, Y
LDA $0002, X
STA $00D9, Y ;Get and set source addresses
LDA #$7AC0
STA $00D5, Y
LDA #$7BC0
STA $00DC, Y ;Target addresses (F580 and F780 in VRAM)
LDA #$0080
STA $00D0, Y
STA $00D7, Y ;80 bytes each
TYA
CLC
ADC #$000E
TAY
STY $0330
LDA #$0000
STA $00D0, Y
RTS
}
LDA #$BD4E
STA $0FA8 ;Next AI script
JMP $BD4E ;and run it
BRANCH_ALPHA
LDA $7E7836 ;Check if Ridley is holding Samus
BNE BRANCH_GAMMA
JSR $BC68 ;If not, grab Samus now
BRANCH_GAMMA
JSL $A6DFB7 ;Set 7802 to dead, disable Samus/Ridley interaction, next AI script is C538
LDA #$C538
STA $0FA8 ;Redundant
JMP $C538 ;Run next AI script
BRANCH_BETA
BB8F: ;Ridley in position to grab Samus, no powerbombs
LDA $7E7820 ;Check direction facing
ASL A
TAY
LDA $BBEB, Y ;0040, 0000, 00D0
STA $7E782E ;Target X when holding Samus
LDA $0F7E ;Ridley's Y position
CLC
ADC #$FFC0 ;Up 4 blocks
CMP #$0100
BPL BRANCH_DELTA
LDA #$0100 ;Minimum value is 1 screen
BRANCH_DELTA
STA $7E7830 ;Target Y when holding Samus
LDA $7E7836 ;Check if Ridley is grabbing Samus
BNE BRANCH_EPSILON
JSR $BC68 ;If not, grab Samus now
BRANCH_EPSILON
LDA #$BBC4
STA $0FA8
BBC4: Move towards target position while holding Samus
LDA #$0020
STA $0FB2 ;Custom use timer
LDA $7E782E ;0040, 0000, or 00D0
STA $12
LDA $7E7830 ;Ridley's old Y position + 4 blocks, or #$0100, whichever is larger.
STA $14
LDX #$0000
LDY #$0000
JSR $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
DEC $0FB2 ;Custom use timer
BPL BRANCH_ZETA
LDA #$BBF1
STA $0FA8 ;Next AI script
LDA #$0020
STA $0FB2 ;Set timer to 20
BRANCH_ZETA
RTS
}
BBF1: Drop Samus
{
DEC $0FB2 ;Variable use timer. Starts as 20 in this case
BMI BRANCH_ALPHA
LDA $7E782E ;Target X position
STA $12
LDA #$0100
STA $14
LDX #$0000
LDY #$0000
JMP $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
BRANCH_ALPHA
LDA #$0008
STA $7E201E ;Tail movement threshold
LDA #$00F0
STA $7E2012 ;Tail extension rate
JSR $BC84 ;Let go of Samus
{
LDA #$0001
STA $7E2004 ;Tail fling trigger
STA $7E2000 ;Tail control index
LDA $7E7802 ;Main AI status (1 = active, FFFF = dead)
BMI BRANCH_ALPHA ;Branch if dead
JSR $BCF1 ;Check for spinjumping or spinback (CLC if so)
LDA #$0006
BVS BRANCH_BETA ;Branch if currently morphed
LDA #$000A
BRANCH_BETA
STA $7E783C ;Disable Ridley/Samus interaction for this many frames
BRANCH_ALPHA
LDA #$0000
STA $7E7836 ;Ridley is no longer holding Samus
INC A
JSL $90F084 ;Put #$E695 into $0A42, #$E725 into $0A44. Restores normal Samus controls/processing.
CLC ;Open claws
JMP $DA8B ;Write to VRAM for Ridley's claws
}
LDA #$BC2E
STA $0FA8 ;Set next main AI script
LDA #$0040
STA $0FB2 ;Set main AI script timer
RTS
}
BC2E: Wait after dropping Samus
{
DEC $0FB2 ;Main AI script timer
BMI BRANCH_ALPHA
LDA $7E7820 ;Direction facing
ASL A
TAY
LDA $BC62, Y ;00B0, 0000, 0050
STA $12
LDA #$00E0
STA $14
LDX #$0000
LDY #$0000
JSR $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
RTS
BRANCH_ALPHA
LDA #$0010
STA $7E201E ;Tail movement threshold
LDA #$00F0
STA $7E2012 ;Tail extension rate
LDA #$B321
STA $0FA8 ;Next main AI script
RTS
}
BD4E: Dodge a powerbomb
{
LDA $0CEE ;Powerbomb timer
BEQ BRANCH_ALPHA
LDA #$0002
STA $7E7802 ;Main battle AI is momentarily paused?
LDY #$0050
LDA $0CE2 ;X position of powerbomb explosion
CMP #$0080
BPL BRANCH_BETA
LDY #$00C0
BRANCH_BETA
STY $12
LDY #$00C0
LDA $0CE4 ;Y position of powerbomb explosion
CMP #$0100
BPL BRANCH_GAMMA
LDY #$0180
BRANCH_GAMMA
STY $14
LDX #$0000
JSR $B42E ;Y = 4, 8, A, or C, depending on general speed byte
JMP $D523 ;Accelerates Ridley towards the desired X/Y ($12/$14). No deceleration boost ($1A), Y is index value to find acceleration divisor ($18), X is enemy's index
BRANCH_ALPHA
LDA #$0001
STA $7E7802 ;Resume main battle AI
LDY #$B321
LDA $7E7836 ;Holding Samus flag
BEQ BRANCH_DELTA
LDY #$BB8F ;Go to normal holding Samus AI
BRANCH_DELTA
STY $0FA8 ;Next main AI script
RTS
}
C538: Move to death spot
{
JSR $C601 ;Move to death spot, CLC when near it
{
LDX #$0080
STX $12
LDY #$0148
STY $14
LDX #$0000
LDY #$0000
LDA #$0010
JSR $D526 ;Accelerates Ridley towards the desired X/Y ($12/$14). A is deceleration boost, Y is index value to find acceleration divisor ($18), X is enemy's index
LDA #$0004
STA $16
STA $18
JSL $A9EF06 ;Check if Ridley is near $12/$14. CLC if so
RTS
}
BCC BRANCH_ALPHA
RTS
BRANCH_ALPHA
C53E: Die
LDA #$E6C8
JSR $D467 ;STA to GraphicAI instruction (0F92), delay (0F94) = 1, STZ $0F90
LDA #$C551
STA $0FA8 ;Next main AI script
LDA #$0020
STA $0FB2 ;Main AI script timer
RTS
}
C551: Move to death spot, wait for timer, then move lava
{
JSR $C601 ;Move to death spot, CLC when near it
DEC $0FB2 ;Timer
BPL BRANCH_$C550 ;points to an RTS
STZ $0FAA
STZ $0FAC ;Stop Ridley's speed
LDA #$0210
STA $197A ;New lava height
LDA #$0040
STA $197C ;Lava speed
LDA #$0001
STA $1980 ;Delay before lava begins moving
LDA #$0000
STA $7E800E ;Prep for later
STA $7E8010 ;Prep for later
LDA #$C588
STA $0FA8
LDA #$00A0
STA $0FB2 ;Timer
C588: Spawn explosions
JSR $C623 ;
{
LDA $7E800E ;Timer between explosions
DEC A
BMI BRANCH_ALPHA ;Branches immediately
STA $7E800E
RTS
BRANCH_ALPHA
LDA #$0004
STA $7E800E
LDA $7E8010 ;Explosion index
INC A
CMP #$000A
BMI BRANCH_BETA
LDA #$0000
BRANCH_BETA
STA $7E8010
ASL A
ASL A
TAY
LDA $C66E, Y ;FFE8, FFEC, 0010, 001E, 000E, FFFE, FFFE, FFE1, FFFC, 0013
CLC
ADC $0F7A ;Ridley's X position
STA $12
LDA $C670, Y ;FFE8, 0014, FFE2, FFFD, FFF3, 0012, FFE0, 0008, FFF6, 0013
CLC
ADC $0F7E ;Ridley's Y position
STA $14
LDA #$0003
LDY #$E509
JSL $868097 ;Draw an explosion
LDA #$0024
JSL $8090B7 ;Play an explosion sound
RTS
}
DEC $0FB2
BPL BRANCH_$C550 ;RTS
LDA $7E7836 ;Check if Ridley is holding Samus
BEQ BRANCH_ALPHA
JSR $BC84 ;Let go of Samus
BRANCH_ALPHA
LDA #$C5A8
STA $0FA8 ;Next main AI script
STZ $0FAA
STZ $0FAC ;Stop movement
JMP $C932 ;Spawns the individual parts of Ridley to fly off
...
C932:
LDX #$C9E7
JSL $A09275 ;Dunno. Not doing right now
LDX #$C9D7
JSL $A09275
LDX #$C9C7
JSL $A09275
LDX #$C9B7
JSL $A09275
LDX #$C9A7
JSL $A09275
LDX #$C997
JSL $A09275
LDX #$C987
JSL $A09275
LDX #$C9F7
JSL $A09275
LDX #$CA07
JSL $A09275
LDX #$CA27
JSL $A09275
LDX #$CA17
JSL $A09275
LDX #$CA37
JSL $A09275
RTS
}
C5A8: Disable Ridley
{
JSR $C623 ;Keep playing explosions
LDA #$0000
STA $7E7804 ;Ridley is now inactive
LDA $0F86
ORA #$0100
STA $0F86 ;Make Ridley invisible
LDA #$C5C8
STA $0FA8 ;Next main AI script
LDA #$0020
STA $0FB2 ;Main AI script timer
RTS
}
C5C8: Wait 20 frames
{
DEC $0FB2 ;Main AI script timer
BPL BRANCH_$C550 ;an RTS from a looong time ago
LDA #$C5DA
STA $0FA8 ;Next main AI script
LDA #$0100
STA $0FB2 ;Main AI script timer
RTS
}
C5DA: Wait another 100 frames, then drop items/change music/set boss bit
{
DEC $0FB2 ;Main AI script timer
BPL BRANCH_ALPHA
LDA #$0001
JSL $8081A6 ;Set boss bits in A for current area (7E:D828,X)
JSL $A0B9A5 ;Drop items. Not gonna bother documenting
LDA #$0003
JSL $808FC1 ;Change to elevator music
LDA $0F86
ORA #$0200
STA $0F86 ;Delete Ridley
LDA #$C600
STA $0FA8 ;Next main AI script
BRANCH_ALPHA
C600:
RTS
}
A6:A0F5
Ridley_Initialization:
{
LDX $079F ;Region number
LDA $7ED828, X ;Boss bit table
AND #$0001 ;First boss bit of current Region (Ridley, in this case)
BEQ BRANCH_ALPHA ;Branch if still alive
LDA $0F86 ;Property bits of Ridley (assumed to be first enemy)
AND #$FFFF ;Useless
ORA #$0700 ;Set Delete enemy, Delete enemy, and Disable enemy/Samus interaction
STA $0F86 ;Store in property bits
RTL
BRANCH_ALPHA ;Setup for Ridley when alive
PHB
PEA #$7E7E
PLB
PLB ;Set bank to 7E (ram)
LDA #$0000
LDX #$0FFE
BRANCH_BETA
STA $2000, X ;Forget the LDA earlier, STZ would make more sense
DEX
DEX
BPL BRANCH_BETA ;Clears all RAM between 7E:2000 and 7E:2FFF
PLB
JSL $90A7E2 ; Clear automap and set entire room to explored (horribly inefficient yet hardcoded stuff)
STZ $0FB4 ; Speed in SMILE
STZ $0FB6 ; Speed 2 in SMILE
LDA #$E538 ; Starting graphicAI. Necessary to avoid crashing, I guess
JSR $D467 ; STA to GraphicAI instruction (0F92), delay (0F94) = 1, STZ $0F90
LDA #$0E00
STA $0F96 ; Pallete
STA $7E7818 ; Wing pallete, I guess
LDA $0F88 ; Property bits 2
ORA #$0004 ; Enable multiple hitboxes
STA $0F88
LDA #$0000
STA $7E7802 ;Ridley's main battle AI is not active yet
STA $7E781A ;Ridley's hit counter for Ceres?
STZ $183E ; Screen shaking type
STZ $1840 ; Screen shaking duration
JSR $D2D6 ; Initializes a ton of variables from 7E:2012 to 7E:20A7. I'm *guessing* they're for his tail.
; Uses JSR $D3B4: Copy 7 entries from (X) to 7E:(Y), 7E:(Y+14), 7E:(Y+28), 7E:(Y+3C), etc.
JSR $D9FD ; Store DA71 to 7E:780A, 1 to 7E:780C
LDA $079F ; Region
CMP #$0002 ; Check if Norfair
BEQ BRANCH_GAMMA
JMP $A1EE ; Probably Ceres initialization
BRANCH_GAMMA
LDA $0F86 ; Property bits
ORA #$1400 ; Enable Plasma block and Disable enemy/Samus interaction
STA $0F86
LDA #$0060
STA $0F7A ; X position
LDA #$018A
STA $0F7E ; Y position
LDA #$B2F3
LDA #$A35B ; haha
STA $0FA8 ; Current main AI script
STZ $0FAA ; Custom, X speed in 1/100ths of a pixel
STZ $0FAC ; Custom, Y speed in 1/100ths of a pixel
LDA #$0005
STA $0F9A ; Visibility Layer
LDA #$0000
STA $7E7802 ; Already been set to 0. Redundant. Ridley's main battle AI is not active yet.
INC A
STA $7E7804 ;Activate Ridley?
LDA #$0040
STA $7E8000 ;Upmost Y position allowed
LDA #$01A0
STA $7E8002 ;Downmost Y position allowed
LDA #$0040
STA $7E8004 ;Leftmost X position allowed
LDA #$00E0
STA $7E8006 ;Rightmost X position allowed
LDA #$0002
STA $7E7820 ;Facing direction
LDA #$0078
STA $7E7838 ;Tail tip damage
LDY #$E1CF
LDX #$0140
LDA #$0020
JSL $A9D2F6 ;Copy 2*A bytes from (Y) to 7E:C200,X
LDX #$00E2
LDX #$0000 ;again, haha
LDY #$000F
LDA #$0000
BRANCH_DELTA
STA $7EC2E2, X ;Unknown
STA $7EC3E2, X ;Unknown
INX
INX
DEY
BNE BRANCH_DELTA
RTL
$1321EE ALTERNATE ENTRY POINT ; Ceres Ridley Initialization
LDA $0F86
ORA #$1400 ;Enable Plasma block and Disable enemy/Samus interaction
STA $0F86
LDA #$00BA
STA $0F7A ;X position
LDA #$00A9
STA $0F7E ;Y position
LDA #$0000
STA $093F ;Unknown
STA $7E7820 ;Facing direction
STA $7E7804 ;Set Ridley as inactive?
INC A
STA $7E2002 ;Unknown
LDA #$000F
STA $7E7838 ;Tail tip damage
LDA #$A35B
STA $0FA8 ;Current main AI script
STZ $0FAA ;X speed
STZ $0FAC ;Y speed
LDA #$FFE0
STA $7E8000 ;Upmost Y position allowed
LDA #$00B0
STA $7E8002 ;Downmost Y position allowed
LDA #$0028
STA $7E8004 ;Leftmost X position allowed
LDA #$00E0
STA $7E8006 ;Rightmost X position allowed
LDY #$E16F
LDX #$0140
LDA #$0020
JSL $A9D2F6 ;Copy 2*A bytes from (Y) to 7E:C200,X
LDX #$01E2
LDY #$000F
LDA #$0000
BRANCH_EPSILON
STA $7EC200, X ;Clear color pallete data?
INX
INX
DEY
BNE BRANCH_EPSILON
LDA #$BF31
STA $7E7806 ;Used for hatchling Metroid's graphic draw.
LDA #$0001
STA $7E7808 ;Used for hatchling Metroid's graphic draw.
LDA #$BE9C
STA $7E8800 ;Ceres Ridley hurt AI script?
LDA #$0005
STA $7E780E ;Wing flap frame
LDA #$0000
JSL $808FC1 ;Change music control to this
RTL
$132288 ALTERNATE ENTRY POINT ;Ceres Ridley's Main AI
LDA #$7FFF
STA $0F8C ;Ridley's health
PEA #$A293 ;Right before the LDA $093F
JMP ($0FA8) ;Basically JSR ($0FA8) instead, run main AI script
LDA $093F ;Unknown, initialized to 0
BNE BRANCH_ZETA
LDA $7E7804 ;Check if Ridley is active?
BEQ BRANCH_THETA
JSR $D4DA ;Make wings/tail flash when hit
JSR $D86B ;Handles movement and main body wall collisions
JSR $D97D ;Handle wing flapping
JSR $A2BD ;1/100 chance of setting 7E:201E to 7-16 (all hex numbers)
{
LDA $05E5 ;Random number
CMP #$FF00
BCC BRANCH_MU
LDA $05E5
AND #$000F
ADC #$0007
STA $7E201E ;Tail movement threshold
BRANCH_MU
RTS
}
JSR $CAF5 ;Handles something and tail movement
JSR $D4B5 ;Determine and set Ridley's color pallete
{
LDA $7E7802 ;Check if Ridley's main battle AI is active
BEQ BRANCH_ALPHA
LDA $7E781A ;Ridley's hit counter for Ceres?
CMP #$0032 ;50 in decimal
BCC BRANCH_ALPHA
LDY #$0000
CMP #$0046 ;70 in decimal
BCC BRANCH_BETA
LDY #$0001
CMP #$005A ;90 in decimal
LDY #$0002
BRANCH_BETA
STY $12
JMP $D495 ;Set Ridley's color pallete
...
$A6D495:
LDA $7EC400 ;Unknown
BNE BRANCH_ALPHA
LDA $12
ASL A
ASL A
ASL A
SEC
SBC $12
ASL A
ASL A ;Multiplied by 28 in decimal
CLC
ADC #$E46A
TAY
LDX #$01E2
LDA #$000E
JSL $A9D2E4 ;Copy 2*A bytes from (Y) to 7E:C000,X
BRANCH_ALPHA
RTS
}
JSR $DA0C ;No idea. Doesn't have any noticable effect, adds two entries to 7E00D0,X table
JSR $DB2A ;Draw tail
JSR $DAD8 ;Drawing routine for Ridley's wings
BRA BRANCH_THETA
BRANCH_ZETA
RTL
$1322D3 ALTERNATE ENTRY POINT ;This is Ceres Ridley's hurt AI
;I think only power bombs can manage to get here.
JSR $D4DA ;Make wings/tail flash when hit
JSR $DB2A ;Draw tail
JSR $DAD8 ;Drawing routine for Ridley's wings
BRANCH_THETA
JSR $BE93 ;basically JSR ($7E8800)
{
LDA $7E8800
STA $12
JMP ($0012)
}
LDA $7E7804 ;Check if Ridley is active?
BEQ BRANCH_IOTA
LDA #$A600
STA $178D
LDA #$A2F2
STA $178C ;Long pointer: A6A2F2
RTL
BRANCH_IOTA
LDA $093F ;Unknown, initialized to 0 on for Ceres
BNE BRANCH_KAPPA
JSR $BF1A ;Draw the metroid hatchling!
{
LDA #$7806
JSR $DBCB ;Calculate graphic to use. JSR to with an address (in ram) of a pointer followed by a counter, data at pointer (to rom) should be a counter (frame duration) followed by a graphic pointer, OR a pointer to code.
{
STA $00
INC A
INC A
STA $03
SEP #$20
LDA #$7E
STA $02
STA $05 ;00 = 7E7806 (initialized as BF31), 03 = 7E7808 (initialized as 1)
REP #$20
LDA [$00]
BMI BRANCH_ALPHA
PLA
RTS
BRANCH_ALPHA
TAX
LDA $0000, X
BMI BRANCH_BETA
CMP [$03]
BNE BRANCH_GAMMA
INX
INX
INX
INX
LDA $0000, X
BPL BRANCH_DELTA
BRANCH_BETA
STA $06
INX
INX
PEA #$DBEE ;Points to just before the LDA $0000,X just above
JMP ($0006)
BRANCH_DELTA
LDA #$0001
STA [$03]
TXA
STA [$00]
LDY $0002, X
RTS
BRANCH_GAMMA
LDA [$03]
INC A
STA [$03]
LDY $0002, X
RTS
}
LDA $7E8804 ;Metroid's X position
STA $12
LDA $7E8808 ;Metroid's Y position
STA $14
STZ $16
JMP $DC13 ;General use draw, $16 has pallete, Y is pointer to sprite data.
}
BRANCH_KAPPA
LDA $0FEA ;Unknown, door's custom ram
BEQ BRANCH_LAMBDA
LDA $1840 ;Shaking duraton?
AND #$0003
TAX
LDA $A321, X
CLC
ADC $0FBA ;Door's X position
BRANCH_NU
STA $14
LDA $0FBE ;Door's Y position
STA $12
LDA #$0400
STA $16
LDY #$A329
JSL $81879F ;Dunno this routine, but it draws the door
BRANCH_LAMBDA
RTL
$1323?? ALTERNATE ENTRY POINT
JSR $9C6B ; $131C6B IN ROM
TAX
ORA $0FAC9C
RTS
$1324D6 ALTERNATE ENTRY POINT
ASL A
TAX
LDY $A4EB, X
BNE BRANCH_ULTIMA
SEC
RTS
BRANCH_ULTIMA
LDX #$00E2
LDA #$000E
JSL $A9D2E4 ; $14D2E4 IN ROM
CLC
RTS
}
;A6:B227
Ridley_Main_AI:
LDA $7E8008 ;Unknown, oddly. It wasn't initialized.
SEC
SBC #$0004
BPL BRANCH_ALPHA
LDA #$0000
BRANCH_ALPHA
STA $7E8008 ;A timer or counter, I guess?
JSR $BCB4 ;Displayed below. Handles Enemy/Samus interaction bit.
{
LDA $7E7802 ;Check if main battle AI is running
BMI BRANCH_ALPHA ;There's a minus option? Dunno when this would branch
BEQ BRANCH_BETA ;Branch if main battle AI is not running
JSR $DE7A ;Displayed below. Checks if Ridley is on screen
{
LDA $0F7E
BMI BRANCH_ALPHA ;Negative Y position? What, at start of battle?
CLC
ADC #$0020
SEC
SBC $0915
BMI BRANCH_ALPHA ;Branch if 2 blocks above screen
CMP #$0120
BPL BRANCH_ALPHA ;or 2 blocks below screen (note: 1 screen = E blocks)
LDA $0F7A
BMI BRANCH_ALPHA ;Negative X position. As impossible as negative Y position
CLC
ADC #$0020
SEC
SBC $0911
BMI BRANCH_ALPHA ;Branch if 2 blocks left of screen - impossible
CMP #$0140
BPL BRANCH_ALPHA ;Branch if 2 blocks right of screen - impossible
CLC ;Clear if on screen
RTS
BRANCH_ALPHA
SEC ;Set if off screen
RTS
}
BCC BRANCH_GAMMA
LDA $0F86
ORA #$0400 ;Disable interaction with Samus if off-screen
STA $0F86
RTS
BRANCH_GAMMA
LDA $0F86
AND #$FBFF ;Enable interaction with Samus if on-screen
STA $0F86
BRANCH_BETA
LDA $7E783C ;Disable Ridley/Samus interaction for this many frames
BEQ BRANCH_ALPHA
DEC A
STA $7E783C
BNE BRANCH_ALPHA
LDA $7E7802
BMI BRANCH_ALPHA ;This check is useless, it exists earlier already
LDA $0F86
AND #$FBFF
STA $0F86 ;Enable Enemy/Samus interaction
BRANCH_ALPHA
RTS
}
JSR $BD2C ;Power Bomb Check/Reaction
{
LDA $7E7802 ;Check if Ridley's main battle AI is active
BMI BRANCH_ALPHA ;Not sure when this would branch
BEQ BRANCH_ALPHA ;Branch if main AI inactive
CMP #$0002
BEQ BRANCH_ALPHA
LDA $0CEE ;Powerbomb timer
BEQ BRANCH_ALPHA
LDA $7E7836 ;Ridley is grabbing Samus?
BNE BRANCH_ALPHA
JSR $B84D ;Store 1 to 7E:2000 and 7E:2014
LDY #$BAB7
STY $0FA8 ;Apparently this is Current Main AI script
BRANCH_ALPHA
RTS
}
PEA #$B243 ;Note: This points to just before the LDA.
JMP ($0FA8) ;In effect, this is JSR ($0FA8). When it reaches an RTS, it returns to LDA $7E7804
LDA $7E7804 ;Checks if Ridley is active?
BEQ BRANCH_BETA
JSR $D4DA ;Make wings/tail flash when hit
{
PHX
LDX #$0E00 ;Normal pallete
LDA $0F9C ;Hit
BEQ BRANCH_ALPHA
DEC A
BEQ BRANCH_ALPHA
LDA $0E44 ;Flashing counter, I guess
INC A
AND #$0002
BEQ BRANCH_ALPHA
LDX #$0000 ;White (hurt) pallete
BRANCH_ALPHA
TXA
STA $7E7818 ;Wing/Tail pallete
PLX
RTS
}
JSR $D86B ;Handles movement and main body wall collisions
{
LDA #$0000
STA $7E783E ;Wall collision. 0 = none, 1 = left, 2 = right, 4 = top, 8 = bottom. 4 and 8 take priority over 1 and 2
LDX $0E54
LDA $0FAA, X ;Subpixel speed (1 byte)
SEP #$20
CLC
ADC $0F7D, X ;high byte of subpixel X
STA $0F7D, X
REP #$20
AND #$FF00
XBA
BPL BRANCH_ALPHA
ORA #$FF00
BRANCH_ALPHA
ADC $0F7A, X ;X position
CMP $7E8004 ;Minimum X position
BPL BRANCH_BETA
JSR $D914 ;Cause room shaking, only happens in Ceres. Has unreachable code for Norfair room shaking
{
LDA $079F ;Region
CMP #$0002
BEQ BRANCH_ALPHA
LDA $0FAA, X ;X Speed
BPL BRANCH_BETA
EOR #$FFFF
INC A
BRANCH_BETA
STA $12
LDA $0FAC, X ;Y Speed
BPL BRANCH_GAMMA
EOR #$FFFF
INC A
BRANCH_GAMMA
CMP $12
BCS BRANCH_DELTA
LDA $12
BRANCH_DELTA ;Get the absolute greater of the two speeds
CMP #$0280 ;and compare to 2 1/2 pixels per frame
BCC BRANCH_ALPHA
LDA $079F
CMP #$0002
BEQ BRANCH_EPSILON
LDA #$0021 ;Ceres room shake value
BRA BRANCH_ZETA
BRANCH_EPSILON
LDA #$0018 ;Norfair room shake value. Never used
BRANCH_ZETA
STA $183E ;Room shake type
LDA #$000C
STA $1840 ;Room shake duration
BRANCH_ALPHA
RTS
}
LDA $7E8004
STA $0F7A, X ;Cap X position
STZ $0FAA, X ;Stop speed
LDA #$0001
STA $7E783E ;Mark as hit left wall?
BRA BRANCH_GAMMA
BRANCH_BETA
CMP $7E8006 ;Maximum X position
BMI BRANCH_ZETA
STZ $0FAA, X ;Stop speed
LDA #$0002
STA $7E783E ;Mark as hit right wall?
LDA $7E8006
BRANCH_ZETA
STA $0F7A, X ;Update (or cap if hit right wall) X position
BRANCH_GAMMA
LDA $0FAC, X ;Y speed
SEP #$20
CLC
ADC $0F81, X ;High byte of subpixel Y position
STA $0F81, X
REP #$20
AND #$FF00
XBA
BPL BRANCH_DELTA
ORA #$FF00
BRANCH_DELTA
ADC $0F7E, X ;Y position
CMP $7E8000 ;Min Y position
BPL BRANCH_EPSILON
LDA $7E8000
STA $0F7E, X ;Cap Y position
STZ $0FAC, X ;Stop Y speed
LDA $7E783E ;Please Nintendo, quit being stupid
LDA #$0004
STA $7E783E ;Hit top wall
RTS
BRANCH_EPSILON
CMP $7E8002 ;Max Y position
BMI BRANCH_THETA
STZ $0FAC, X ;Stop Y speed
LDA $7E783E
LDA #$0008
STA $7E783E ;Hit bottom wall
LDA $7E8002
BRANCH_THETA
STA $0F7E, X ;Update (or cap if hit bottom wall) Y position
RTS
}
JSR $D97D ;Handle wing flapping
{
JSR $D9A8 ;Calculate wing flap speed
{
LDA $0FAA ;X Speed
BPL BRANCH_ALPHA
EOR #$FFFF
INC A
BRANCH_ALPHA
STA $12
LDA $0FAC ;Y Speed
BPL BRANCH_BETA
EOR #$FFFF
INC A
BRANCH_BETA
CLC
ADC $12
BNE BRANCH_GAMMA
STA $7E7810
RTS
BRANCH_GAMMA ;Ridley is moving (and not exactly along a diagonal)
SEC
SBC $12
CMP $12
BPL BRANCH_DELTA
LDA $12
BRANCH_DELTA ;Get greater of two speeds
ASL A
ASL A
AND #$0F00
XBA
ASL A
CMP #$000E
BCC BRANCH_EPSILON
LDA #$000E
BRANCH_EPSILON ;At this point, A = 2*max(#$000E, SpeedInPixels*4)
TAX
LDA $D9ED, X ;0C, 0E, 10, 12, 1C, 20, 28, 30
BIT $0FAC
BMI BRANCH_ZETA
LSR A
BRANCH_ZETA ;If Ridley is moving upwards, double it.
STA $7E7810 ;Wing flapping speed?
RTS
}
LDA $7E7812 ;Wing flap counter, I suppose
SEC
SBC $7E7810 ;Wing flap speed
STA $7E7812
BPL BRANCH_ALPHA ;If counter < 0, advance wing flap frame
LDA #$0020
STA $7E7812
LDA $7E780E ;Wing flap frame
INC A
CMP #$000A
BCC BRANCH_BETA
LDA #$0000
BRANCH_BETA
STA $7E780E ;Update Wing flap frame
BRANCH_ALPHA
RTS
}
JSR $CAF5 ;Run Tail AI: Sound, control AI, X/Y positions, tail extension, hurt Samus
{
JSR $D2AA ;Play swishing sound if tail is moving quickly
{
LDA $7E2014 ;Tail parts angular speed
CMP #$0008
BMI BRANCH_ALPHA
LDA $7E781C ;A simple timer, seems to be specifically for this routine.
INC A
STA $7E781C
CMP #$0010
BMI BRANCH_BETA
LDA $7E781E ;Check if a sound is currently playing
BNE BRANCH_ALPHA
LDA #$0021 ;Sounds like a spinjump sound
JSL $80914D ;Play sound
BRANCH_ALPHA
LDA #$0000
STA $7E781C
BRANCH_BETA
RTS
}
LDA $7E2000 ;Tail control index
ASL A
TAX
JSR ($CB21, X) ;CB20, CBC0, CB33, CB45, CBC7, CBCE, CB4E, CB60, CBD5 (See 7E:2000 in Ridley's ram)
PHB
PEA #$7E7E
PLB
PLB
JSR $CEBA ;Update tail positions
{
LDA $0F7E ;Ridley Y position
CLC
ADC $2032 ;Ridley to Tail 1 Adjustment
CLC
ADC #$0010 ;Hardcoded adjustment
STA $202E ;Tail 1 Y position
CLC
ADC $2046 ;Tail 1 to Tail 2 Adjustment
STA $2042 ;Tail 2 Y position
CLC
ADC $205A ;etc
STA $2056
CLC
ADC $206E
STA $206A
CLC
ADC $2082
STA $207E
CLC
ADC $2096
STA $2092
CLC
ADC $20AA
STA $20A6
LDA $7820 ;Facing direction
DEC A
BEQ BRANCH_ALPHA
INC A
ASL A
TAX
LDA $A6CF54, X
ADC $2030 ;Ridley to Tail 1 Adjustment, sorta
BRANCH_ALPHA ;A depends on 7820: 0 => $2030 + #$20, 1 => #$0, 2 => $2030 + #$FFE0
CLC
ADC $0F7A ;Ridley X position
STA $202C ;Tail 1 X position
LDA $7820
DEC A
BNE BRANCH_BETA
LDA $0F7A
STA $2040
STA $2054
STA $2068
STA $207C
STA $2090
STA $20A4 ;If $7820 = 1, all tail X positions are the same as Ridley's X position
BRA BRANCH_GAMMA ;and RTS
BRANCH_BETA
LDA $202C ;Tail 1 X position
CLC
ADC $2044 ;Tail 1 to Tail 2 adjustment
STA $2040 ;Tail 2 X position
CLC
ADC $2058 ;etc.
STA $2054
CLC
ADC $206C
STA $2068
CLC
ADC $2080
STA $207C
CLC
ADC $2094
STA $2090
CLC
ADC $20A8
STA $20A4
BRANCH_GAMMA
RTS
}
JSR $CF5A ;Tail extending
{
LDA $203C ;Target extension distance
BEQ BRANCH_ALPHA
CMP $203A ;Distance from tail 1 to tail 2
BPL BRANCH_BETA
LDA #$0000
STA $203C
BRANCH_BETA
LDA $203A
CLC
ADC $2012 ;Extension speed (Initialized to F0)
CMP #$1800 ;Cap at 18 pixels
BMI BRANCH_GAMMA
LDA #$1800
BRANCH_GAMMA
STA $203A
BRA BRANCH_DELTA
BRANCH_ALPHA
LDA #$0800 ;Default distance is 8 pixels
CMP $203A
BPL BRANCH_DELTA
LDA $203A
SEC
SBC #$0080 ;Pullback speed is 1/2 pixel a frame
STA $203A
BRANCH_DELTA
LDA $2050 ;Same for Tail 2
BEQ BRANCH_EPSILON
CMP $204E
BPL BRANCH_ZETA
LDA #$0000
STA $2050
BRANCH_ZETA
LDA $204E
CLC
ADC $2012
CMP #$1800
BMI BRANCH_THETA
LDA #$1800
BRANCH_THETA
STA $204E
BRA BRANCH_IOTA
BRANCH_EPSILON
LDA #$0800
CMP $204E
BPL BRANCH_IOTA
LDA $204E
SEC
SBC #$0080
STA $204E
BRANCH_IOTA
LDA $2064 ;Same for Tail 3
BEQ BRANCH_KAPPA
CMP $2062
BPL BRANCH_LAMBDA
LDA #$0000
STA $2064
BRANCH_LAMBDA
LDA $2062
CLC
ADC $2012
CMP #$1600 ;16 pixel max distance cap
BMI BRANCH_MU
LDA #$1600
BRANCH_MU
STA $2062
BRA BRANCH_NU
BRANCH_KAPPA
LDA #$0800
CMP $2062
BPL BRANCH_NU
LDA $2062
SEC
SBC #$0080
STA $2062
BRANCH_NU
LDA $2078 ;Same for Tail 4
BEQ BRANCH_XI
CMP $2076
BPL BRANCH_OMICRON
LDA #$0000
STA $2078
BRANCH_OMICRON
LDA $2076
CLC
ADC $2012
CMP #$1600
BMI BRANCH_PI
LDA #$1600
BRANCH_PI
STA $2076
BRA BRANCH_RHO
BRANCH_XI
LDA #$0800
CMP $2076
BPL BRANCH_RHO
LDA $2076
SEC
SBC #$0080
STA $2076
BRANCH_RHO
LDA $208C ;Same for Tail 5
BEQ BRANCH_SIGMA
CMP $208A
BPL BRANCH_TAU
LDA #$0000
STA $208C
BRANCH_TAU
LDA $208A
CLC
ADC $2012
CMP #$1200 ;12 pixel max distance cap
BMI BRANCH_UPSILON
LDA #$1200
BRANCH_UPSILON
STA $208A
BRA BRANCH_PHI
BRANCH_SIGMA
LDA #$0800
CMP $208A
BPL BRANCH_PHI
LDA $208A
SEC
SBC #$0080
STA $208A
BRANCH_PHI
LDA $20A0 ;Same for Tail tip
BEQ BRANCH_CHI
CMP $209E
BPL BRANCH_PSI
LDA #$0000
STA $20A0
BRANCH_PSI
LDA $209E
CLC
ADC $2012
CMP #$0500 ;5 pixel max distance cap
BMI BRANCH_OMEGA
LDA #$0500
BRANCH_OMEGA
STA $209E
BRA BRANCH_ALTIMA
BRANCH_CHI
LDA #$0500 ;and also min distance cap. <_<
CMP $209E
BPL BRANCH_ALTIMA
LDA $209E
SEC
SBC #$0080
STA $209E
BRANCH_ALTIMA
RTS
}
PLB
LDA $0F86
AND #$0400 ;Enemy/Samus interaction
ORA $18A8 ;Samus Invincibility
ORA $7E7836 ;Ridley is holding Samus
BNE BRANCH_ALPHA
JMP $DFD9 ;Tail/Samus interaction
{
LDA #$000E
STA $16
STA $18
LDA $7E20A4 ;Tail tip X position
STA $12
LDA $7E20A6 ;Tail tip Y position
STA $14
JSR $DF29 ;Surprisingly efficient collision detection. I'm going to have to steal this code.
{
LDA $0AF6 ;Samus's X position
SEC
SBC $12 ;Tail tip X position
BPL BRANCH_ALPHA
EOR #$FFFF
INC A
BRANCH_ALPHA ;Absolute X distance between Samus and Tail tip
SEC
SBC $0AFE ;Samus X Radius
BCC BRANCH_BETA
CMP $16 ;#$000E
BCS BRANCH_GAMMA
BRANCH_BETA
LDA $0AFA ;Samus Y position
SEC
SBC $14 ;Tail tip Y position
BPL BRANCH_DELTA
EOR #$FFFF
INC A
BRANCH_DELTA ;Absolute Y distance between Samus and Tail tip
SEC
SBC $0B00 ;Samus Y Radius
BCC BRANCH_EPSILON
CMP $18 ;#$000E
BCC BRANCH_EPSILON
BRANCH_GAMMA
CLC ;No collision
RTS
BRANCH_EPSILON
SEC ;Collision
RTS
}
BCC BRANCH_ALPHA
LDA $7E7838 ;Tail tip damage
JSL $A0A45E ;Divide A (damage) by suit damage divisor.
JSL $91DF51 ;Deal damage to Samus. Should not be negative or #$12C (300)
LDA #$0060
STA $18A8 ;Samus's invincibility time
LDA #$0005
STA $18AA ;Samus's pushback timer
LDY #$0000
LDA $0AF6 ;Samus's X position
SEC
SBC $7E20A4 ;Tailtip X position
BMI BRANCH_BETA
INY
BRANCH_BETA
STY $0A54 ;Direction to push Samus
BRANCH_ALPHA
RTS
}
BRANCH_ALPHA
RTS
}
JSR $E088 ;Tail tip kills projectiles
{
LDA $0F86
AND #$0400 ;Check Enemy/Samus interaction
BEQ BRANCH_ALPHA
RTS ;Do nothing if disabled
BRANCH_ALPHA
LDA #$000E
STA $16
STA $18
LDA $7E20A4 ;Tail tip X position
STA $12
LDA $7E20A6 ;Tail tip Y position
STA $14
JSR $DEA6 ;Check Tail/Projectile collisions
{
LDA $0CCE ;Check projectile counter
BNE BRANCH_ALPHA
CLC ;Leave if no projectiles
RTS
BRANCH_ALPHA
LDY #$0000
BRANCH_THETA
LDA $0C18, Y ;Check projectile types
BPL BRANCH_BETA
XBA
AND #$000F
CMP #$0003
BPL BRANCH_BETA ;Skip projectile if powerbomb (3) or bomb (5)
LDA $0B64, Y ;Projectile X position
SEC
SBC $12 ;Tail tip X position
BPL BRANCH_GAMMA
EOR #$FFFF
INC A
BRANCH_GAMMA ;Get absolute X distance between projectile and tail
SEC
SBC $0BB4, Y ;Projectile X radius
BCC BRANCH_DELTA
CMP $16 ;Tail tip X radius
BCS BRANCH_BETA
BRANCH_DELTA
LDA $0B78, Y ;Projectile Y position
SEC
SBC $14 ;Tail tip Y position
BPL BRANCH_EPSILON
EOR #$FFFF
INC A
BRANCH_EPSILON ;Get absolute Y distance between projectile and tail
SEC
SBC $0BC8, Y ;Projectile Y radius
BCC BRANCH_ZETA
CMP $18 ;Tail tip Y radius
BCC BRANCH_ZETA
BRANCH_BETA ;No collision
INY
INY ;Next projectile
CPY #$000A ;Max = 5 projectiles (10 slots, but top 5 are for bombs)
BMI BRANCH_THETA ;Check next projectile
CLC ;No collisions
RTS
BRANCH_ZETA
LDA $12
STA $0B64, Y
LDA $14
STA $0B78, Y ;Move projectile to tail tip?
LDA $0C04, Y
ORA #$0010 ;Kill projectile
STA $0C04, Y
SEC ;Collision
RTS
}
BCS BRANCH_$136126
LDA #$000A
STA $16
STA $18
LDA $7E2090 ;Tail part 6 X position
STA $12
LDA $7E2092 ;Tail part 6 Y position
STA $14
JSR $DEA6 ;Check Tail/Projectile collisions for tail part 6
BCS BRANCH_$136126
RTS
...
BRANCH_$136126
LDA $0B64, Y ;Projectile X position (now tail X position)
STA $12
LDA $0B78, Y ;Projectile Y position (now tail Y position)
STA $14
LDA $0C19, Y ;Projectile type
AND #$000F
LDY #$000C
DEC A
BNE BRANCH_ALPHA
LDA #$003D
JSL $809049 ;Sound for missile collisions (dud hit? Not checked)
LDY #$0006 ;Dud explosion instead of yellow smoke
BRANCH_ALPHA
TYA
LDY #$E509
JSL $868097 ;Spawn animation (yellow smoke, unless missile, then dud explosion)
RTS
}
JSR $DB2A ;Draw tail
{
LDA $0F86
AND #$0100 ;Ridley is invisible? Not sure when this happens
BEQ BRANCH_ALPHA
RTS
BRANCH_ALPHA
LDA $7E20A4 ;Tail tip X position
STA $12
LDA $7E20A6 ;Tail tip Y position
STA $14
LDA $7E20A2 ;Angle of tail tip.
CLC
ADC $7E208E ;Angle of tail part 6
CLC
ADC #$0008
AND #$00F0
LSR A
LSR A
LSR A
TAX
LDY $DCBA, X ;Graphic entry for different rotations for tail tip. Format: First 2 bytes = number of tiles, bytes 3-4 = X offset byte, 5 = Y offset, byte 6-7 = character + flip + priority
JSR $DBC2 ;General use draw, 7E7818 has pallete, Y is pointer to sprite data.
{
LDA $7E7818 ;Wing/Tail pallete
STA $16
JMP $DC13
...
$A6DC13
LDA $0000, Y
INY
INY
STA $18 ;Number of tiles, I'm guessing
LDX $0590 ;OAM 'stack' pointer
CLC
BRANCH_EPSILON
LDA $0001, Y ;Sprite's Y position offset from tail
AND #$FF00
BPL BRANCH_ALPHA
ORA #$00FF
BRANCH_ALPHA
XBA
CLC
ADC $14 ;Tail's Y position
SEC
SBC $0915 ;Scroll Y offset
BMI BRANCH_BETA
CMP #$00E0 ;Bottom of screen
BPL BRANCH_BETA ;Skip (go to Beta) if off screen
STA $1A ;Sprite's Y position on screen
LDA $0000, Y ;Sprite's X position offset from tail (2 bytes)
ADC $12 ;Tail's X position
SEC
SBC $0911 ;Scroll X position
STA $0370, X ;X Coordinate of sprite (1 byte)
AND #$0100
BEQ BRANCH_GAMMA
LDA $81859F, X
STA $1C
LDA ($1C)
ORA $81839F, X
STA ($1C) ;Set extra bit for X position if necessary
BRANCH_GAMMA
LDA $0000, Y
BPL BRANCH_DELTA
LDA $81859F, X
STA $1C
LDA ($1C)
ORA $8183A1, X
STA ($1C) ;Set extra bit for Size(?) if necessary
BRANCH_DELTA
LDA $1A ;Sprite's Y position on screen
STA $0371, X ;Y coordinate of sprite (1 byte)
LDA $0003, Y ;Character, flip, priority (can, but should not, contain pallete choice)
ORA $16 ;Pallete
STA $0372, X ;Sprite's Character, pallete, priority, flip.
TXA
CLC
ADC #$0004
AND #$01FF
TAX ;Move to next OAM slot
BRANCH_BETA
TYA
CLC
ADC #$0005
TAY ;Move to next sprite to draw
DEC $18 ;Decrement sprite counter
BNE BRANCH_EPSILON ;If more sprites to draw, loop for next sprite
STX $0590 ;Else update the OAM 'stack' pointer
RTS
}
LDA $7E2092 ;Tail part 6 Y position
STA $14
LDA $7E2090 ;Tail part 6 X position
STA $12
LDY #$DC9E ;Small tail graphic
JSR $DBC2 ;General use draw, 7E7818 has pallete, Y is pointer to sprite data.
LDA $7E207C ;Tail part 5 X position
STA $12
LDA $7E207E ;Tail part 5 Y position
STA $14
LDY #$DC9E ;Small tail graphic
JSR $DBC2 ;General use draw, 7E7818 has pallete, Y is pointer to sprite data.
LDA $7E2068 ;Tail part 4 X position
STA $12
LDA $7E206A ;Tail part 4 Y position
STA $14
LDY #$DC97 ;Medium tail graphic
JSR $DBC2 ;General use draw, 7E7818 has pallete, Y is pointer to sprite data.
LDA $7E2054 ;Tail part 3 X position
STA $12
LDA $7E2056 ;Tail part 3 Y position
STA $14
LDY #$DC97 ;Medium tail graphic
JSR $DBC2 ;General use draw, 7E7818 has pallete, Y is pointer to sprite data.
LDA $7E2040 ;Tail part 2 X position
STA $12
LDA $7E2042 ;Tail part 2 Y position
STA $14
LDY #$DC90 ;Large tail graphic
JSR $DBC2 ;General use draw, 7E7818 has pallete, Y is pointer to sprite data.
LDA $7E202C ;Tail part 1 X position
STA $12
LDA $7E202E ;Tail part 1 Y position
STA $14
LDY #$DC90 ;Large tail graphic
LDA $7E7818 ;Pallete for Wing/Tail
STA $16
JMP $DC13 ;General use draw, $16 has pallete, Y is pointer to sprite data.
}
JSR $DAD8 ;Drawing routine for Ridley's wings
{
LDA $7E7820 ;Facing direction
BEQ BRANCH_ALPHA ;Facing left
DEC A
BEQ BRANCH_BETA ;Facing front
LDA #$000A ;Facing right
BRANCH_ALPHA
CLC
ADC $7E780E ;Wing flap frame
ASL A
TAX
LDY $DB02, X ;Pointer table: DD4A, DD6A, DD85, DD96, DDA7, DDC2, then backwards down to DD6A, DDE2, DE02, DE1D, DE2E, DE3F, DE5A, back down to DE02
LDA $7E7818 ;Wing/Tail pallete
STA $16
LDA $0F7A ;Ridley X Position
STA $12
LDA $0F7E ;Ridley Y Position
STA $14
JMP $DC13 ;General use draw, $16 has pallete, Y is pointer to sprite data.
BRANCH_BETA
RTS
}
JSR $DA0C ;Animate Ridley's ribs
{
LDA $7E780C ;Some sort of timer/counter, initialized to 1
DEC A
STA $7E780C
BNE BRANCH_$135A0B ;An RTS
LDA $7E780A ;Pointer to new graphic data to update
BRANCH_BETA
TAX
LDA $0000, X
BPL BRANCH_ALPHA ;Positive means New graphic data
STA $7E780A ;Negative means pointer to next New graphic data
BRA BRANCH_BETA
BRANCH_ALPHA
STA $7E780C
LDY $0330 ;'Stack' index for graphics to update
LDA #$B000
STA $00D3, Y
STA $00DA, Y ;Set source banks to B0
LDA $0002, X
STA $00D2, Y
LDA $0004, X
STA $00D9, Y ;Get and set source addresses
LDA #$7220
STA $00D5, Y
LDA #$7320
STA $00DC, Y ;Set target VRAM (E440 and E640)
LDA #$0040
STA $00D0, Y
STA $00D7, Y ;Size is 40 bytes
TYA
CLC
ADC #$000E
TAY
STY $0330
LDA #$0000
STA $00D0, Y
TXA
CLC
ADC #$0006
STA $7E780A ;Go to next New graphic data
RTS
}
LDA $7E7836 ;Check if Ridley is holding Samus
BEQ BRANCH_BETA
JSR $B9E1 ;If holding Samus, move Samus to within Ridley's claws
{
LDA $7E7828 ;X Displacement for Ridley grabbing Samus
BEQ BRANCH_ALPHA
STA $12
BPL BRANCH_BETA
EOR #$FFFF
INC A
BRANCH_BETA ;Absolute value of 7E7828, other than 0
SEC
SBC #$0004
BPL BRANCH_GAMMA
LDA #$0000
BRA BRANCH_DELTA
BRANCH_GAMMA
BIT $12
BPL BRANCH_DELTA
EOR #$FFFF
INC A
BRANCH_DELTA
STA $7E7828 ;Basically, as a signed value, reduce by 4 every frame, minimum of 0
BRANCH_ALPHA
LDA $7E782A ;Y Displacement for Ridley grabbing Samus
BEQ BRANCH_EPSILON
STA $12
BPL BRANCH_ZETA
EOR #$FFFF
INC A
BRANCH_ZETA
SEC
SBC #$0004
BPL BRANCH_THETA
LDA #$0000
BRA BRANCH_IOTA
BRANCH_THETA
BIT $12
BPL BRANCH_IOTA
EOR #$FFFF
INC A
BRANCH_IOTA
STA $7E782A ;Same, as a signed value, reduce by 4 every frame, minimum of 0
BRANCH_EPSILON
LDA $7E7820 ;Facing direction
ASL A
TAY
LDA $B9D5, Y ;Normal Ridley to Samus X distance
ADC $0F7A ;Ridley's X position
CLC
ADC $7E7828 ;X displacement
STA $0AF6 ;Samus's X position
LDA $7E783A ;Unknown, only used for this
TAY
LDA $B9DB, Y ;Normal Ridley to Samus Y distance
CLC
ADC $0F7E ;Ridley's Y position
CLC
ADC $7E782A ;Y displacement
STA $0AFA ;Samus's Y position
RTS
}
BRANCH_BETA
JSR $D474 ;Determine and set Ridley's speed and color pallete
{
LDA #$0000
LDY $0F8C ;Ridley's health
CPY #$2328 ;9000 (of 18000)
BCS BRANCH_ALPHA
INC A
CPY #$1518 ;5400 (of 18000)
BCS BRANCH_ALPHA
INC A
CPY #$0708 ;1800 (of 18000)
BCS BRANCH_ALPHA
INC A
BRANCH_ALPHA
STA $7E7824 ;General Speed modifier, 0 - 3
DEC A
STA $12
BMI BRANCH_BETA
LDA $7EC400 ;Unknown
BNE BRANCH_BETA
LDA $12
ASL A
ASL A
ASL A
SEC
SBC $12
ASL A
ASL A ;Multiplied by 28 in decimal
CLC
ADC #$E46A
TAY
LDX #$01E2
LDA #$000E
JSL $A9D2E4 ;Copy 2*A bytes from (Y) to 7E:C000,X
BRANCH_BETA
RTS
}
RTL
}
E84D: Fireball angle/speed calculation
{
PHX
PHY
LDA $7E7820 ;Facing direction
BNE BRANCH_ALPHA ;Branch if facing right
LDA #$FFE7 ;-19 pixels
CLC
ADC $0F7A ;Ridley's X position
STA $12
LDA $0AF6 ;Samus's X position
SEC
SBC $12
STA $12 ;$12 = Samus_X - Ridley_X + 19
LDA #$FFD5 ;-2B pixels
CLC
ADC $0F7E ;Ridley's Y position
STA $14
LDA $0AFA ;Samus's Y position
SEC
SBC $14
STA $14 ;$14 = Samus_Y - Ridley_Y + 2B
JSL $A0C0AE ;Rough angle calculation given X (in $12) and Y (in $14). Angle 0 = up (-Y), 40 = right (X), 80 = down (Y), C0 = left (-X)
SEC
SBC #$0080 ;Now FF80 = up, FFC0 = right, 0 = down, 40 = left, 80 = up
EOR #$FFFF ;Now FF80 = up, FFC0 = left, 0 = down, 40 = right, 80 = up
INC A
AND #$00FF ;Now 0 = down, 40 = right, 80 = up, C0 = left
CMP #$00B0
BCS BRANCH_BETA
CMP #$0040
BCC BRANCH_GAMMA
LDA #$00B0 ;If between 40 and B0, use B0 (Left up-left)
BRA BRANCH_DELTA
BRANCH_BETA
CMP #$00EB
BCC BRANCH_DELTA
BRANCH_GAMMA
LDA #$00EB ;If above EB or below 40, use EB (Down down-left)
BRANCH_DELTA
STA $12
BRA BRANCH_EPSILON
BRANCH_ALPHA
LDA #$0019 ;19 pixels
CLC
ADC $0F7A ;Ridley's X position
STA $12
LDA $0AF6 ;Samus's X position
SEC
SBC $12
STA $12 ;Samus_X - Ridley_X - 19
LDA #$FFD5 ;2B pixles
CLC
ADC $0F7E ;Ridley's Y position
STA $14
LDA $0AFA ;Samus's Y position
SEC
SBC $14
STA $14 ;Samus_Y - Ridley_Y + 2B
JSL $A0C0AE ;Rough angle calculation given X (in $12) and Y (in $14). Angle 0 = up (-Y), 40 = right (X), 80 = down (Y), C0 = left (-X)
SEC
SBC #$0080 ;Now FF80 = up, FFC0 = right, 0 = down, 40 = left, 80 = up
EOR #$FFFF ;Now FF80 = up, FFC0 = left, 0 = down, 40 = right, 80 = up
INC A
AND #$00FF ;Now 0 = down, 40 = right, 80 = up, C0 = left
CMP #$0050
BCC BRANCH_ZETA
CMP #$00C0
BCS BRANCH_THETA
LDA #$0050 ;If between 50 and C0, use 50 (Right up-right)
BRA BRANCH_IOTA
BRANCH_ZETA
CMP #$0015
BCS BRANCH_IOTA
BRANCH_THETA
LDA #$0015 ;If below 15 or above C0, use 15 (down down-right)
BRANCH_IOTA
STA $12
BRANCH_EPSILON ;$12 contains angle
LDA #$0500
JSL $86C26C ;Calculates A * sin ($12 * 360/256), result in A.
STA $7E7832 ;X component of speed
LDA #$0500
JSL $86C272 ;Calculates A * cos ($12 * 360/256), result in A.
STA $7E7834 ;Y component of speed
PLY
PLX
RTL
}
Tail Routines
CD24: Tail bouncing
{
JSR $CBFE
{
LDA $7820 ;Direction facing
ASL A
TAX
LDA $A6CC12, X ;3FF0, 3FF0, 3FC0
STA $2016 ;Minimum Angle
LDA $A6CC18, X ;4040, 4040, 4010
STA $2018 ;Maximum Angle
RTS
}
JSR $CC1E
{
LDA $2020 ;0 = not rotating?, 8000 = rotating?
AND $2034
AND $2048
AND $205C
AND $2070
AND $2084
AND $2098
BEQ BRANCH_ALPHA
SEC
RTS
BRANCH_ALPHA
CLC ;Don't branch if all tail parts are rotating
RTS
}
BCC BRANCH_ALPHA ;Skip
LDA $05E5 ;Random number
AND #$00FF
CMP #$00F0 ;1/10 chance of skipping distance check
BCS BRANCH_BETA
LDA $0AF6 ;Samus X
SEC
SBC $000F7A ;Ridley X. o_O
BPL BRANCH_GAMMA
EOR #$FFFF
INC A
BRANCH_GAMMA ;Absolute X distance
CMP #$0080 ;Half a screen
BCS BRANCH_ALPHA
BRANCH_BETA ;All tail parts are rotating, + 1/10 chance or Ridley is within 1/2 a screen of Samus.
LDA $201C ;Optional maximum
AND $201A ;Optional minimum
BPL BRANCH_ALPHA
LDA #$3F00
STA $201A
LDA #$0008
STA $2014 ;Tail parts' angular speed
RTS
BRANCH_ALPHA
LDA $2020 ;I think these are all flags for each tail segment. Minus means that tail part is moving angularly?
ORA $2034
ORA $2048
ORA $205C
ORA $2070
ORA $2084
ORA $2098
BEQ BRANCH_DELTA ;Branch if none are rotating
RTS
BRANCH_DELTA
BIT $0FAC ;Ridley's Y speed
BMI BRANCH_EPSILON
LDA #$0005
STA $2000 ;Tail control index
BRANCH_EPSILON
LDA #$FFFF
STA $201A
STA $201C ;Disable optional caps
LDA $2010
BNE BRANCH_ZETA
BRANCH_THETA
STA $2014 ;Angular speed of Ridley's tail parts
RTS
BRANCH_ZETA
DEC A
STA $2010 ;Some sort of timer?
BNE BRANCH_THETA
LDA #$8000
STA $2020 ;Set first tail part to rotating
JSR $CE65 ;Set angles to 40XX, XX is previous angle (fifth part is actually first part's 40XX)
{
LDA $202A ;Angle of first tail part
AND #$00FF
ORA #$4000
STA $202A
LDA $203E ;Angle of second tail part
AND #$00FF
ORA #$4000
STA $203E
LDA $2052 ;Angle of third tail part
AND #$00FF
ORA #$4000
STA $2052
LDA $2066 ;Angle of fourth tail part
AND #$00FF
ORA #$4000
STA $2066
LDA $202A ;Angle of first tail part
AND #$04FF
ORA #$4000
STA $207A ;Angle of fifth tail part
LDA $208E ;Angle of sixth tail part
AND #$00FF
ORA #$4000
STA $208E
LDA $20A2 ;Angle of tail tip
AND #$00FF
ORA #$4000
STA $20A2
RTS
}
LDA #$0008
STA $2014
RTS
}
CC39: Fling tail at Samus:
Setup max angles (CBFE), then if tail is 'prepped' (all tail parts rotating, target angle not set yet, $2004 (trigger?) is set), target an angle.
Target angle is first projectile near tail tip, in a 8x8 tile square centered on tail tip, or Samus. Max rotational speed, 8.
If no tail parts are currently moving, start the first one moving.
{
JSR $CBFE ;Set min and max tail angles based on direction
JSR $CC1E ;SEC if all tail parts are rotating, else CLC
BCC BRANCH_ALPHA
JSR $CC7D ;
{
LDA $2004 ;Tail fling trigger
BEQ BRANCH_ALPHA
LDA $201C
AND $201A
BMI BRANCH_BETA ;Branch if optional limits are unused
BRANCH_ALPHA
LDA $2002 ;Main battle AI flag (0 = inactive, 1 = active, FFFF = dead)
BEQ BRANCH_GAMMA
LDA $05E5 ;RNG
AND #$00FF
CMP #$00F0
BCS BRANCH_BETA ;Branch 1/10 times
LDA $0AF6 ;Samus X position
SEC
SBC $0F7A ;Ridley X position
BPL BRANCH_DELTA
EOR #$FFFF
INC A
BRANCH_DELTA ;Absolute distance
CMP #$0080 ;1/2 a screen
BCS BRANCH_GAMMA
LDA #$0000
BRA BRANCH_EPSILON
BRANCH_BETA ;If Norfair, only here if 2004 is set and angle targets are currently unused
LDA $2004
DEC A
BRANCH_EPSILON
JSR $D19D ;Target an angle (towards a missile or Samus) for tail. Note: Actual angle is actually twice the angle chosen, since each tail segment doubles it. Also, tail circles 2*A amount of times first
{
AND #$00FF
XBA
STA $200A ;Revolutions to make
LDA $7820 ;Direction facing
DEC A
BEQ BRANCH_ALPHA ;Branch if facing forward
LDA $7802 ;Main battle AI
BEQ BRANCH_ALPHA ;Branch if inactive
JSR $D242 ;Target a missile/super missile if available
{
LDA $20A4 ;Tail tip X position
STA $12
LDA $20A6 ;Tail tip Y position
STA $14
LDA #$0040 ;Tail tip detection area
STA $16 ;X size
STA $18 ;Y size
LDA $0CCE ;Samus's projectile counter
BNE BRANCH_ALPHA ;Branch if there are projectiles
CLC
RTS
BRANCH_ALPHA
LDY #$0000 ;Start loop, projectile 0 (of 4)
BRANCH_IOTA
LDA $0C19, Y
AND #$000F ;Projectile type
DEC A
BEQ BRANCH_BETA ;Branch if missile
DEC A
BNE BRANCH_GAMMA ;Branch if not super missile
BRANCH_BETA ;Missiles and super missiles go here
LDA $0B64, Y ;X position of projectile
SEC
SBC $12 ;Ridley's tail X position
BPL BRANCH_DELTA
EOR #$FFFF
INC A
BRANCH_DELTA ;Absolute distance
SEC
SBC $0BB4, Y ;Projectile X size
BCC BRANCH_EPSILON
CMP $16 ;Tail tip X size
BCS BRANCH_GAMMA ;Branch if miss
BRANCH_EPSILON
LDA $0B78, Y ;Y position of projectile
SEC
SBC $14 ;Y position of Ridley's tail
BPL BRANCH_ZETA
EOR #$FFFF
INC A
BRANCH_ZETA ;Absolute distance
SEC
SBC $0BC8, Y ;Projectile Y size
BCC BRANCH_THETA
CMP $18 ;Tail tip Y size
BCC BRANCH_THETA ;Branch if hit
BRANCH_GAMMA
INY
INY ;Next projectile
CPY #$000A
BMI BRANCH_IOTA ;Branch if still between projectiles 0 - 4
CLC
RTS
BRANCH_THETA
LDA $0B64, Y
STA $12
LDA $0B78, Y
STA $14 ;Put projectile X/Y into $12/$14
SEC
RTS
}
BCC BRANCH_BETA ;Branch if no missile/supermissile targets
LDA $12
SBC $202C ;Tail part 1 X position
STA $12
LDA $14
SEC
SBC $202E ;Tail part 1 Y position
STA $14
BRA BRANCH_GAMMA
BRANCH_ALPHA
RTS
BRANCH_BETA
LDA $0AF6 ;Samus X position
SEC
SBC $202C ;Tail part 1 X position
STA $12
LDA $0AFA ;Samus Y position
CLC
ADC #$0018 ;+18 pixels
SEC
SBC $202E ;Tail part 1 Y position
STA $14
BRANCH_GAMMA
PHB
PHK
PLB
JSL $A0C0AE ;Rough angle calculation given X (in $12) and Y (in $14). Angle 0 = up (-Y), 40 = right (X), 80 = down (Y), C0 = left (-X)
PLB
SEC
SBC #$0080
EOR #$FFFF
INC A
AND #$00FF ;0 = down (Y), 40 = right (X), 80 = up (-Y), C0 = left (-X)
STA $12
LDA $7820 ;Direction facing
BNE BRANCH_DELTA ;Branch if facing right
LDA $12
CMP #$0018 ;down down-right
BCC BRANCH_EPSILON
CMP #$00E8 ;down down-left
BCS BRANCH_EPSILON
LDA #$00E8
BRANCH_EPSILON ;Caps are E8 - 18, if 19 - E7, use E8 instead.
CLC
ADC #$3F00
SEC
SBC $200A ;Number of revolutions to spin tail
CMP $202A ;Angle of tail part 1
BCS BRANCH_ZETA
STA $201A ;Optional lower (clockwise) target
LDA #$0008
STA $2014
BRANCH_ZETA
RTS
BRANCH_DELTA ;Facing right
LDA $12
CMP #$0018 ;down down-right
BCC BRANCH_THETA
CMP #$00E8 ;down down-left
BCS BRANCH_THETA
LDA #$0018
BRANCH_THETA ;Caps are E8 - 18, if 19-E7, use 18 instead.
CLC
ADC #$4000
CLC
ADC $200A ;Number of revolutions to spin tail
CMP $202A ;Angle of tail part 1
BCC BRANCH_IOTA
STA $201C ;Optional upper (counterclockwise) target
LDA #$0008
STA $2014
BRANCH_IOTA
RTS
}
PLA
BRANCH_GAMMA
STZ $2004
RTS
}
BRANCH_ALPHA
LDA $2020
ORA $2034
ORA $2048
ORA $205C
ORA $2070
ORA $2084
ORA $2098
BEQ BRANCH_BETA ;Branch if no tail parts are rotating
RTS
BRANCH_BETA
LDA #$8000
STA $2020 ;Start first tail part rotating
LDA #$FFFF
STA $201A
STA $201C ;Disable target angles
LDA #$0002
LDY $0AF6
CPY #$0070
BCS BRANCH_GAMMA
LDA #$0001
BRANCH_GAMMA
STA $2014 ;Rotation speed = 2 if Samus is on the right half of the screen, 1 if on the left. Why?
RTS
}
CCBD: Swing tail in circles
{
JSR $CBFE ;Set min and max tail angles based on direction
JSR $CC1E ;SEC if all tail parts are rotating, else CLC
BCC BRANCH_ALPHA
JSR $CD0C ;
{
LDA $2004 ;Tail fling trigger
BEQ BRANCH_ALPHA
LDA $201C
AND $201A ;Target limits
BPL BRANCH_ALPHA
LDA #$0001
JSR $D19D ;Target an angle (towards a missile or Samus) for tail. Note: Actual angle is actually twice the angle chosen, since each tail segment doubles it. Also, tail circles 2*A amount of times first
PLA
STZ $2004
BRANCH_ALPHA
RTS
}
BRANCH_ALPHA
LDA $7E2020
ORA $7E2034
ORA $7E2048
ORA $7E205C
ORA $7E2070
ORA $7E2084
ORA $7E2098
BEQ BRANCH_BETA ;Branch if all tail parts are still
RTS
BRANCH_BETA
LDA #$8000
STA $7E2020 ;Set first part to rotating
LDA #$FFFF
STA $7E201A
STA $7E201C ;Disable target angles
LDA #$0002
LDY $0AF6
CPY #$0070
BCS BRANCH_GAMMA
LDA #$0001
BRANCH_GAMMA
STA $7E2014 ;Rotation speed = 2 if Samus is on the right half of the screen, 1 if on the left. Why?
RTS
}
CDAA: Extend tail. Happens only while tail bouncing, moving downwards, and no tail parts currently rotating
{
JSR $CBFE ;Set min and max tail angles based on direction
JSR $CC1E ;SEC if all tail parts are rotating, else CLC
BCC BRANCH_ALPHA ;Always branches?
{ ;All this code NEVER HAPPENS! Just go to Branch_Alpha
LDA $05E5 ;Random number
AND #$00FF
CMP #$00F0 ;1/10 chance of branching
BCS BRANCH_BETA
LDA $0AF6 ;Samus's X position
SEC
SBC $000F7A ;Ridley's X position
BPL BRANCH_GAMMA
EOR #$FFFF
INC A
BRANCH_GAMMA ;Absolute distance
CMP #$0080 ;1/2 a screen
BCS BRANCH_ALPHA
BRANCH_BETA
LDA $201C
AND $201A
BPL BRANCH_ALPHA ;Branch if both target angles are used
LDA #$3F00
STA $201A ;Set lower (clockwise) target angle
LDA #$0008
STA $2014
RTS
}
BRANCH_ALPHA
LDA $2020
ORA $2034
ORA $2048
ORA $205C
ORA $2070
ORA $2084
ORA $2098
BEQ BRANCH_DELTA ;Branch if no tail parts are rotating. Always branches?
RTS
BRANCH_DELTA
BIT $0FAC ;Ridley's Y movement
BMI BRANCH_EPSILON ;Branch if moving up. Never branches?
LDA #$0006
STA $2000
LDA #$0A00
STA $2028
STA $203C
STA $2050
STA $2064
STA $2078
STA $208C
STA $20A0 ;Set all tail parts' target extension distance to A pixels
LDA #$4000
STA $202A
STA $203E
STA $2052
STA $2066
STA $207A
STA $208E
STA $20A2 ;Set all tail parts' angles to straight down
LDA #$8000
STA $2020 ;Start tail part 1 rotating
BRANCH_EPSILON
LDA #$FFFF
STA $201A
STA $201C ;Disable target angles
LDA $2010 ;Some sort of timer? Always 0 / never used?
BNE BRANCH_ZETA
JMP BRANCH_THETA ; ...
BRANCH_ZETA
DEC A
STA $2010
BNE BRANCH_THETA
LDA #$8000
STA $2020 ;Start tail part 1 rotating
JSR $CE65 ;Set all tail angles to 40XX
LDA #$0008
BRANCH_THETA
STA $2014
RTS
}