[18:54] You'll get to see what it is Christmas [18:55] Aw [18:55] That's so far from now [18:55] but I guess I can give a hint for now... assuming I can come up with a good hint [18:55] ok [18:56] It's the most useless item in Super Metroid [18:56] grapple? I need to come up with harder hints. >_> Grapple pose animation frame numbers: 00 - 1F = moving (1 revolution clockwise from up) 20 - 3F = end of push off of wall (same) 40+ = at rest, downwards TODO: NEED A BLUE SUIT SPEED CHECK... I'll stick it in the grapple motion code. Ram, with changes (- = removed, + = added, : = unchanged) -7E:0CF4 - 7E:0CF5 Flags. First bit set if Samus is in liquid, last bit cleared when grapple beam hits grapple block (not enemy). +7E:0CF4 - 7E:0CF5 Flags. 0 set if Samus is in liquid, F set if grapple shot connected, E set if grapple shot exists, 1 set if connected to grapple block, 2 set if connected to enemy that can pull, 3 if enemy grapple-pull code unless it collides with ground, 4 if enemy uses grapple pull code always. -7E:0CF6 - 7E:0CF7 Unknown, set to A when grapple is fired +7E:0CF6 - 7E:0CF7 Target grapple length :7E:0CF8 - 7E:0CF9 Force slow/stupid-scrolling? Screen scrolls at 3 pixels per frame. Enabled during grappling, disabled when grapple beam is newly shot. :7E:0CFA - 7E:0CFB Something for grapple beam graphics (Angle from grapple beam to grapple point) -7E:0CFC - 7E:0CFD Something for grapple beam graphics (Angle from grapple beam to grapple point) +7E:0CFC - 7E:0CFD Length of grapple beam (subpixels) :7E:0CFE - 7E:0CFF Length of grapple beam (pixels) -7E:0D00 - 7E:0D01 Speed of grapple beam (length). Set to C when starting grapple beam. +7E:0D00 - 7E:0D01 X-dot of grapple beam length (1/100 pixels/frame). Handled like real physics -7E:0D02 - 7E:0D03 X offset of grapple point relative to Samus -7E:0D04 - 7E:0D05 Y offset of grapple point relative to Samus +7E:0D02 - 7E:0D03 X position of Grapple point previous frame +7E:0D04 - 7E:0D05 Y position of Grapple point previous frame :7E:0D06 - 7E:0D07 Sub-pixel X position of Grapple point :7E:0D08 - 7E:0D09 X position of Grapple point :7E:0D0A - 7E:0D0B Sub-pixel Y position of Grapple point :7E:0D0C - 7E:0D0D Y position of Grapple point -7E:0D0E - 7E:0D0F 32-bit running sum of X speed * 64 -7E:0D10 - 7E:0D11 32-bit running sum of X speed * 64 +7E:0D0E - 7E:0D0F X block position of Grapple point +7E:0D10 - 7E:0D11 Y block position of Grapple point -7E:0D12 - 7E:0D13 32-bit running sum of Y speed * 64 -7E:0D14 - 7E:0D15 32-bit running sum of Y speed * 64 +7E:0D12 - 7E:0D13 New X block position of Grapple point +7E:0D14 - 7E:0D15 New Y block position of Grapple point -7E:0D16 - 7E:0D17 X position of start of grapple beam (Basically same as 0D1A?) -7E:0D18 - 7E:0D19 Y position of start of grapple beam (Basically same as 0D1C?) +7E:0D16 - 7E:0D17 X position of 'top' of Samus's head +7E:0D18 - 7E:0D19 Y position of 'top' of Samus's head :7E:0D1A - 7E:0D1B X position of start of grapple beam :7E:0D1C - 7E:0D1D Y position of start of grapple beam -7E:0D1E - 7E:0D1F Unknown. Cleared when starting grapple beam +7E:0D1E - 7E:0D1F 0DC6 mirror 7E:0D20 - 7E:0D21 Unknown. Cleared when starting grapple beam :7E:0D22 - 7E:0D23 X Speed of grapple point (1/100 pixels/frame). +Samus's forward-direction X adjustment :7E:0D24 - 7E:0D25 Y Speed of grapple point (1/100 pixels/frame). +Samus's forward-direction Y adjustment :7E:0D26 - 7E:0D27 Angular velocity, signed (+ = clockwise, - = counterclockwise) 7E:0D28 - 7E:0D29 Unknown. Cleared when starting grapple beam 7E:0D2A - 7E:0D2B Unknown. Cleared when starting grapple beam 7E:0D2C - 7E:0D2D Unknown. Cleared when starting grapple beam 7E:0D2E - 7E:0D2F Angular velocity boost (signed) from pushing off of wall 7E:0D30 - 7E:0D31 Unknown. Cleared when starting grapple beam 7E:0D32 - 7E:0D33 Pointer to code for grapple beam. Usually C4F0 (start beam, not active), C703 is firing beam (not hitting anything), C856 is force-cancel beam? :7E:0D34 - 7E:0D35 Direction to fire (grapple beam specific?) 7E:0D36 - 7E:0D37 Unknown. Cleared when starting grapple beam 7E:0D38 - 7E:0D39 Unknown. Cleared when starting grapple beam 7E:0D3A - 7E:0D3B Unknown. Set to 2 when starting grapple beam 7E:0D3C - 7E:0D3D Unknown. Cleared when starting grapple beam :7E:0D3E - 7E:0D3F Grapple point animation timer. Set to 5 when starting grapple beam :7E:0D40 - 7E:0D41 Grapple point animation pointer. Set to 8200 when starting grapple beam -7E:0D42 - 7E:0D61 Grapple segment animation instruction timers. Similar to PLM setup -7E:0D62 - 7E:0D81 Grapple segment animation instruction pointers. Similar to PLM setup +7E:0D42 - 7E:0D43 Grapple segment direction (horiz = 8220, diag = 8A20, vert = 9220) +7E:0D44 - 7E:0D45 Angle of Samus while grappling +7E:0D46 - 7E:0D4D Temp values. X0 - X3 / V0 - V3 +7E:0D4E - 7E:0D55 Temp values. Y0 - Y3 / A0 - A3 +7E:0D56 - 7E:0D57 'Long' term temp value. 1/100th revolutions Samus attempts to swing this frame. +7E:0D58 - 7E:0D7F Temp array, X/Y of blocks to check for collisions with Samus. +7E:0D80 - 7E:0D81 'Stack' index for 0D58 7E:0D82 - 7E:0D83 Variable, cleared when starting grapple beam. 32-bit Signed X speed * 64 during grapple collision detection. Used also as a temporary JMP target 7E:0D84 - 7E:0D85 Variable, cleared when starting grapple beam. 32-bit Signed X speed * 64 7E:0D86 - 7E:0D87 Variable, cleared when starting grapple beam. 32-bit Signed Y speed * 64 7E:0D88 - 7E:0D89 Variable, cleared when starting grapple beam. 32-bit Signed Y speed * 64 7E:0D8A - 7E:0D8B Variable, cleared when starting grapple beam. Counter during grapple collision detection 7E:0D8C - 7E:0D8D Unknown. Cleared when starting grapple beam 7E:0D8E - 7E:0D8F Unknown. Cleared when starting grapple beam 7E:0D90 - 7E:0D91 Unknown. Cleared when starting grapple beam. X Position of grapple start, calculated from grapple point and grapple length (94:A957) 7E:0D92 - 7E:0D93 Y position of grapple start, calculated from grapple point and grapple length 7E:0D94 - 7E:0D95 Grapple start's block X position, calculated from above 7E:0D96 - 7E:0D97 Grapple start's block X position, calculated from above 7E:0D9C - 7E:0D9D Total grapple speed this frame ((speed + boost) * water effect) Complete overhaul on grapple beam: Last item, select will deselect grapple beam, item cancel will not necessarily. If there is a grapple shot in screen, item cancel will kill the grapple shot. If there isn't, item cancel will deselect grapple. When a grapple shot is connected to something, Samus's main beam will be available with the fire button. New enemy responces to grapple beam: Stop while beam is on enemy, Samus can pull enemy (8000) Stop while beam is on enemy, Samus can grapple from enemy (8005) Stop while beam is on enemy, Samus can grapple from enemy, enemy falls from gravity (8014) Stop while beam is on enemy, Samus can pull enemy, enemy falls from gravity (8019) Continue moving, but unable to move past beam (Samus can pull enemy) (800F) Continue moving, enemy can pull Samus (0002) (Done) Die (will be rare) (800A) Stop grapple beam (0001) (Done) Completely ignore grapple beam (0000) (Done) Samus's controls while grappling... Run + Down pulls grapple to Samus - does not crouch or aim down Run + Up pushes grapple from Samus - does not aim up If Samus can pull the enemy, no change from normal controls. If enemy can pull Samus, Samus has two modes of movement Normal movement within grapple beam range Grapple swing at grapple beam range Press Run in mid-air to switch to grapple swing Press Jump to pull Samus towards enemy from grapple swing, goes to spin jump/normal movement Collision with ground while swinging will put Samus into normal movement Attempting to move past grapple range will put Samus into grapple movement Easy jump-away hook: Holding away and jumping will cancel the grapple shot There's already a routine that handles grapple beam graphics. Score. 94:AFBA uses 0D08 and 0D0C (grapple point X/Y), 0D1A and 0D1C (grapple start X/Y), 0CFA (grapple beam angle), 0CFE (grapple beam length). Does all the other work from there. Things to do with AFBA: Make it calculate the angle itself, or not do redundant calculations for the angle. Will decide when I recode grapple physics. Also: Make the graphics routine simply pick a random graphic from the available angle list, *every* frame. No more preset graphics patterns. Hunted a bit for the routine that did it already. Decided to forget about it and program one myself. Load angle, if negative, subtract 80. Subtract 40, if negative, invert. Result is angle from 0 to 40. 00 - 10 = 8220, 11 - 2F = 8A20, 30 - 40 = 9220. Compare with old value, if different, write to D0 to update. (0080 bytes, 9AXXXX, target 6210) Also for grapple spot: move from animation to animation every 5 frames. (Start at 8200, add 200 every 5 frames, if 8A00 restart to 8200). Another D0 write All right, animation tweaking is working perfectly, I think. Next is the real physics changing part. List of things to change: Samus's pose data for grapple positions, maybe the transition table too Grapple instructions Enemy responses (I'll do this last) Item Cancel tweak Pull of grapple beam will be in enemy code (for enemy pullable) or grapple code (for Samus pullable) 94A85B tweak: don't need 4x checking. Also might need to edit a few flags/plms/other 9BBD95 tweak: Change angle slightly according to d-pad. Might optimize as well. 94ACFE currently handles all movement and collision detection for Samus's grappling JSR $AB90,X (X = 2*blocktype) is the actual collision code Need to add a routine to make Samus refire the grapple beam if she changes directions Graphics: Compare X and Y distances, divide larger value by 'speed' in that direction, use that as # of segments to draw 0D32s to change: 9BC490 (grapple movement routine) 91D748 (Pallete related, I think) 91D911 (Sound related, I think) 90EB86 (unknown, 0A5C. Samus's graphic display?) 809C85 (Cancel 'cancel sound' if grapple is active?) 90C58A (setup for when Grapple is selected) 90D525 looks like it's never called... 90DD3D (Common Arm cannon code before select index. Hi-jack this) 90DD74 (Turning Arm cannon code. Kills grapple shot from the looks of it) 90DDB6 (Spin Jump, Hurt, and Spin Back Arm cannon code. Kills grapple shot too) 90E2A1 (Some case for 0A5A, grabbed by Draygon) (looks like it's for aiming - prevents change in pose if currently firing?) A59618 (Draygon's death code) 9BB987 (Special case stuff for Draygon, shouldn't need to worry about I think) 90F2B8 (JSL that checks if grapple beam is currently firing) Let's start with the 'grapple selected' code. There are three possibilities in this mode: Samus is in a grapple pose: Load movement type, compare to grapple, continue if equal If Samus is extending or shortening grapple, adjust current max. Done Samus has a grapple shot connected: I'll make a flag for this somewhere. Load flag, if set, continue If cancel is pressed, kill shot. Goto 'Samus is not currently firing' If Grapple range > absolute max, kill shot. Goto 'Samus is not currently firing' If Samus is extending or shortening grapple, adjust current max. Done Samus is currently firing / able to fire a grapple shot. The 'else' case. Basically the grapple code already available. If Samus is currently firing, check if fire is held. If not, kill shot. Done If so, do nothing. Grapple shot will handle its own movement If Samus is not currently firing, check if fire is being newly pressed. If so, start new shot. Done If not, do nothing. Done 'Arm Cannon: Grapple Selected' In a more code-like structure: if Samus has a connected grapple shot if Samus is in grapple pose, go check current max adjustment else if cancel is pressed, goto kill shot else if grapple range > absolute max, goto kill shot adjust range of grapple beam if Samus is currently firing if shot is not held kill shot if Samus is not firing if shot is newly pressed start shot Grapple shot code for 'Connected, not grappling' if enemy can pull Samus if run is newly pressed if Samus in air, put Samus into grapple pose (move if necessary) and set initial speed else if Grapple range > current max if Samus on ground if angle is within $20 from a horizontal, slide Samus else if Samus can be pulled towards enemy, move Samus and put in grapple pose else extend Grapple range. If resulting range is > absolute max, kill shot. else put into grapple pose (move if necessary) and set initial speed if collision with ground, set to standing Grapple shot code for 'Grappling' Move Samus according to current speed (normal and angular) Collision with ground: Change Samus to standing if angle is within $20 from a horizontal, slide Samus extend Grapple range as necessary. If resulting range is > absolute max, kill shot. Collision with other wall: if angle is within $20 from a horizontal, slide Samus extend Grapple range as necessary. If resulting range is > absolute max, kill shot. Reduce current speeds (will need to mess with options for this. Also: Account for liquid/Gravity Suit) Adjust normal speed based on distance from current max Convert gravity (account for liquid/gravity suit - probably use 0B32) to normal/tangential and add Add speed according to d-pad (left = clockwise, right = counter) Grapple shot code for 'Inactive' (DONE) ... nothing. Arm cannon handles firing (DONE) Grapple shot code for 'Firing' Extend (DONE) Collision detection for enemies (JSL $A09E9A) (eh. I'll do it later) Collision detection for blocks (rewrite $94A85B) (DONE) Grapple pose code Just need to add allowances for transitioning out, I think. Press Jump to pull Samus towards enemy from grapple swing, goes to spin jump/normal movement Collision with ground while swinging will put Samus into normal movement Attempting to move past grapple range will put Samus into grapple movement Easy jump-away hook: Holding away and jumping will cancel the grapple shot Also need to change the stupid/slow scroll to be smart/fast scroll. (DONE) ;Generic code to add a vector to a position. $12 = angle, A = distance ;AddVectorToPosition: ; PHA ; JSL $86C26C ; ADC XPos ; STA XPos ; PLA ; JSL $86C272 ; EOR #$FFFF ; INC ; ADC YPos ; STA YPos FINAL CODE ASSEMBLED IN XKAS: ;TODO list: ALL enemy stuff, fix echoes appearance (maybe), prevent too-fast scroll bugs. Tests if landing needs to adjust 0AF6 ;Change grapple check to work with new grapple flags ;Allows picking up item drops, may do other (hopefully benificial) things org $90F2C5 print "Boundary: ",pc GrappleCheck: LDA $0CF4 print "Boundary: ",pc org $90F0C8 print "Boundary: ",pc DW GrappleCheck ;$844B5-$84538 print "Boundary: ",pc org $90C4B5 print "Boundary: ",pc PHP REP #$30 LDA $09D2 STA $12 LDA $8F BIT $09B8 BEQ + JSR CancelCheck BRA ++ + STZ $16 LDA $8B BIT $09B8 BEQ + INC $16 + LDA $8F BIT $09BA BEQ +++ LDA $09D2 INC A CMP #$0005 ;No more x-ray scope! BMI + -- LDA #$0000 + STA $09D2 - ASL A TAX JSR ($C539,X) ; $84539 IN ROM BCC + INC $09D2 LDA $09D2 CMP #$0005 BMI - BRA -- + LDA $16 BEQ + LDA $09D2 STA $0A04 BRA ++ + STZ $0A04 ++ LDA $09D2 CMP $12 BNE + +++ LDA $0AAA CMP #$0002 BEQ ++ INC A STA $0AAA BRA ++ + LDA #$0001 STA $0AAA ++ PLP RTS print "Boundary: ",pc org $A0C0AE print "Boundary: ",pc PHP REP #$30 PHX PHY PHB PHK PLB LDX #$0000 TXY LDA $12 BPL + LDX #$0004 EOR #$FFFF INC A STA $12 + LDA $14 BPL + INX INX EOR #$FFFF INC A STA $14 + SEP #$20 XBA LDA $12 CMP $14 BCS ++ ;Branch if $14 is not bigger than $12 XBA INX ++ STZ $4204 REP #$20 STA $4205 PHX TYX LDA #$00B8 STA $14 JSR GetAngleAdjustment PLX BIT.w AngleSign-1,X BPL + EOR #$FFFF INC + CLC ADC #$0080 ;0000 + 00C0 = 01, 0000 - 0140 = FF, 0000 + 0040 = 00, 0000 - 0040 = 00 STA $12 LDA.w AngleStart-1,X AND #$FF00 CLC ADC $12 XBA AND #$00FF PLB PLY PLX PLP RTL GetAngleAdjustment: LDA $4214 LDY #$0009 - DEY ASL BCC - - DEY BEQ + LSR INX INX BRA - + XBA AND #$00FF ASL TAY LDA.w AngleIndexes,X STA $12 LDA [$12],Y RTS AngleStart: DB $40,$80,$40,$00,$C0,$80,$C0,$00 AngleSign: DB $00,$80,$80,$00,$80,$00,$00,$80 AngleIndexes: ; DW $FFFC,$FFF4,$FFE4,$FFC4,$FF84,$FF04,$FE04,$FC04 DW $FC04,$FE04,$FF04,$FF84,$FFC4,$FFE4,$FFF4,$FFFC EndCheck: print "Boundary: ",pc org $B8FC04 print "Boundary: ",pc incbin AnglesT.bin print "Boundary: ",pc org $90DD6F print "Boundary: ",pc JSL PreGrappleMain print "Boundary: ",pc org $90DD69 print "Boundary: ",pc DW CallGrappleArmCannon print "Boundary: ",pc org $94ACFE print "Boundary: ",pc GrappleMotion: PHB PHK PLB LDA $0D26 BEQ ++ CLC ADC $0CFA XBA SEP #$21 SBC $0CFB STA $0D56 BEQ + JSR SwingCollisionCheck BCS ++ ;Carry set on collision, cleared on no collision + REP #$21 LDA $0D26 ADC $0CFA ;Carry cleared because no collision STA $0CFA LDA $0D26 CLC ADC $0D44 STA $0D44 ++ LDA $0D00 CLC ADC $0CFD XBA AND #$00FF CMP #$0008 BPL + LDA #$0008 + SEC SBC $0CFE BEQ NoCollision2b JSR LengthCollisionCheck BCS AdjustSpeed ;It'll branch if there *is* a collision. ;print "Start of Angular Momentum conservation: ", pc LDA $0CFE ADC #$0014 STA $4202 LDA $0D26 PHP BPL + EOR #$FFFF INC + STA $4203 JSR ConserveAngularMomentum ;JSR and RTS cycles waste time while waiting for hardware results. :) LDA $4214 PLP ;Also does REP #$20 for me BPL + EOR #$FFFF INC + STA $0D26 BRA AdjustSpeed NoCollision2b: LDA $0D00 CLC ADC $0CFD CMP #$0800 BPL + LDA #$0800 + STA $0CFD AdjustSpeed: LDA $0CF6 XBA SEC SBC $0CFD PHP BPL + EOR #$FFFF INC + ; PHA ;Not used atm. Might enable if I want a different fraction. LSR LSR ;Hmm... This doesn't seem right. Need to tinker with the fraction. ; PLX ;Just getting rid of trash (well, it's trash now) on the stack PLP BPL + EOR #$FFFF INC + CLC ADC $0D00 CLC BPL + SEC + ROR STA $0D00 LDA $0CF4 ;Check if in water w/o gravity LSR LDA $0D26 BEQ GrappleGravity PHP BPL + EOR #$FFFF INC + STA $16 BCS + LSR ;Bigger fraction if not in water ADC $16 LSR ADC $16 LSR ADC $16 + LSR ;Smaller fraction if in water ADC $16 LSR ADC $16 LSR CLC ADC $16 LSR ADC $16 LSR DEC PLP BPL + EOR #$FFFF INC + STA $0D26 ;Now for gravity... GrappleGravity: LDA $0D45 AND #$00FF ASL TAX LDA $A0B443,X ASL CLC ADC $A0B443,X ASL ASL ASL AND #$FF00 XBA BPL + ORA #$FF00 + CLC ADC $0D16 SEC SBC $0D08 STA $12 LDA $A0B3C3,X ASL CLC ADC $A0B3C3,X ASL ASL ASL AND #$FF00 XBA BPL + ORA #$FF00 + CLC ADC $0D18 SEC SBC $0D0C STA $14 JSL CalculateVectorLength TAY LDA #$0800 STA $4204 SEP #$20 TYA STA $4206 REP #$21 LDA $A0B3C3,X ;TODO: Currently, Gravity's effect on vertical displacement is .1 pix/frame^2. Might be tweaked later. LSR LSR LSR LSR BIT #$FE00 ;This is imprecise, but it'll work for most formulas so it's fine BEQ + ORA #$FE00 ;Ditto + CLC ADC $0D00 STA $0D00 LDY $4214 LDA $A0B443,X JSL SignedMultiplication BNE + CPX #$0100 BEQ +++ BMI ++ DEC $0D26 BRA +++ + BPL ++ ;Small increase for gravity to aid movement when near center DEC DEC ++ SEC ;INC and CLC at the same time ADC $0D26 STA $0D26 ;After gravity, I'm *done* +++ JSR SamusGrappleAngle JSL $9BBD95 ;Er. *Now* I'm done PLB RTL ConserveAngularMomentum: XBA LDY $4216 STY $12 STA $4203 CLC STZ $14 LDA $13 ADC $4216 STA $4204 LDA $0CFD CLC ADC $0D00 CMP #$0800 BPL + LDA #$0800 STZ $0D00 + STA $0CFD XBA SEP #$21 ADC #$13 STA $4206 PHA TDC LDA $12 XBA REP #$20 NOP ORA $4216 ;Guaranteed to be under 100 XBA STA $4204 SEP #$20 PLA LDY $4214 STA $4206 TDC TYA XBA NOP RTS print "Boundary: ",pc org $9094F7 ;Start of grapple-scroll code print "Boundary: ",pc LDA $0CFB AND #$00FF STA $12 LDA $0D26 BPL Skip90 LDA $12 EOR #$0080 STA $12 LDA $0D26 EOR #$FFFF INC Skip90: BIT #$F000 BEQ + LDA #$0FFF + ASL ASL ASL PHA JSL $86C272 JSR ScrollSetupNum JSR HorizontalScroll PLA ; ASL JSL $86C26C JSR ScrollSetupNum JSR VerticalScroll JSL $80A528 ; $2528 IN ROM JSL $80A731 ; $2731 IN ROM BRA Skip92 print "Boundary: ",pc org $909563 print "Boundary: ",pc Skip92: print "Boundary: ",pc org $90DD21 print "Boundary: ",pc DW TurningGrapple print "Boundary: ",pc org $90DD33 print "Boundary: ",pc DW TurningGrapple print "Boundary: ",pc org $90DD35 print "Boundary: ",pc DW TurningGrapple ;Should be DONE print "Boundary: ",pc org $90DD3D print "Boundary: ",pc PHP REP #$30 LDA $0CF4 BEQ + JSL GrappleMain + LDA $09D2 ASL A TAX JSR ($DD61, X) ; $85D61 IN ROM PLP RTS print "Boundary: ",pc org $9BC490 print "Boundary: ",pc LDA $0CF4 BPL NoConnection LDA $8B AND #$0C00 BEQ +++ BIT #$0800 BNE + LDA $0CF6 DEC DEC CMP #$0010 BPL ++ LDA #$0010 BRA ++ + LDA $0CF6 INC INC CMP #$006F BMI ++ LDA #$006E ++ STA $0CF6 +++ PLA PLB JML $90B80D ;Hooray for 'bad' coding NoConnection: BNE + STZ $0CD0 ;Works, but still need palette fix on item cancel LDA $8F ORA $0E00 ;Check if fire was pressed last frame BIT $09B2 BEQ + PHB PHK PLB JMP CreateShot + RTL ;$86B86-$86BF1 print "Boundary: ",pc org $90EB86 print "Boundary: ",pc LDA $0CF4 BNE + LDA #$0007 JSL $809049 ;Augh. Playing this disables spin jump sounds, not playing this causes too much grapple sounds. LDA #$EB52 STA $0A5C LDA #$2C0F STA $7EC6B0 STA $7EC6B2 JMP $EB52 + JSR $EEE7 JSR $87BD LDA $0CF4 BPL + LDA $0CF6 LSR STA $4204 LDA #$0A00 STA $4205 SEP #$20 JSR DrawTargetLength BEQ + JSR $BAFC BRA ++ + JSL $9BC036 ; $DC036 IN ROM ++ JSR $8A4C ; $80A4C IN ROM JSR $85E2 ; $805E2 IN ROM LDA $0AAC AND #$000F BEQ + JSR $C663 ; $84663 IN ROM + JSL $9BCC00 ; $DBFA5 IN ROM LDA $0CFE BEQ + JSL $94AFBA ; $A2FBA IN ROM + RTS ;Arm cannon graphic print "Boundary: ",pc org $90C5F7 print "Boundary: ",pc JSR ACGHook ;Prevent high speed falling through ground print "Boundary: ",pc org $909256 print "Boundary: ",pc JSR HorizontalHighSpeedCheck print "Boundary: ",pc org $90E647 print "Boundary: ",pc JSR MirrorDirection print "Boundary: ",pc org $90E626 print "Boundary: ",pc JSR MirrorDirection print "Boundary: ",pc org $90FAD0 ;Just need free space. I think this is the best spot for free space. print "Boundary: ",pc ;An alternative to 0DC6! MirrorDirection: STA $0DC6 STA $0D1E RTS DrawTargetLength: NOP NOP NOP LDA $4214 DEC BPL ++ LDA #$09 ++ STA $7EC6B0 LDA $4216 DEC BPL ++ LDA #$09 ++ STA $7EC6B2 REP #$20 LDA $0A1F AND #$00FF CMP #$0016 RTS ACGHook: CMP #$0004 BNE ACGNormal LDA $0CF4 BPL ACGSet LDA $0A1F AND #$00FF CMP #$0016 BEQ ACGSet LDA #$0000 RTS ACGSet: LDA #$0001 RTS ACGNormal: LDA $C7D9,X RTS HorizontalScroll: ADC $0AF8 SEC SBC $090F STA $14 LDA $0AF6 SBC $0911 CLC ADC $16 JSR ScrollSub ADC $090F STA $090F LDA $16 STA $0DA2 ADC $0911 STA $0911 RTS VerticalScroll: ADC $0AFC SEC SBC $0913 STA $14 LDA $0AFA SBC $0915 CLC ADC $16 JSR ScrollSub ADC $0913 STA $0913 LDA $16 STA $0DA6 ADC $0915 STA $0915 RTS ScrollSetupNum: STZ $16 STZ $14 AND #$FFFF ;It's stupid, I know. But there's no TEST A. BPL Skip93 DEC $16 Skip93: STA $15 LDA $14 CLC RTS ScrollSub: SEC SBC #$0080 BPL ScrollRight LSR ROR $14 LSR ROR $14 ORA #$C000 CMP #$FFF0 BEQ ScrollCapped BPL Skip94 LDA #$FFF0 BRA ScrollCapped ScrollRight: LSR ROR $14 LSR ROR $14 CMP #$0010 BMI Skip94 LDA #$0010 ScrollCapped: STZ $14 Skip94: STA $16 CLC LDA $14 RTS CallGrappleArmCannon: JSL $9BC490 RTS ;org $90DD TurningGrapple: LDA $0CF4 BEQ + JSL GrappleMain - RTS + LDA $0B5E BEQ - JMP $DD3D CancelCheck: LDA $0A1F CMP #$0016 BEQ + LDA $0CF4 BMI ++ + STZ $0A04 STZ $09D2 ++ STZ $0CF4 RTS HorizontalHighSpeedCheck: LDA $0DBC CMP #$000F BMI + LDA #$000E + RTS print "Boundary: ",pc org $94AFBA ;(Grapple segment and point drawing. Not sure what calls it, but don't need to call it myself. Leave where it is) print "Boundary: ",pc PHB PHK PLB LDA $0CFB AND #$00FF EOR #$0080 ASL A TAX STZ $1A STZ $1C LDA $A0B443, X ASL A ASL A ASL A BPL BRANCH_ALPHA DEC $1C ;Makes $1D = #$FF BRANCH_ALPHA: STA $1B STZ $1E STZ $20 LDA $A0B3C3, X ASL A ASL A ASL A BPL BRANCH_BETA DEC $20 BRANCH_BETA: STA $1F LDA $0CFA AND #$8000 LSR A STA $26 EOR $0CFA AND #$4000 EOR #$4000 ASL A ORA $26 STA $26 LDA $0D1A SEC SBC $0911 SEC SBC #$0004 STA $14 STZ $12 LDA $0CFE BMI BRANCH_GAMMA ;uh. How? STA $4204 SEP #$20 LDA #$08 STA $4206 REP #$20 LDA $0D1C SEC SBC $0915 SEC SBC #$0004 STA $18 STZ $16 LDA $4214 BMI BRANCH_GAMMA ;Again. How? ; AND #$000F ;Should be redundant. I'll delete it, just in case I have unusually long grapple beams. ; SEC ; SBC #$0001 ;DEC would be faster. And from the looks of it, I *don't* want this. STA $28 ; JSL $808111 ;Improve random number generation, I hope BRANCH_THETA: LDA $14 ORA $18 AND #$FF00 BNE BRANCH_ZETA ;Branch if offscreen PHX JSL $808111 AND #$0003 CLC ADC #$3A21 ;Get 1 of 4 grapple beam graphics TAY JSR $B0AA ; This routine's good enough, let's leave it alone PLX DEX DEX DEC $28 BPL BRANCH_THETA BRANCH_ZETA: JSR $B14B ; Grapple Point Display B. A was deleted, B alone is good enough. BRANCH_GAMMA: PLB RTL print "Boundary: ",pc org $9BCC00 print "Boundary: ",pc DEC $0D3E BPL ++ LDA #$0005 STA $0D3E LDA $0D40 CLC ADC #$0200 CMP #$8A00 BMI + LDA #$8200 + STA $0D40 LDX $0330 LDA #$0020 STA $D0, X LDA $0D40 STA $D2, X LDA #$009A STA $D4, X LDA #$6200 STA $D5, X TXA CLC ADC #$0007 STA $0330 ++ SEP #$21 LDA $0CFB BPL + SBC #$80 + SBC #$40 BPL + EOR #$FF INC + LDY #$8220 CMP #$10 BMI + LDY #$8A20 CMP #$2F BMI + LDY #$9220 + REP #$20 CPY $0D42 BEQ + STY $0D42 LDX $0330 LDA #$0080 STA $D0, X STY $D2, X LDA #$009A STA $D4, X LDA #$6210 STA $D5, X TXA CLC ADC #$0007 STA $0330 + LDA $0CF4 CMP #$4000 BNE + LDA $0CD0 CMP #$0078 BPL + INC $0CD0 + RTL CreateShot: LDA #$0020 STA $0CCC LDA $0A04 BEQ + STZ $0A04 STZ $09D2 + STZ $0CF8 LDA #$0001 STA $0CD0 LDA #$0005 JSL $80903F LDA $0A1C ASL ASL ASL TAX LDA $91B62D,X AND #$00FF STA $16 LDA $91B62C,X AND #$00FF BIT #$00F0 BEQ + PLB RTL + STZ $0D06 STZ $0D0A STZ $0CFE STA $0D34 ASL TAX LDA #$4000 STA $0CF4 LDA #$EB86 STA $0A5C LDA #$7F91 STA $7EC1BE LDA #$0040 STA $0CF6 SEP #$20 LDA $0DB2 ORA $0DB5 BEQ + LDA $0DB2 XBA LDA $0DB5 BRA ++ + LDA $0DB6 XBA LDA $0DB9 ++ TAY LDA $0DAA ORA $0DAD BEQ + LDA $0DAA XBA LDA $0DAD BRA ++ + LDA $0DAE XBA LDA $0DB1 ++ REP #$21 ADC $C0DB,X BMI NegativeX CMP #$0F00 BMI StoreXSpeed LDA #$0F00 BRA StoreXSpeed NegativeX: CMP #$F100 BPL StoreXSpeed LDA #$F100 StoreXSpeed: STA $0D22 TYA CLC ADC $C0EF,X BMI NegativeY CMP #$0F00 BMI StoreYSpeed LDA #$0F00 BRA StoreYSpeed NegativeY: CMP #$F100 BPL StoreYSpeed LDA #$F100 StoreYSpeed: STA $0D24 LDA $C104,X STA $0CFA LDA $C122, X ;Initial grapple point X offset from Samus CLC ADC $0AF6 STA $0D08 ;X position of grapple point STA $0D02 LSR LSR LSR LSR STA $0D0E LDA $0A1F AND #$00FF DEC BEQ WalkingRunning LDA $C14A,X CLC ADC $0AF6 STA $0D1A ;X position of grapple start LDA $0AFA SEC SBC $16 PHA CLC ADC $C136, X STA $0D0C ;Y position of grapple point STA $0D04 LSR LSR LSR LSR STA $0D10 PLA CLC ADC $C15E, X STA $0D1C ;Y position of grapple start JMP GrappleCollisionDetection WalkingRunning: LDA $C19A,X CLC ADC $0AF6 STA $0D1A ;X position of grapple start LDA $0AFA SEC SBC $16 PHA CLC ADC $C186, X STA $0D0C ;Y position of grapple point STA $0D04 LSR LSR LSR LSR STA $0D10 PLA CLC ADC $C1AE, X STA $0D1C ;Y position of grapple start JMP GrappleCollisionDetection PreGrappleMain: LDA $09B6 ORA $09B4 AND $8F BEQ + JMP JumpTransition + LDA $0CF4 BNE + JMP FallingTransition + LDA $8B AND #$0C00 BEQ + BIT #$0800 BNE ++ LDA $0CF6 DEC DEC CMP #$0010 BPL +++ LDA #$0010 BRA +++ ++ LDA $0CF6 INC INC CMP #$006F BMI +++ LDA #$006E +++ STA $0CF6 + LDA $0B3F AND #$0004 BEQ GrappleConnected LDA $0D26 BPL + EOR #$FFFF INC + BIT #$F000 BEQ + LDA #$0FFF + ASL ASL ASL ASL AND #$FF00 ORA $0CFE ADC #$0018 STA $4202 LDA #$1800 ;Todo: Find a good number for this (minimum value for blue suit) CMP $4216 BMI GrappleConnected LDA #$0004 TRB $0B3F BRA GrappleConnected GrappleMain: LDA $0CF4 BMI GrappleConnected JMP GrappleFiring GrappleConnected: JSL $A09E9A BCC + ;Branch if no effect, no branch if effect on grapple beam BVS ++ ;Branch if Caught on enemy, no branch if stop beam. ; BRA + ;This is a temporary 'fix'. Will be deleted later BRA FallingTransition + JSL $94A91F BCC FallingTransition ;Branch if no effect block, no branch if effect beam BVC FallingTransition ;Branch if stop beam, no branch if caught on block LDA $0D08 AND #$FFF0 ORA #$0008 STA $0D08 LDA $0D0C AND #$FFF0 ORA #$0008 STA $0D0C ;Move grapple point to current block. LDA #$8002 ;Set Connected and Connection: Grapple Block TSB $0CF4 ++ ; LDA #$0006 ; JSL $809049 ; Play grapple-attached sound. Not sure if this should be played or not. LDA $0A1F AND #$00FF CMP #$0016 BEQ ++ LDY $0CF4 LDA #$001E TRB $0CF4 ;Delete old connections and check again next frame TYA BIT #$0006 BNE + JSL CalculateGrappleLengthA CMP #$0088 BPL +++ STA $0CFE TXA LSR XBA STA $0CFA RTL ; BIT #$0008 ; BEQ +++ ; JMP GrapplePullEnemy ;I think I'll have the enemy code do it instead + JMP GrapplePullSamus ++ JML GrappleMotion +++ STZ $0CF4 RTL ;V = w x r, Vx = w * r * sin (r + Dir * 40), Vy = w * r * (-cos (r + Dir * 40)) ;100 u = 2pi w, w = 29 u = (20 + 8 + 1) u, 101001 - LDA, ASL, ASL, ADC, ASL, ASL, ASL, ADC ;LSR speed before starting ;w = rad/frame(0000 - 0400 * 29 = 0000 - A400), r = radius (0CFE + #14) (14 - 94) ;(w * r)/256 * sin/cos = value from 0000 to 5ED0 (or A130 - 0000 - 5ED0) ;u = 0800 --> 0400, r = 0080 --> 0094, unaltered = 5ED0, goal = 1D0F. Divide by 343/100 (835/256 in decimal) ;unaltered / D * 8 FallingTransition: ;Convert angular speed to linear, set 0A32 to 7, 0A2C to 51(right) or 52(left) ;print "Start of FallingTransition: ",pc STZ $0CF4 STZ $0CF8 LDA $0A1F AND #$00FF CMP #$0016 BNE ++ LDA #$0007 STA $0A32 LDA #$0051 STA $0A2C JSR ConvertSpeedToLinear BEQ +++ BPL + EOR #$FFFF INC INC $0A2C + SEP #$20 STA $0B45 XBA STA $0B42 LDA #$01 STA $0B3C REP #$20 JSR SetNonGrapplePosition ++ RTL +++ LDA $0A1E AND #$0004 BEQ + INC $0A2C + JSR SetNonGrapplePosition RTL SetNonGrapplePosition: print "Break Grapple: ", pc PHB PHK PLB LDA $0D45 AND #$00FF ASL TAX LDY #$0020 LDA $A0B443,X JSL SignedMultiplication CLC ADC $0D1A STA $0AF6 SEC SBC #$0009 STA $12 ADC #$0011 LSR LSR LSR LSR STA $14 LDA $12 LSR LSR LSR LSR STA $12 LDA $A0B3C3,X JSL SignedMultiplication CLC ADC $0D1C STA $0AFA CLC ADC #$000C STA $16 SBC #$0017 LSR LSR LSR LSR STA $18 LDA $07A5 STA $4202 LDA $16 LSR LSR LSR LSR STZ $16 STA $4203 LDA $14 CLC ADC $4216 ASL PHA LDA $12 CLC ADC $4216 ASL JSR BlockTest BVC + INC $16 ;Bottom Left collision + PLA JSR BlockTest LDA $18 STZ $18 BVC + INC $18 ;Bottom Right collision + STA $4203 LDA $14 CLC ADC $4216 ASL PHA LDA $12 CLC ADC $4216 STZ $12 STZ $14 ASL JSR BlockTest BVC + INC $12 ;Top Left collision + PLA JSR BlockTest BVC + INC $14 ;Top Right collision + PLB ;print "PushTests: ", pc LDA $16 AND $18 BNE PushUp LDA $16 AND $12 BNE PushRight LDA $18 AND $14 BNE PushLeft LDA $12 AND $14 BEQ NoPush ;PushDown: LDA $0AFA AND #$FFF0 ORA #$000C STA $0AFA NoPush: RTS PushUp: LDA $0AFA AND #$FFF0 ORA #$0004 STA $0AFA LDA $0B2D LDY $0B36 DEY BNE + EOR #$FFFF INC + INY INY CLC ADC #$FE40 BPL + DEY EOR #$FFFF INC + STA $0B2D RTS PushRight: LDA $0AF6 AND #$FFF0 ORA #$0007 STA $0AF6 LDA #$0180 STA $12 BRA PushSideUp PushLeft: LDA $0AF6 AND #$FFF0 ORA #$0009 STA $0AF6 LDA #$FE80 STA $12 PushSideUp: SEP #$20 LDA $0B42 XBA LDA $0B45 REP #$20 LDY $0A2C CPY #$0019 BEQ + CPY #$001A BNE PushRight-1 EOR #$FFFF INC DEY + CLC ADC $12 BPL + INY EOR #$FFFF INC + STY $0A2C SEP #$20 STA $0B45 XBA STA $0B42 REP #$20 LDA $0B2D LDY $0B36 DEY BNE + EOR #$FFFF INC INY + INY CLC ADC #$FEC0 BPL + DEY EOR #$FFFF INC + STY $0B36 STA $0B2D RTS BTVE: ;Block Test Vertically Extended ;VerticallyExtended: LDA $01,S LSR TAX SEP #$21 LDA $7F6402,X BPL + EOR #$FF INC STA $4203 REP #$20 LDA $01,S SBC $4216 SEC SBC $4216 PLX BRA BlockTest + STA $4203 REP #$21 LDA $01,S ADC $4216 CLC ADC $4216 PLX BlockTest: - PHA TAX LDA $7F0003,X AND #$00F0 LSR LSR LSR LSR TAX BIT.w GrappleBlockTest-1,X BMI + ;Branch if extended block. PLX RTS ;V Set = Solid, V Clear = Air + BVS BTVE ;Extended block. Branch if vertically extended ;HorizontallyExtended: LDA $01,S LSR TAX LDA $7F6401,X AND #$FF00 XBA BPL + ORA #$FF00 + ASL CLC ADC $01,S PLX BRA - ++ JumpTransition: STZ $0CF4 STZ $0CF8 LDY #$0019 STY $0A2C LDY #$0007 ;I'm not sure about this STY $0A32 BIT $09B6 BNE ++ JSR ConvertSpeedToLinear STA $0D26 ;Save it for later LDA $0CFB EOR #$0080 AND #$00FF ASL TAX LDA $A0B3C3,X LDY #$0380 ;TODO: Tweak this till it's reasonable. Jump speed boost out of grapple JSL SignedWordMultiplication PHA LDA $0B2D DEC $0B36 BNE + EOR #$FFFF INC + LDY #$0002 STY $0B36 CLC ADC $01,S BPL + EOR #$FFFF INC DEC $0B36 + STA $0B2D PLA LDY #$0380 LDA $A0B443,X JSL SignedWordMultiplication CLC ADC $0D26 BRA + ++ JSR ConvertSpeedToLinear + BEQ ++ BPL + EOR #$FFFF INC INC $0A2C + CMP #$0700 BPL + STZ $0B3E + LDY #$0160 SEC SBC #$0160 BPL + ADC #$0160 TAY TDC + SEP #$20 STY $0B45 STA $0B45 XBA STA $0B42 TYA STA $0B49 LDA #$01 STA $0B3C REP #$20 JSR SetNonGrapplePosition RTL ++ LDA $0A1E AND #$0004 BEQ + INC $0A2C + JSR SetNonGrapplePosition RTL ;Uses $16. Converts 0D26, 0CFE, and 0CFB into 0B2D, 0B36, and signed X-Speed in A, ready to branch on sign, adjust pose, and put speed into 0B42/0B45 ;See FallingTransition for an example of use ConvertSpeedToLinear: STZ $16 LDA $0D26 BPL + EOR #$FFFF INC DEC $16 + CMP #$147A BMI + LDA #$147A + LSR STA $0D26 ASL CLC ADC $0D26 ASL ASL ASL CLC ADC $0D26 ;($0D26 * 12.5 decimal) XBA STA $4202 LDA $0CFE CLC ADC #$0014 STA $4203 LDA $0CFB CLC ADC #$0040 AND #$00FF BIT $16 BPL + EOR #$0080 + ASL TAX LDA $4216 LSR TAY LDA $A0B3C3,X JSL SignedWordMultiplication STZ $0B36 BPL + EOR #$FFFF INC DEC $0B36 + INC $0B36 INC $0B36 STA $0B2D LDA $A0B443,X JSL SignedWordMultiplication STZ $0B43 RTS CalculateGrappleLengthA: LDA $0AF6 STA $0D1A LDA $0AFA STA $0D1C CalculateGrappleLength: LDA $0D1A SEC SBC $0D08 STA $12 LDA $0D1C SEC SBC $0D0C STA $14 CalculateVectorLength: LDA $12 BPL + EOR #$FFFF INC + PHA LDA $14 BPL + EOR #$FFFF INC + CMP $01,S ;Carry set if Y >= X BCC GrappleLengthX XBA AND #$FF00 TAY PLA JSL $A0C0AE ASL TAX LDA $A0B3C3,X BIT #$00FF BEQ Cardinal BPL Skip06 Skip07: EOR #$FFFF INC Skip06: STY $4204 SEP #$20 STA $4206 REP #$20 NOP NOP NOP NOP NOP NOP LDA $4214 RTL GrappleLengthX: PLA XBA AND #$FF00 TAY JSL $A0C0AE ASL TAX LDA $A0B443,X BIT #$00FF BEQ Cardinal BMI Skip07 BRA Skip06 Cardinal: TYA XBA RTL GrappleFiring: PHB PHK PLB LDA $8B BIT $09B2 BEQ KillShot LDA $0A1C ASL ASL ASL TAX LDA $91B62D,X AND #$00FF STA $16 LDA $91B62C,X AND #$00FF BIT #$00F0 BEQ Branch_Something KillShot: STZ $0CF4 PLB RTL Branch_Something: ASL TAX LDA $0A1F AND #$00FF DEC BEQ + LDA $C14A,X CLC ADC $0AF6 STA $0D1A LDA $0AFA SEC SBC $16 CLC ADC $C15E, X STA $0D1C BRA ++ + LDA $C19A,X CLC ADC $0AF6 STA $0D1A ;X position of grapple start LDA $0AFA SEC SBC $16 CLC ADC $C1AE, X STA $0D1C ;Y position of grapple start ++ JSL CalculateGrappleLength STA $0CFE TXA LSR XBA STA $0CFA LDA $0CFE CMP #$0060 BPL KillShot SEP #$20 LDA $0D22 CLC ADC $0D07 STA $0D07 LDA $0D23 BPL + ADC $0D08 STA $0D08 LDA #$FF BRA ++ + ADC $0D08 STA $0D08 LDA #$00 ++ ADC $0D09 STA $0D09 LDA $0D24 CLC ADC $0D0B STA $0D0B LDA $0D25 BPL + ADC $0D0C STA $0D0C LDA #$FF BRA ++ + ADC $0D0C STA $0D0C LDA #$00 ++ ADC $0D0D STA $0D0D REP #$20 LDA $0D0C LSR LSR LSR LSR STA $0D14 LDA $0D0A LSR LSR LSR LSR STA $0D12 STZ $4204 CMP $0D0E BNE + JMP SameX + BPL MovedRight MovedLeft: LDA $0D14 CMP $0D10 BNE + JMP SameY + SEP #$20 BPL DownLeft UpLeft: LDA $0D04 XBA LDA $0D02 REP #$20 AND #$0F0F STA $4205 SEP #$20 LDA $0D0C XBA LDA $0D08 REP #$20 AND #$0F0F EOR #$0F0F LDY $4214 STA $4205 JMP CompareAngles DownLeft: LDA $0D04 EOR #$0F XBA LDA $0D02 REP #$20 AND #$0F0F STA $4205 SEP #$20 LDA $0D0C XBA LDA $0D08 EOR #$0F REP #$20 AND #$0F0F LDY $4214 STA $4205 BRA CompareAngles MovedRight: LDA $0D14 CMP $0D10 BEQ SameY SEP #$20 BPL DownRight UpRight: LDA $0D04 XBA LDA $0D02 EOR #$0F REP #$20 AND #$0F0F STA $4205 SEP #$20 LDA $0D0C EOR #$0F XBA LDA $0D08 REP #$20 AND #$0F0F LDY $4214 STA $4205 BRA CompareAngles DownRight: LDA $0D04 XBA LDA $0D02 REP #$20 AND #$0F0F EOR #$0F0F STA $4205 SEP #$20 LDA $0D0C XBA LDA $0D08 REP #$20 AND #$0F0F LDY $4214 STA $4205 CompareAngles: NOP NOP NOP NOP NOP NOP CPY $4214 BCS YThenX XThenY: LDA $0D12 STA $0D0E JSL $94A91F BCC SameX BlockAffect: BVS BlockGrapple JMP KillShot YThenX: LDA $0D14 STA $0D10 JSL $94A91F BCS BlockAffect SameY: LDA $0D12 STA $0D0E BRA GrappleCollisionDetection SameX: LDA $0D14 STA $0D10 GrappleCollisionDetection: JSL $94A91F BCS BlockAffect JSL $A09E9A BCC + BVC + LDA $0CFE CLC ADC #$0010 CMP #$006F BMI ++ LDA #$006E ++ STA $0CF6 + PLB RTL BlockGrapple: LDA $0D08 AND #$FFF0 ORA #$0008 STA $0D08 LDA $0D0C AND #$FFF0 ORA #$0008 STA $0D0C ;Move grapple point to current block. LDA #$8002 ;Set Connected and Connection: Grapple Block TSB $0CF4 LDA #$0006 JSL $809049 ; Play grapple-attached sound SetGrappleDefaults: JSL CalculateGrappleLengthA STA $0CFE CLC ADC #$0008 CMP #$006F BMI + LDA #$006E + STA $0CF6 TXA LSR XBA STA $0CFA LDA #$0008 CLC ADC $0CCC STA $0CCC LDA #$0001 TSB $0A64 STZ $0CD0 PLB RTL GrapplePullSamus: JSL CalculateGrappleLengthA STA $0CFE CMP #$0088 BMI + STZ $0CF4 - RTL + TXA LSR XBA STA $0CFA ; LDA $0B2E ; ORA $0B2C LDA $0B36 ;Proper on-ground check? BNE +++ ;Vertical speed: Check for run and length LDA $0D1E ;0B36 still fails when pulling up STZ $0D1E ;don't repeatedly assume to be on ground CMP #$0001 ;FINALLY seems to work BNE ++ ;Branch if still in air ;Ground: LDA $0CFE SEC SBC $0CF6 BMI - XBA LSR LSR CMP #$0800 ;Maximum force Grapple Beam can apply. This may need finetuning. BMI + LDA #$0800 + PHA LDA $0CFB AND #$00FF STA $12 LDA $01,S JSL $86C26C EOR #$FFFF INC CLC ADC $0B57 BPL + STZ $0B58 DEC $0B58 + STA $0B57 PLA JSL $86C272 ; EOR #$FFFF ; INC CLC ADC #$0180 ;Downward force of gravity. This will most likely need finetuning CLC ADC $0B5B BPL + STZ $0B5C DEC $0B5C + STA $0B5B BPL + LDA #$00FF TSB $0B5D + - RTL +++ LDA $0A68 BNE - LDA $8F BIT $09B6 BNE + ++ LDA $0CFE CMP $0CF6 BMI - STZ $0CF6 + PHB PHK PLB LDA $0AF6 SEC SBC $0D08 STA $12 LDA $0AFA SEC SBC $0D0C STA $14 JSL CalculateVectorLength SEP #$21 SBC #$0E CMP #$08 BPL + LDA #$08 + TAY REP #$20 STZ $18 STZ $16 - JSR GrappleVectorBlockCollision TYA CLC BVC + BIT $18 BMI ++ ADC #$0010 TAY DEC $18 BRA - + ADC #$000D JSR GrappleVectorBlockCollision BVS ++ TYA CLC ADC #$001A JSR GrappleVectorBlockCollision BVS ++ TYA CLC ADC #$0028 JSR GrappleVectorBlockCollision BVC SetGrappling BIT $18 BMI ++ DEC $18 DEC $16 TYA SEC SBC #$0010 TAY CMP #$0008 BPL +++ ++ - PLB RTL +++ BIT $18 BPL SetGrappling TYA CLC ADC #$000D JSR GrappleVectorBlockCollision BVS - SetGrappling: LDA $0CFE STY $0CFE LDX $0CF6 BNE + CPY #$006F BMI ++ LDY #$006E ++ STY $0CF6 BRA ++ + CMP $0CF6 BMI + SBC #$000E BIT $18 BPL ++ TYA BIT $16 BPL + SEC SBC #$0008 CMP $0CF6 BPL ++ BRA +++ + CLC ADC #$0008 CMP $0CF6 BMI ++ +++ SBC #$000E CMP #$006F BPL + CMP #$0010 BPL ++ LDA #$0010 BRA ++ + LDA #$006E STA $0CF6 ++ LDA #$0009 STA $0A30 LDY #$00B2 LDA $0A1E BIT #$0004 BEQ + LDY #$00B3 + STY $0A2A PLB RTL GrappleVectorBlockCollision: PHY TAY LDA $A0B443,X JSL SignedMultiplication CLC ADC $0D08 STA $12 LDA $A0B3C3,X JSL SignedMultiplication CLC ADC $0D0C LSR LSR LSR LSR STA $14 SEP #$20 XBA LDA $07A5 REP #$21 STA $4202 LDA $12 LSR LSR LSR LSR CLC ADC $4216 ASL PHX JSR BlockTest PLX PLY RTS GrappleBlockTest: DB $00,$40,$00,$00,$00,$80,$00,$00,$40,$40,$40,$40,$40,$C0,$40,$40 SetGrappleVelocities: LDA $0CFA STA $0D44 XBA AND #$00FF ASL TAX LDY $0B2D LDA $A0B3C3,X JSL SignedWordMultiplication STA $14 ;-Y * cos theta LDA $A0B443,X JSL SignedWordMultiplication ;Y * sin theta STA $16 LDY $0B36 DEY BNE + ;Branch if not moving up EOR #$FFFF INC STA $16 LDA $14 EOR #$FFFF INC STA $14 + LDA $0B44 CLC ADC $0B48 SEP #$20 LDA $0B42 ADC $0B46 REP #$20 XBA TAY LDA $A0B443,X JSL SignedWordMultiplication BIT $0DAA BPL + EOR #$FFFF INC + SEC SBC $14 STA $0D00 LDA $A0B3C3,X JSL SignedWordMultiplication BIT $0DAA BMI + EOR #$FFFF INC + CLC ADC $16 PHP BPL + EOR #$FFFF INC + ASL ASL ASL STA $4204 SEP #$20 LDA $0CFE LSR ADC $0CFE ADC #$30 STA $4206 REP #$20 NOP NOP NOP NOP NOP NOP LDA $4214 ; ASL ;Too much? ASL ADC $4214 ASL ASL PLP BPL Skip71 EOR #$FFFF INC Skip71: STA $0D26 RTL CalculateSamusHead: LDA $0CFB AND #$00FF ASL TAX LDY $0CFE LDA $A0B443,X ;sin x JSL SignedMultiplication CLC ADC $0D08 STA $0D1A LDA $A0B3C3,X ;-cos x JSL SignedMultiplication CLC ADC $0D0C STA $0D1C LDY #$000C LDA $0D45 AND #$00FF ASL TAX LDA $A0B443,X JSL SignedMultiplication CLC ADC $0D1A STA $0D16 LDA $A0B3C3,X JSL SignedMultiplication CLC ADC $0D1C STA $0D18 RTS CheckWater: LDA $09A2 BIT #$0020 BNE + LDA $196E BEQ + LDA $195E BMI + SEC SBC #$0011 CMP $0AFA BPL + LDA #$0001 TSB $0CF4 RTS + LDA #$0001 TRB $0CF4 RTS print "Boundary: ",pc org $9BBD95 print "Boundary: ",pc PHB PHK PLB ; LDA $0D1A ; STA $0D16 ; LDA $0D1C ; STA $0D18 JSR CalculateSamusHead LDA $0D26 BPL + EOR #$FFFF INC A + CMP #$0010 BMI + LDA #$0001 STA $0CF8 BRA ++ + STZ $0CF8 LDA $0D44 CMP $0CFA BNE ++ AND #$FF00 CMP #$8000 BNE ++ LDA $0A96 CMP #$0040 BPL +++ LDA #$0008 STA $0A94 LDA #$0040 STA $0A96 +++ LDX #$0020 BRA + ++ LDA #$000F STA $0A94 LDA $0D45 LSR LSR INC LSR AND #$001F STA $0A96 ASL A TAX + LDA $0D26 BPL + EOR #$FFFF INC A + CMP #$0200 BMI ++ LDA $0A96 CMP #$0040 BMI + LDA #$0010 + CLC ADC #$0020 STA $0A96 ++ LDA $0A1E AND #$00FF CMP #$0004 BEQ ++ LDA $C301, X AND #$FF00 XBA BPL + ORA #$FF00 + CLC ADC $0D1A STA $0AF6 LDA $C302, X AND #$FF00 XBA BPL + ORA #$FF00 BRA + ++ LDA $C2C1, X AND #$FF00 XBA BPL ++ ORA #$FF00 ++ CLC ADC $0D1A STA $0AF6 LDA $C2C2, X AND #$FF00 XBA BPL + ORA #$FF00 + CLC ADC $0D1C STA $0AFA JSR $BE98 ; Sets previous position... prevent scroll bugs? JSR CheckWater PLB RTL print "Boundary: ",pc org $91EF4F ;'Set Samus in grappling pose' routine. Needs: Convert momentum, BD95, print "Boundary: ",pc JSL SetGrappleVelocities JSL $9BBD95 ; $DBD95 IN ROM STZ $0CD0 STZ $0CD6 STZ $0CD8 STZ $0CDA STZ $0CDC STZ $0CDE STZ $0CE0 JSL $91DEBA STZ $0B46 STZ $0B48 STZ $0B2C STZ $0B2E STZ $0B42 STZ $0B44 LDA #$0006 JSL $809049 RTS print "Boundary: ",pc org $94B260 print "Boundary: ",pc SamusGrappleAngle: LDA $8B LDX $0D44 CPX $0CFA BNE LimitedMotion BIT #$0200 BNE DecrementAngle BIT #$0100 BEQ NoChange IncrementAngle: TXA CLC ADC #$0E00 STA $0D44 TDC SEP #$20 LDA #$40 JSR ForwardCollisionCheckSetup LDA #$00FF BRA CollisionCheck LimitedMotion: BPL + BIT #$0200 BEQ IncrementAngle BRA CopyAngle + BIT #$0100 BEQ DecrementAngle CopyAngle: TXA StoreAngle: STA $0D44 NoChange: RTS DecrementAngle: TXA SEC SBC #$0E00 STA $0D44 TDC SEP #$20 LDA #$C0 JSR ForwardCollisionCheckSetup LDA #$0001 CollisionCheck: STA $12 LDX #$0006 SEP #$20 BRA + -- CLC LDA $13 ADC $12 STA $13 - + LDA $0D46,X TAY LDA $13 CLC ADC $0D4E,X REP #$20 PHX JSR GetBlockXY SEP #$20 TDC PLX BCS -- DEX DEX BPL - LDA $13 CLC ADC $0D45 STA $0D45 LDA $13 CLC ADC $0CFB STA $0CFB LDA $13 XBA REP #$20 LSR LSR BIT #$2000 BEQ + ORA #$C000 + CLC ADC $0D26 STA $0D26 RTS AND #$00FF ASL TAX LDY #$0005 LDA $A0B443,X JSL SignedMultiplication CLC ADC $0D1A STA $0D22 LDA $A0B3C3,X JSL SignedMultiplication CLC ADC $0D1C STA $0D24 LDA $12 XBA AND #$00FF ASL TAX LDY #$0028 LDA $A0B443,X JSL SignedMultiplication PHA CLC ADC $0D22 STA $14 LDA $A0B3C3,X JSL SignedMultiplication PHA CLC ADC $0D24 LSR LSR LSR LSR XBA ORA $07A5 STA $4202 LDA $14 LSR LSR LSR LSR CLC ADC $4216 STA $0DC4 STA $18 ASL TAX LDA $7F0003,X AND #$00F0 LSR LSR LSR TAX JSR (GrappleBlockCollision,X) PLA BCS ++ BPL + SEC + ROR ADC $0D24 ASL ASL ASL ASL AND #$FF00 ORA $07A5 STA $4202 PLA CLC BPL + SEC + ROR ADC $0D22 LSR LSR LSR LSR CLC ADC $4216 STA $0DC4 STA $18 ASL TAX LDA $7F0003,X AND #$00F0 LSR LSR LSR TAX JSR (GrappleBlockCollision,X) + LDA $12 RTS ++ PLA LDA $12 RTS GrappleBlockCollision: DW ClearC,SetC,ClearC,ClearC,ClearC,HorizontalExtend,ClearC,ClearC,SetC,SetC,Spike,CrumbleBlock,SetC,VerticalExtend,SetC,BombBlock BombBlock: LDX $0DC4 LDA $7F6401, X AND #$FF00 XBA SEC BMI + ASL A TAX LDA $936B, X JSL $8484E7 ; $204E7 IN ROM + RTS CrumbleBlock: LDX $0DC4 LDA $7F6401, X AND #$FF00 XBA BMI + ASL A TAX LDA $9139, X JSL $8484E7 ; $204E7 IN ROM RTS + AND #$007F ASL A TAY LDA $079F ASL A TAX LDA $92E9, X STA $22 LDA ($22), Y JSL $8484E7 ; $204E7 IN ROM RTS ClearC: CLC RTS Spike: LDX $0DC4 LDA $7F6402,X ASL AND #$01FF TAX JSR ($902B,X) SetC: SEC RTS HorizontalExtend: LDX $0DC4 LDA $7F6401,X AND #$FF00 XBA BPL + ORA #$FF00 + CLC ADC $0DC4 LookupExtension: STA $0DC4 ASL TAX LDA $7F0003,X AND #$00F0 LSR LSR LSR TAX JMP (GrappleBlockCollision,X) VerticalExtend: LDX $0DC4 SEP #$20 LDA $7F6402,X BMI + STA $4203 REP #$21 LDA $0DC4 NOP ADC $4216 BRA LookupExtension + EOR #$FF INC STA $4203 REP #$20 LDA $0DC4 SEC SBC $4216 BRA LookupExtension SixSinAngle: TAX LDA $A0B443,X ASL CLC ADC $A0B443,X ASL AND #$FF00 XBA BPL + ORA #$FF00 + RTS SixCosAngle: LDA $A0B3C3,X ASL CLC ADC $A0B3C3,X ASL AND #$FF00 XBA BPL + ORA #$FF00 + RTS TwoSixSinAngle: AND #$00FF ASL TAX LDA $A0B443,X ASL CLC ADC $A0B443,X ASL ASL CLC ADC $A0B443,X ASL AND #$FF00 XBA BPL + ORA #$FF00 + RTS TwoSixCosAngle: LDA $A0B3C3,X ASL CLC ADC $A0B3C3,X ASL ASL CLC ADC $A0B3C3,X ASL EOR #$FFFF INC AND #$FF00 XBA BPL + ORA #$FF00 + RTS ;0D60, 0D64, 0D68 SetSideChecks: BMI + INC $18 + LDA $18 ;If 0, check + side. Or not? BNE + LDA $0D48 EOR #$FFFF INC STA $0D48 LDA $0D50 EOR #$FFFF INC STA $0D50 + LDA $0D48 CLC ADC $0D46 STA $12 CLC ADC $0D4A STA $0D64 CLC LDA $0D4A BPL + SEC + ROR CLC ADC $12 STA $0D60 CLC ADC $0D4A BIT $16 BMI + LDA $12 + STA $0D68 LDA $0D50 CLC ADC $0D4E STA $12 CLC ADC $0D52 STA $0D66 CLC LDA $0D52 BPL + SEC + ROR CLC ADC $12 STA $0D62 CLC ADC $0D52 BIT $16 BMI + LDA $12 + STA $0D6A LDX #$0010 RTS LengthCollisionCheck: ;+ = extending, - = retracting. A holds new grapple beam distance. ;Cases: Extending straight, Ext CW, Ext CCW, retracting straight, retracting CW, retracting CCW. ;Checks: Foot (2), Foot and + Side (3), Foot and - Side, Head (2), Head and - Side (3), Head and + Side ;Calculate offset due to movement ;Calculate 5 pixels + side(X/Y). - side is same but negative. ;Calculate 1A pixels towards feet(X/Y) ;Add results as necessary to get spots to check. ;print "Start of LengthCollisionCheck: ", pc STZ $16 STZ $18 BPL + EOR #$FFFF INC DEC $16 ;$16 is negative if retracting DEC $18 + INC TAY LDA $0CFB AND #$00FF BIT $16 BPL + EOR #$0080 + ASL TAX LDA $A0B443,X JSL SignedMultiplication CLC ADC $0D16 STA $0D46 ;X offset due to movement + 'Origin' LDA $A0B3C3,X JSL SignedMultiplication CLC ADC $0D18 STA $0D4E ;Y offset due to movement + 'Origin' LDA $0D45 EOR #$0080 JSR TwoSixSinAngle EOR #$FFFF INC STA $0D4A ;X for 2/3 to feet JSR TwoSixCosAngle STA $0D52 ;Y for 2/3 to feet TXA CLC ADC #$0180 AND #$01FF JSR SixSinAngle STA $0D48 ;X for + side JSR SixCosAngle STA $0D50 ;Y for + side LDA $0D46 CLC ADC $0D48 STA $0D58 LDA $0D46 SEC SBC $0D48 STA $0D5C LDA $0D4E CLC ADC $0D50 STA $0D5A LDA $0D4E SEC SBC $0D50 STA $0D5E LDX #$0004 LDA $0CFA CMP $0D44 BEQ + ;Skip additional spots JSR SetSideChecks + BIT $16 BMI ++ LDA $0D4A ;Change head position to foot CLC BPL + SEC + ROR CLC ADC $0D4A PHA CLC ADC $0D58 STA $0D58 ;X of foot (1) PLA CLC ADC $0D5C STA $0D5C ;X of foot (2) LDA $0D52 CLC BPL + SEC + ROR CLC ADC $0D52 PHA CLC ADC $0D5A ;Y of foot (1) STA $0D5A PLA CLC ADC $0D5E STA $0D5E ;Y of foot (2) ++ LDA $07A5 ;At this point, X is index to first X/Y to check, and all spots are ready. STA $4202 ;Yes, it does multiply it, but it doesn't waste time so eh. - ;print "Start of extending block detection: ", pc ; JSR DebugCollisionSpots LDA $0D5A,X ;Get Y LSR LSR LSR LSR STA $4203 ;High byte (trash) goes into dividend register. Doesn't do anything so it's fine. LDA $0D58,X LSR LSR LSR LSR CLC ADC $4216 STA $0DC4 STA $18 PHX ASL TAX LDA $7F0003,X AND #$00F0 LSR LSR LSR TAX JSR (GrappleBlockCollision,X) PLX BCS + DEX DEX DEX DEX BPL - - RTS + STZ $0D00 BIT $16 BMI - CPX #$0008 ;Carry set if greater or equal BPL - LDA $0D44 CMP #$A100 BCS - ;Branches if A100 - FFFF CMP #$6000 BMI + JSR AttemptLanding + SEC RTS ;DebugCollisionSpots: ; PHX ; PHA ; LDA $0D5A,X ; PHA ; LDA $0D58,X ; LDX $0590 ; SEC ; SBC $0911 ; SBC #$0004 ; STA $0370, X ; AND #$0100 ; BEQ + ; LDA $81859F, X ; STA $22 ; LDA ($22) ; ORA $81839F, X ; STA ($22) ;+ ; PLA ; SEC ; SBC $0915 ; SBC #$0004 ; STA $0371, X ; LDA #$3A20 ; STA $0372, X ; TXA ; CLC ; ADC #$0004 ; STA $0590 ; PLA ; PLX ; RTS AttemptLandingLoop: - LDA $18 SEC SBC $07A5 BMI AttemptLandingLoop-2 ;Bad practice saves 2 bytes for free! STA $18 STA $0DC4 ASL TAX LDA $7F0003,x AND #$00F0 LSR LSR LSR TAX JSR (GrappleBlockCollision,X) BCS + DEC $16 BPL - + RTS AttemptLanding: LDA #$0002 STA $16 LDA $07A5 STA $4202 ;AttemptLandingb: JSR AttemptLandingLoop BCS AttemptLanding-1 ;Set Samus to standing. May throw some ugly stack work in right here. PLA PLA PLB ;Let's handle the stack now instead of later LDA $18 STA $4204 LDA $07A5 SEP #$20 STA $4206 REP #$20 LDY #$00A4 LDA $0A1E BIT #$0004 BEQ + INY + STY $0A28 LDA #$0005 STA $0A2E LDA $4214 ASL ASL ASL ASL CLC ADC #$001B ;will need to doublecheck STA $0AFA STZ $0CF8 STZ $0B36 LDA $4216 ASL ASL ASL ASL ADC #$000A CMP $0AF6 BMI ++ SBC #$0005 CMP $0AF6 BMI +++ + DEC $18 BRA + ++ INC $18 + PHA LDA $07A5 ASL ADC $18 STA $18 LDA #$0002 STA $16 JSR AttemptLandingLoop PLA BCC + STA $0AF6 BRA +++ + AND #$FFF0 SBC #$0003 CMP $0AF6 BPL + CLC ADC #$0018 CMP $0AF6 BPL +++ + STA $0AF6 +++ JSL CalculateGrappleLengthA ;print "GrappleLength: ",pc CLC ADC #$0008 CMP $0CF6 BMI + CMP #$006F BMI ++ CMP #$0077 BPL +++ LDA #$006E ++ STA $0CF6 + RTL +++ STZ $0CF4 RTL ForwardCollisionCheckSetup: CLC ADC $0D45 REP #$20 ASL JSR SixSinAngle CLC ADC $0D16 STA $0D4C JSR SixCosAngle CLC ADC $0D18 STA $0D54 LDA $0D45 JSR TwoSixSinAngle STA $14 CLC ADC $0D4C STA $0D4A LDA $14 CLC BPL + SEC + ROR PHA CLC ADC $0D4C STA $0D48 PLA CLC ADC $14 CLC ADC $0D4C STA $0D46 JSR TwoSixCosAngle EOR #$FFFF INC STA $14 CLC ADC $0D54 STA $0D52 LDA $14 CLC BPL + SEC + ROR PHA CLC ADC $0D54 STA $0D50 PLA CLC ADC $14 CLC ADC $0D54 STA $0D4E LDY #$0006 - LDA $0D4E,Y SEC SBC $0D0C STA $14 LDA $0D46,Y SEC SBC $0D08 STA $12 PHY JSL CalculateVectorLength PLY STA $0D46,Y TXA LSR STA $0D4E,Y DEY DEY BPL - LDA #$0028 STA $0D80 RTS SwingCollisionCheck: ;print "Start of SwingCollisionCheck: ", pc TDC LDA #$C0 BIT $0D27 BMI + LDA #$40 + JSR ForwardCollisionCheckSetup STZ $12 SEP #$20 TDC INC BIT $0D56 BPL + LDA #$FF + STA $12 -- CLC LDA $13 ADC $12 STA $13 LDX #$0006 - LDA $0D46,X TAY LDA $13 CLC ADC $0D4E,X REP #$20 PHX JSR GetBlockXY PLX BCS + SEP #$20 TDC DEX DEX BPL - LDA $13 CMP $0D56 BNE -- CLC RTS + BNE ++ ;Check from PLX, branch if X !=0 LDA $0D44 CMP #$6000 BMI ++ CMP #$A0FF BPL ++ + JSR AttemptLanding ++ ;Code for normal collision response here SEP #$21 LDA $13 SBC $12 ; SEC ; SBC $12 STA $13 ;Go to angle before collision STZ $12 REP #$20 LDA $12 ;Successful degrees moved before collision SEC SBC $0D26 ;target degrees to move LSR ;-(Degrees not moved) LSR ;Divided by 4 BIT #$2000 BEQ + ORA #$C000 + CLC ADC $12 ;Successful movement - (degrees not moved) / 4 PHA CLC ADC $0CFA STA $0CFA PLA CLC ADC $0D44 STA $0D44 LDA $0D26 EOR #$FFFF INC LSR LSR BIT #$2000 BEQ + ORA #$C000 + STA $0D26 ;Reverse and divide old speed by 4 SEC RTS ;Below this should be DONE GetBlockXY: print "GetBlock routine: ", pc ASL TAX LDA $A0B443,X JSL SignedMultiplication CLC ADC $0D08 LSR LSR LSR LSR STA $16 LDA $A0B3C3,X JSL SignedMultiplication CLC ADC $0D0C ASL ASL ASL ASL AND #$FF00 ORA $16 LDX #$0026 CPX $0D80 BMI + ;Set new block - CMP $0D58,X BNE ++ ;Skip block CLC RTS ++ DEX DEX ;This shouldn't ever reach negative. If it does... well. It'll be interesting. CPX $0D80 BPL - + STA $0D58,X STX $0D80 SEP #$20 XBA STA $4202 LDA $07A5 STA $4203 LDA #$00 XBA REP #$21 ADC $4216 STA $0DC4 STA $18 ;Well, let's hope the grapple block collision won't change this... ASL TAX LDA $7F0003,X AND #$00F0 LSR LSR LSR TAX JSR (GrappleBlockCollision,X) ++ RTS ;16-bit value in Y * signed 9-bit A value, high 16-bit result in A. Result should be signed, but large values can mess it up. ;4216(high * byte) + 4217 (low * sign) = A? SignedWordMultiplication: SEP #$20 XBA BPL ++ TYA XBA BEQ + EOR #$FF INC REP #$20 STA $4202 TYA SEP #$20 NOP LDA $4217 XBA STA $4203 XBA REP #$21 AND #$00FF ADC $4216 EOR #$FFFF INC RTL + REP #$20 TYA EOR #$FFFF INC RTL ++ BNE + TYA XBA REP #$20 STA $4202 TYA SEP #$20 NOP LDA $4217 XBA STA $4203 XBA REP #$21 AND #$00FF ADC $4216 RTL + REP #$20 TYA RTL ;8-bit value in Y * signed 9-bit A, 16-bit result in A. Result should be signed, but large values can mess it up. SignedMultiplicationExtra: STY $4202 XBA BPL ++ XBA BEQ + SEP #$20 EOR #$FF INC STA $4203 REP #$20 LDA #$FFFF EOR $4216 ;I do funny things to save cycles... INC RTL + TYA EOR #$FFFF INC XBA RTL ++ BNE + SEP #$20 XBA STA $4203 REP #$20 NOP NOP LDA $4216 RTL + TYA XBA RTL ;8-bit value in Y * signed 9-bit A, high byte of result sign-extended to 16-bits in A SignedMultiplication: STY $4202 XBA BPL ++ XBA BEQ + SEP #$20 EOR #$FF INC STA $4203 LDA #$FF NOP NOP EOR $4217 ;I do funny things to save cycles... REP #$20 INC RTL + TYA EOR #$FFFF INC RTL ++ BNE + SEP #$20 XBA STA $4203 REP #$20 LDA #$00FF NOP AND $4217 RTL + TYA RTL ChargeGraphicPosition: LDA $0A1C ASL ASL ASL TAX LDA $91B62D,X AND #$00FF STA $16 LDA $91B62C,X AND #$00FF CMP #$0010 BMI + PLA PLB RTL + ASL TAX LDA $0A1F AND #$00FF CMP #$0001 BEQ ++ LDA $C1C2, X CLC ADC $0AFA SEC SBC $16 TAY LDA $C1A8, X CLC ADC $0AF6 RTS ++ LDA $C1F0, X CLC ADC $0AFA SEC SBC $16 TAY LDA $C1DC, X CLC ADC $0AF6 RTS print "Boundary: ",pc org $90DD7D ;What to do when turning around print "Boundary: ",pc BIT $0CF4 BMI + STZ $0CF4 + RTS ;$DC036-$DC0DA print "Boundary: ",pc org $9BC036 print "Boundary: ",pc PHP REP #$30 LDA $0CD0 BNE + - PLP RTL + CMP #$0001 BNE + LDA #$0010 STA $0CD6 LDA #$0003 STA $0CDC + LDA $0CDC DEC A STA $0CDC BPL ++ LDA $0CD6 INC A STA $0CD6 TAX LDA $90C487, X AND #$00FF CMP #$00FE BNE + LDA $90C488, X ORA #$FF00 CLC ADC $0CD6 STA $0CD6 TAX LDA $90C487, X AND #$00FF + STA $0CDC ++ LDA $0D1A SEC SBC $0911 STA $14 LDA $0D1C SEC SBC $0915 STA $12 AND #$FF00 BNE + LDA $0CD6 STA $16 JSL $818A37 ; $8A37 IN ROM BRA ++ + LDA $0CD6 STA $16 JSL $818AB7 ; $8AB7 IN ROM ++ PLP RTL pad $9BC0DB ;Don't don't clear 0DC6 (all originally BRA $01 originally STZ $0DC6). print "Boundary: ",pc org $91EC10 print "Boundary: ",pc ; BRA + ; NOP ;+ STZ $0DC6 print "Boundary: ",pc org $90E5FE print "Boundary: ",pc ; BRA + ; NOP ;+ STZ $0DC6 print "Boundary: ",pc org $90A68F print "Boundary: ",pc ; BRA + ; NOP ;+ STZ $0DC6 print "Boundary: ",pc org $90A654 print "Boundary: ",pc ; BRA + ; NOP ;+ STZ $0DC6 print "Boundary: ",pc org $90DDB6 print "Boundary: ",pc LDA $0CF4 BPL + JSL GrappleMain RTS + STZ $0CF4 RTS ;DD3D, DDB6, BF9D, DD6F, DD74, DD8C, DDD8 ; 03,0A,0D,14,19,1B 04,07,08,09,11,12,13 0B,0C,16,0E,17,18 0F 1A print "Boundary: ",pc org $91EBB7 print "Boundary: ",pc JSL DisableGrapple ;Calls to movement transitions print "Boundary: ",pc org $91F41A print "Boundary: ",pc JSL MovementTransition print "Boundary: ",pc org $91F3A5 print "Boundary: ",pc JSL MovementTransition ;Transition to new movement type print "Boundary: ",pc org $B880B0 print "Boundary: ",pc MovementTransition: PHP PHB PHK PLB REP #$30 LDA $0A1F AND #$00FF ASL A TAX JSR (MovementTransitions, X) PLB PLP RTL MovementTransitions: ; 00,01, 02, 03, 04,05,06,07, 08,09,0A,0B,0C, 0D DW NT,NT,NormalJump,SpinJump,KillGrapple,NT,NT,NT,KillGrapple,NT,NT,NT,NT,UnknownTransition ; 0E,0F,10, 11, 12, 13, 14,15,16,17,18,19,1A, 1B DW NT,NT,NT,KillGrapple,SpringAir,KillGrapple,WallJump,NT,NT,NT,NT,NT,NT,KillGrapple WallJump: LDA $0A23 AND #$00FF CMP #$0014 BEQ + JSL $909949 ; $81949 IN ROM + NT: RTS SpringAir: LDA $0A1C CMP #$007F BNE + LDA $0A23 AND #$00FF CMP #$0011 BEQ ++ BRA +++ + CMP #$0080 BNE +++ LDA $0A23 AND #$00FF CMP #$0011 BNE +++ ++ JSL $9098BC ; $818BC IN ROM +++ KillGrapple: STZ $0CF4 RTS UnknownTransition: LDA $0A1C CMP #$0065 BNE + LDA $0A20 CMP #$0064 BEQ ++ BRA +++ + CMP #$0066 BNE +++ LDA $0A20 CMP #$0063 BNE +++ ++ JSL $9098BC ; $818BC IN ROM +++ RTS NormalJump: LDA $0A1C CMP #$004B BEQ + CMP #$004C BEQ + CMP #$0055 BMI +++ CMP #$005B BPL +++ + LDA $0A20 CMP #$0027 BEQ + CMP #$0028 BNE ++ + LDA $0AFA SEC SBC #$000A STA $0AFA ++ JSL $9098BC ; $818BC IN ROM +++ RTS SpinJump: LDA $0A23 AND #$00FF CMP #$0003 BEQ + CMP #$0014 BEQ + JSL $B88000 ; $818BC IN ROM + RTS DisableGrapple: PHB PHK PLB LDA $0A1F AND #$00FF TAX BIT.w DisableGrappleTransitions-1,X BPL + STZ $0CF4 + PLB JML $91FB08 DisableGrappleTransitions: DB $00,$00,$00,$00,$80,$00,$00,$00,$80,$00,$00,$00,$00,$00,$00,$00 DB $00,$80,$80,$80,$00,$00,$00,$00,$00,$00,$00,$80 ;$101E9A-$101F6C, ;$101F7D-$102079 print "Boundary: ",pc org $A09E9A print "Boundary: ",pc STZ $18A6 STZ $17AA -- LDY $17AA LDA $17EC, Y CMP #$FFFF BNE + CLC RTL + STA $0E54 TAX LDA $0FA0, X BEQ + - INC $17AA INC $17AA BRA -- + LDA $0F7A, X SEC SBC $0D08 BPL + EOR #$FFFF INC A + SEC SBC $0F82, X BCC + CMP #$0008 BCS - + LDA $0F7E, X SEC SBC $0D0C BPL + EOR #$FFFF INC A + SEC SBC $0F84, X BCC + CMP #$0008 BCS - + LDA $0F78, X TAX LDA $A0001A, X BPL + LDX $0E54 LDA #$0001 STA $0F8A, X ;Set to run grapple AI LDA #$8000 BRA ++ + BEQ - DEC BNE + STZ $0CF4 SEC REP #$40 RTL + LDA #$8004 ++ TSB $0CF4 LDX $0E54 LDA $0F7A, X STA $0D08 LDA $0F7E, X STA $0D0C LDA $0A1F AND #$00FF CMP #$0016 BEQ + SEC SEP #$40 RTL + JSL CalculateGrappleLength CMP #$0088 BPL ++ STA $0CFE TXA LSR AND #$00FF SEP #$20 LDY $0CFA STA $0CFB CPY $0D44 BEQ + CLC BMI +++ ADC #$F2 BRA + +++ ADC #$0E + STA $0D45 REP #$20 SEP #$41 RTL ++ STZ $0CF4 SEC REP #$40 RTL ;GrapplePullEnemyStop: ;Will be handled by individual enemies ; LDX $0E54 ; LDA $0F9E, X ; BEQ + ; LDA #$0004 ; STA $0F8A, X ; STZ $0CF4 ; RTS ;+ ; LDA $0F78, X ; TAX ; LDA $A0000D, X ; AND #$00FF ; BNE + ; LDA #$0004 ;+ ; LDX $0E54 ; STA $0F9C, X ; STZ $0F8A, X ; LDA $0CFE ; SEC ; SBC $0CF6 ; B ; RTS ;What enemies need to do: ;Check if frozen (LDA $0F9E,X : BEQ + : LDA #$0004 : STA $0F8A,X : STZ $0CF4 : LDA $0F78,X : TAX : LDA $A0001E,X : STA $1784 : JML [$1784] : + ...) ;Enemy stun effect (LDA $0F78,X : TAX : LDA $A0000D,X : AND #$00FF : BNE + : LDA #$0004 : LDX $0E54 : STA $0F9C,X : STZ $0F8A,X) ;Compare grapple length to target length, adjust speed if necessary ;Have a main AI mode for grapple movement, use it until collision with appropriate surface ; GrapplePullSamusStop: LDX $0E54 LDA $0F9E, X BNE + LDA #$0004 STA $0F8A, X STZ $0CF4 LDA $0F78,X TAX LDA $A0001E,X STA $1784 JML [$1784] + LDA $0F78, X TAX LDA $A0000D, X AND #$00FF BNE + LDA #$0004 + LDX $0E54 STA $0F9C, X STZ $0F8A, X LDA #$0004 TSB $0CF4 RTL print "Boundary: ",pc org $A3E669 print "Boundary: ",pc LDX $0E54 LDA $0F92, X ;Get orientation AND #$0003 ASL A TAY LDA $E2CC, Y ;E25C, E278, E294, E2B0 STA $0F92, X ;Set graphic AI LDA #$804D STA $0F8E, X ;Advanced hit box pointer. Probably unused, Geemers are simple squares LDA #$0001 STA $0F94, X ;Start graphic AI immediately LDA #$E6C1 STA $0FB2, X ;Main AI pointer initialized to E6C1 LDA $0FB4, X ;'Speed' from SMILE. Intended to be 0000 - 001F or 00FF XBA LSR LSR STA $0FA8, X ;Horizontal and STA $0FAA, X ;Vertical speeds. LDA $0F86, X AND #$0003 BNE + LDA $0FA8, X ;Swap X speed if initially moving left (0) EOR #$FFFF INC A STA $0FA8, X RTL + CMP #$0002 BNE + LDA $0FAA, X ;Swap Y speed if initially moving up (2) EOR #$FFFF INC A STA $0FAA, X + RTL ;Right is probably 1, down is probably 3. ;E785: Falling print "Boundary: ",pc org $A3E785 print "Boundary: ",pc LDA $7E780A,X STA $12 LDA $7E780C,X STA $14 JSL $A0C6AB PHP LDA $7E7802, X ;Uh. Not sure when this was initialized. STA $12 LDA $7E7804, X STA $14 JSL $A0C786 ;Vertical motion BCS + PLP BCC ++ BRA +++ + PLP +++ LDA #$0000 STA $7E7802, X STA $7E7804, X STA $7E780A, X STA $7E780C, X STA $7E7808, X ;Clear speeds LDA $7E7806, X STA $0FB2, X ;Restore previous AI RTL ++ LDA $7E7804, X CMP #$0004 ;Cap speed at 4 pixels per frame BPL + LDA $7E7802, X CLC ADC #$4000 STA $7E7802, X LDA $7E7804, X ADC #$0000 STA $7E7804, X ;Accelerate due to gravity + RTL print "Must be before a3e7f2: ", pc print "Boundary: ",pc org $A0DD19 print "Boundary: ",pc DW $F650 print "Boundary: ",pc org $A0DD2F print "Boundary: ",pc DW GeemerTouch print "Boundary: ",pc org $A3F650 ;First free space available in the bank... ouch print "Boundary: ",pc ;Check if frozen (LDA $0F9E,X : BEQ + : LDA #$0004 : STA $0F8A,X : STZ $0CF4 : LDA $0F78,X : TAX : LDA $A0001E,X : STA $1784 : JML [$1784] : + ...) ;Enemy stun effect (LDA $0F78,X : TAX : LDA $A0000D,X : AND #$00FF : BNE + : LDA #$0004 : LDX $0E54 : STA $0F9C,X : STZ $0F8A,X) ;Compare grapple length to target length, adjust speed if necessary LDA $0F9E,X : BEQ + : LDA #$0004 : STA $0F8A,X : STZ $0CF4 : JML $A0957E + LDA #$0004 : STA $0F9C,X : STZ $0F8A,X : LDA $0F7A,X LDA $0CFE SEC SBC $0CF6 BPL + JMP $E785 + TAY LDA $0CFB AND #$00FF ASL TAX LDA $A0B3C3,X JSL SignedMultiplicationExtra LSR LSR LSR LSR BIT #$0800 BEQ + ORA #$F000 + PHA LDA $A0B443,X JSL SignedMultiplicationExtra PLY LSR LSR LSR LSR BIT #$0800 BEQ + ORA #$F000 + LDX $0E54 PHB PEA $7E7E PLB PLB CLC ADC $780B,X STZ $780C,X BMI + CMP #$0800 BMI ++ LDA #$0008 BRA ++ + DEC $780C,X CMP #$F800 BPL ++ LDA #$F800 ++ STA $780B,X CLC TYA ADC $7803,X STZ $7804,X BMI + CMP #$0800 BMI ++ LDA #$0008 BRA ++ + DEC $7804,X CMP #$F800 BPL ++ LDA #$F800 ++ STA $7803,X LDA $0FB2,X CMP #$E785 BEQ + STA $7806,X LDA #$E785 STA $0FB2,X + PLB JMP $E785 GeemerTouch: LDX $0E54 LDA $0F8A,X LSR BCS + JML $A0A477 + RTL macro EnemyGrapplePointers(bank) ;TODO: Implement all of these. Starting with GrapplePullSamusStop { print "Boundary: ",pc org print "Boundary: ",pc JSL $000000 ;Dummied for now RTL JSL GrapplePullSamusStop RTL JSL $000000 ;Dummied for now RTL JSL $000000 ;Dummied for now RTL JSL $000000 ;Dummied for now RTL JSL $000000 ;Dummied for now RTL } endmacro %EnemyGrapplePointers($A08000) %EnemyGrapplePointers($A28000) %EnemyGrapplePointers($A38000) %EnemyGrapplePointers($A48000) %EnemyGrapplePointers($A58000) %EnemyGrapplePointers($A68000) %EnemyGrapplePointers($A78000) %EnemyGrapplePointers($A88000) %EnemyGrapplePointers($A98000) %EnemyGrapplePointers($AA8000) %EnemyGrapplePointers($B28000) %EnemyGrapplePointers($B38000)