Difference between revisions of "Octorok (One Way)"

From TLoZ: ALTTP Hacking Resources
Jump to: navigation, search
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
{{infobox sprite
+
{{subpage|Sprites}}
| id = $08
 
| hp = $02 ($06B17B)
 
| damage = $01 ($06B26E)
 
| palette = $1D ($06B361)
 
| found = [[Light World]]
 
}}
 
  
== Description ==
+
Sprite {{$|08}}: Octorok (One Way)
Octoroks roam around the light world, and stop to fire in one direction before beginning to move again.
+
== Octorok (One Way) ==
 +
=== Description ===
 +
An octorok who stops, fires only once, then begins moving again.
  
== Combat Strategy ==
+
=== Combat Strategy ===
The projectiles fired by an octorok can be blocked by all shields. They are fired in one of four lateral directions, so standing diagonal to a stationary octorok keeps you out of the line of fire.
+
Very weak enemy. They fire and move only in lateral directions, so staying in their diagonal range is a safe way to approach them.
  
== Known Bugs ==
+
== Stats And Properties ==
 +
See [[Sprite Properties]]
  
== Another Section ==
+
'''{{$|06B088}}'''
 +
{|{{Prettytable}}
 +
!Bit(s)
 +
!Info
 +
!Value
 +
|-
 +
| {{Hex|7}}
 +
| Harmless
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|6}}
 +
| ?
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|5}}
 +
| ?
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|4-0}}
 +
| OAM Slots
 +
| {{Hex|00010}} ({{$|02}})
 +
|}
 +
 
 +
'''{{$|06B17B}}'''
 +
{|{{Prettytable}}
 +
! Bit(s)
 +
! Info
 +
! Value
 +
|-
 +
| {{Hex|7-0}}
 +
| HP
 +
| {{Hex|0000 0010}} ({{$|02}})
 +
|}
 +
 
 +
'''{{$|06B26E}}'''
 +
{|{{Prettytable}}
 +
! Bit(s)
 +
! Info
 +
! Value
 +
|-
 +
| {{Hex|7-4}}
 +
| ?
 +
| {{Hex|0000}} ({{$|00}})
 +
|-
 +
| {{Hex|3-0}}
 +
| [[Damage Types|Damage Type]]
 +
| {{Hex|0001}} ({{$|01}})
 +
|}
 +
 
 +
'''{{$|06B361}}'''
 +
{|{{Prettytable}}
 +
! Bit(s)
 +
! Info
 +
! Value
 +
|-
 +
| {{Hex|7}}
 +
| No Death Animation
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|6}}
 +
| Invincible
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|5}}
 +
| Adjust Child coordinates
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|4}}
 +
| Draw Shadow
 +
| {{Hex|1}}
 +
|-
 +
| {{Hex|3-1}}
 +
| Palette
 +
| {{Hex|110}} ({{$|06}})
 +
|-
 +
| {{Hex|0}}
 +
| ?
 +
| {{Hex|1}}
 +
|}
 +
 
 +
'''{{$|06B454}}'''
 +
{|{{Prettytable}}
 +
! Bit(s)
 +
! Info
 +
! Value
 +
|-
 +
| {{Hex|7}}
 +
| Ignore Collision Settings
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|6}}
 +
| Statis
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|5}}
 +
| Persist
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|4-0}}
 +
| Hit Box Dimensions
 +
| {{Hex|00000}} ({{$|00}})
 +
|}
 +
 
 +
'''{{$|06B547}}'''
 +
{|{{Prettytable}}
 +
! Bit(s)
 +
! Info
 +
! Value
 +
|-
 +
| {{Hex|7-4}}
 +
| Tile Interaction Hit Box
 +
| {{Hex|0000}} ({{$|00}})
 +
|-
 +
| {{Hex|3}}
 +
| ?
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|2}}
 +
| ?
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|1}}
 +
| Dies Like A Boss
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|0}}
 +
| Falls In Holes
 +
| {{Hex|0}}
 +
|}
 +
 
 +
'''{{$|06B63A}}'''
 +
{|{{Prettytable}}
 +
! Bit(s)
 +
! Info
 +
! Value
 +
|-
 +
| {{Hex|7}}
 +
| Disable Tile Interactions
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|6}}
 +
| ?
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|5}}
 +
| Is shield Blockable
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|4}}
 +
| Alternate Damage Sound
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|3-0}}
 +
| Prize Pack
 +
| {{Hex|0010}} ({{$|02}})
 +
|}
 +
 
 +
'''{{$|06B72D}}'''
 +
{|{{Prettytable}}
 +
! Bit(s)
 +
! Info
 +
! Value
 +
|-
 +
| {{Hex|7}}
 +
| ?
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|6}}
 +
| ?
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|5}}
 +
| Is Interactive
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|4}}
 +
| Deflect Projectiles
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|3}}
 +
| Collide With Less Tiles
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|2}}
 +
| Impervious To Sword/Hammer
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|1}}
 +
| Impervious To Arrows?
 +
| {{Hex|0}}
 +
|-
 +
| {{Hex|0}}
 +
| ?
 +
| {{Hex|0}}
 +
|}
 +
 
 +
== Code ==
 +
<Code>
 +
    ; $35363-$35376 DATA
 +
    pool Sprite_Octorock:
 +
    {
 +
    .next_direction
 +
        db  3,  2,  0,  1
 +
       
 +
    .x_speed
 +
        db  24, -24,  0,  0
 +
       
 +
    .y_speed
 +
        db  0,  0,  24, -24
 +
       
 +
    .unused
 +
        ; Unused?
 +
        db  1,  2,  4,  8
 +
   
 +
    .delays
 +
        ; Unused?
 +
        db  60, -128, -96, -128
 +
    }
 +
 
 +
; ==============================================================================
 +
 
 +
    !ai_state  = $0D80
 +
    !graphic  = $0DC0
 +
    !direction = $0DE0
 +
    !type      = $0E20
 +
    !oam_4    = $0F50
 +
   
 +
    ; *$35377-$35450 JUMP LOCATION
 +
    Sprite_Octorock:
 +
    {
 +
        !force_hflip = $00
 +
        !gfx_vert    = $00
 +
       
 +
        ; ------------------------------
 +
       
 +
        ; Octorock Routine (Sprites 0x08 and 0x0A)
 +
        LDY !direction, X : PHY
 +
       
 +
        LDA !timer_1, X : BEQ .timer_1_elapsed
 +
       
 +
        LDA .next_direction, Y : STA !direction, X
 +
   
 +
    .timer_1_elapsed
 +
   
 +
        STZ $00
 +
       
 +
        LDA !graphic, X : CMP.b #$07 : BNE .no_forced_hflip
 +
       
 +
        LDA.b #$40 : STA !force_hflip
 +
   
 +
    .no_forced_hflip
 +
   
 +
        LDA !oam_4, X : AND.b #$BF
 +
       
 +
        ORA $D2AE, Y : ORA !force_hflip : STA !oam_4, X
 +
       
 +
        JSR Octorock_Draw
 +
       
 +
        PLA : STA !direction, X
 +
       
 +
        JSR Sprite_CheckIfActive
 +
        JSR Sprite_CheckIfRecoiling
 +
        JSR Sprite_Move
 +
        JSR Sprite_CheckDamage
 +
       
 +
        LDA !ai_state, X : AND.b #$01 : BNE .stop_and_spit_maybe
 +
       
 +
        LDA !direction, X : AND.b #$02 : ASL A : STA !gfx_vert
 +
       
 +
        INC $0E80, X
 +
       
 +
        LDA $0E80, X : LSR #3 : AND.b #$03 : ORA !gfx_vert : STA !graphic, X
 +
       
 +
        LDA !timer_0, X : BNE .wait_1
 +
       
 +
        ; Switch to the other main AI state.
 +
        INC !ai_state, X
 +
       
 +
        LDY !type, X
 +
       
 +
        LDA .delays-8, Y : STA !timer_0, X
 +
       
 +
        RTS
 +
   
 +
    .wait_1
 +
   
 +
        LDY !direction, X
 +
       
 +
        ; Make this little bugger move.
 +
        LDA .x_speed, Y : STA $0D50, X
 +
        LDA .y_speed, Y : STA $0D40, X
 +
       
 +
        JSR Sprite_CheckTileCollision
 +
       
 +
        LDA $0E70, X : BEQ .epsilon
 +
       
 +
        LDA !direction, X : EOR.b #$01 : STA !direction, X
 +
       
 +
        BRA .return_2
 +
   
 +
    .epsilon
 +
   
 +
        RTS
 +
   
 +
    .stop_and_spit_maybe
 +
   
 +
        JSR Sprite_Zero_XY_Velocity
 +
       
 +
        LDA !timer_0, X : BNE .wait_2
 +
       
 +
        INC !ai_state, X
 +
       
 +
        LDA !direction, X : PHA
 +
       
 +
        ; Set a new countdown timer and direction slightly at random.
 +
        JSL GetRandomInt : AND.b #$3F : ADC.b #$30 : STA !timer_0, X
 +
       
 +
        AND.b #$03 : STA !direction, X
 +
       
 +
        ; Note this odd... certainty that both outcomes result in the same
 +
        ; branch location.
 +
        PLA : CMP !direction, X : BEQ .same_direction
 +
        EOR !direction, X      : BNE .different_direction
 +
       
 +
        ; Thus, this line of code is not reachable, as far as I can tell.
 +
        LDA.b #$08 : STA !timer_1, X
 +
   
 +
    .same_direction
 +
    .different_direction
 +
    .return_2
 +
   
 +
        RTS
 +
   
 +
    .wait_2
 +
   
 +
        LDA !type, X : SUB.b #$08 : REP #$30 : AND.w #$00FF : ASL A : TAY
 +
       
 +
        ; Hidden Jump table, Argghghh!
 +
        LDA Octorock_AI_Table, Y : DEC A : PHA
 +
       
 +
        SEP #$30
 +
       
 +
        RTS
 +
   
 +
    .handlers
 +
   
 +
        !nullptr = 0
 +
       
 +
        dw Octorock_Normal
 +
        dw !nullptr
 +
        dw Octorock_FourShooter
 +
    }
 +
 
 +
; ==============================================================================
 +
 
 +
    ; $35451-$3546E DATA
 +
    pool Octorock_Normal:
 +
    {
 +
   
 +
    .unknown
 +
        db 0, 2, 2, 2, 1, 1, 1, 0
 +
        db 0, 0, 0, 0, 2, 2, 2, 2
 +
        db 2, 1, 1  0
 +
    }
 +
       
 +
; ==============================================================================
 +
 
 +
    ; $35465-$3546E DATA
 +
    pool Octorock_FourShooter:
 +
    {
 +
   
 +
    .unknown
 +
        db 2, 2, 2, 2 2, 2, 2, 2, 1, 0
 +
    }
 +
 
 +
; ==============================================================================
 +
 
 +
    ; $3546F-$35485 JUMP LOCATION (LOCAL)
 +
    Octorock_Normal:
 +
    {
 +
        LDA !timer_0, X : CMP.b #$1C : BNE .dont_spit_rock
 +
       
 +
        PHA
 +
       
 +
        JSR Octorock_SpitOutRock
 +
       
 +
        PLA
 +
   
 +
    .dont_spit_rock
 +
   
 +
        LSR #3 : TAY
 +
       
 +
        LDA .unknown, Y : STA $0DB0, X
 +
       
 +
        RTS
 +
    }
 +
 
 +
; ==============================================================================
 +
 
 +
    ; $35486-$35489 DATA
 +
    pool Octorock_FourShooter:
 +
    {
 +
   
 +
    .next_direction
 +
        db 2, 3, 1, 0
 +
    }
 +
 
 +
; ==============================================================================
 +
 
 +
    ; $3548A-$354B4 JUMP LOCATION (LOCAL)
 +
    Octorock_FourShooter:
 +
    {
 +
        LDA !timer_0, X : PHA
 +
       
 +
        CMP.b #$80 : BCS .just_animate
 +
        AND.b #$0F : BNE .dont_rotate
 +
       
 +
        PHA
 +
       
 +
        LDY !direction, X
 +
       
 +
        LDA .next_direction, Y : STA !direction, X
 +
       
 +
        PLA
 +
   
 +
    .dont_rotate
 +
   
 +
        CMP.b #$08 : BNE .dont_shoot
 +
       
 +
        JSR Octorock_SpitOutRock
 +
   
 +
    .dont_shoot
 +
    .just_animate
 +
   
 +
        PLA : LSR #4 : TAY
 +
       
 +
        LDA .unknown, Y : STA $0DB0, X
 +
       
 +
        RTS
 +
    }
 +
 
 +
; ==============================================================================
 +
 
 +
    ; $354B5-$354CC DATA
 +
    pool Octorock_SpitOutRock:
 +
    {
 +
   
 +
    ; \task Label these sublabels.
 +
   
 +
        db  12, -12,  0,  0
 +
   
 +
    ; $354B9
 +
        db  0,  -1,  0,  0
 +
   
 +
    ; $354BD
 +
        db  4,  4,  12, -12
 +
   
 +
    ; $354C1
 +
        db  0,  0,  0,  -1
 +
   
 +
    ; $354C5
 +
        db  44, -44,  0,  0
 +
   
 +
    ; $354C9
 +
        db  0,  0,  44, -44
 +
    }
 +
 
 +
; ==============================================================================
 +
 
 +
    ; $354CD-$35513 LOCAL
 +
    Octorock_SpitOutRock:
 +
    {
 +
        LDA.b #$07 : JSL Sound_SetSfx2PanLong
 +
       
 +
        LDA.b #$0C
 +
       
 +
        JSL Sprite_SpawnDynamically : BMI .spawn_failed
 +
       
 +
        PHX
 +
       
 +
        ; The position and velocity of the newly created rock depends on the
 +
        ; direction that the Octorok is currently facing.
 +
        LDA !direction, X : TAX
 +
       
 +
        LDA $00 : ADD $D4B5, X : STA $0D10, Y
 +
        LDA $01 : ADC $D4B9, X : STA $0D30, Y
 +
       
 +
        LDA $02 : ADD $D4BD, X : STA $0D00, Y
 +
        LDA $03 : ADC $D4C1, X : STA $0D20, Y
 +
       
 +
        LDA !direction, Y : TAX
 +
       
 +
        LDA $D4C5, X : STA $0D50, Y
 +
        LDA $D4C9, X : STA $0D40, Y
 +
       
 +
        PLX
 +
   
 +
    .spawn_failed
 +
   
 +
        RTS
 +
    }
 +
 
 +
; ==============================================================================
 +
 
 +
    ; $35514-$35549 DATA
 +
    pool Octorock_Draw:
 +
    {
 +
   
 +
    .x_offsets
 +
        dw  8,  0,  4,  8,  0,  4,  9, -1,  4
 +
   
 +
    .y_offsets
 +
        dw  6,  6,  9,  6,  6,  9,  6,  6,  9
 +
   
 +
    .chr
 +
        db $BB, $BB, $BA, $AB, $AB, $AA, $A9, $A9, $B9
 +
   
 +
    .properties
 +
        db $65, $25, $25, $65, $25, $25, $65, $25, $25
 +
    }
 +
 
 +
; ==============================================================================
 +
 
 +
    ; *$3554A-$355B8 LOCAL
 +
    Octorock_Draw:
 +
    {
 +
        !top_x_bit_low  = $0E
 +
        !top_x_bit_high = $0F
 +
       
 +
        JSR Sprite_PrepOamCoord
 +
       
 +
        ; perhaps this draws the octorock's snout?
 +
        LDA !direction, X : CMP.b #$03 : BEQ .dont_draw_this_part
 +
       
 +
        ; $07 = [3 * $0DB0, X] + !direction
 +
        LDA $0DB0, X : ASL A : ADC $0DB0, X : ADC !direction, X : STA $07
 +
       
 +
        PHX : PHA
 +
       
 +
        ASL A : TAX
 +
       
 +
        REP #$20
 +
       
 +
        LDA $00 : ADD .x_offsets, X : STA ($90), Y
 +
       
 +
        AND.w #$0100 : STA !top_x_bit_low
 +
       
 +
        LDA $02 : ADD .y_offsets, X : INY : STA ($90), Y
 +
       
 +
        ADD.w #$0010 : CMP.w #$0100 : SEP #$20 : BCC .not_off_screen
 +
       
 +
        LDA.b #$F0 : STA ($90), Y
 +
   
 +
    .not_off_screen
 +
   
 +
        PLX
 +
       
 +
        LDA .chr, X : INY : STA ($90), Y
 +
       
 +
        LDA .properties, X : INY : ORA $05 : STA ($90), Y
 +
       
 +
        LDA !top_x_bit_high : STA ($92)
 +
       
 +
        PLX
 +
   
 +
    .dont_draw_this_part
 +
   
 +
        REP #$20
 +
       
 +
        LDA $90 : ADD.w #$0004 : STA $90
 +
       
 +
        INC $92
 +
       
 +
        SEP #$20
 +
       
 +
        DEC $0E40, X
 +
       
 +
        LDY.b #$00
 +
       
 +
        JSR Sprite_PrepAndDrawSingleLarge.just_draw
 +
       
 +
        INC $0E40, X
 +
       
 +
        RTS
 +
    }
 +
</Code>

Latest revision as of 17:31, 19 December 2016

This is a subpage of Sprites

Sprite $08: Octorok (One Way)

Octorok (One Way)

Description

An octorok who stops, fires only once, then begins moving again.

Combat Strategy

Very weak enemy. They fire and move only in lateral directions, so staying in their diagonal range is a safe way to approach them.

Stats And Properties

See Sprite Properties

$06B088

Bit(s) Info Value
7 Harmless 0
6  ? 0
5  ? 0
4-0 OAM Slots 00010 ($02)

$06B17B

Bit(s) Info Value
7-0 HP 0000 0010 ($02)

$06B26E

Bit(s) Info Value
7-4  ? 0000 ($00)
3-0 Damage Type 0001 ($01)

$06B361

Bit(s) Info Value
7 No Death Animation 0
6 Invincible 0
5 Adjust Child coordinates 0
4 Draw Shadow 1
3-1 Palette 110 ($06)
0  ? 1

$06B454

Bit(s) Info Value
7 Ignore Collision Settings 0
6 Statis 0
5 Persist 0
4-0 Hit Box Dimensions 00000 ($00)

$06B547

Bit(s) Info Value
7-4 Tile Interaction Hit Box 0000 ($00)
3  ? 0
2  ? 0
1 Dies Like A Boss 0
0 Falls In Holes 0

$06B63A

Bit(s) Info Value
7 Disable Tile Interactions 0
6  ? 0
5 Is shield Blockable 0
4 Alternate Damage Sound 0
3-0 Prize Pack 0010 ($02)

$06B72D

Bit(s) Info Value
7  ? 0
6  ? 0
5 Is Interactive 0
4 Deflect Projectiles 0
3 Collide With Less Tiles 0
2 Impervious To Sword/Hammer 0
1 Impervious To Arrows? 0
0  ? 0

Code

   ; $35363-$35376 DATA
   pool Sprite_Octorock:
   {
   .next_direction
       db   3,   2,   0,   1
       
   .x_speed
       db  24, -24,   0,   0
       
   .y_speed
       db   0,   0,  24, -24
       
   .unused
       ; Unused?
       db   1,   2,   4,   8
   
   .delays
       ; Unused?
       db  60, -128, -96, -128
   }
==============================================================================
   !ai_state  = $0D80
   !graphic   = $0DC0
   !direction = $0DE0
   !type      = $0E20
   !oam_4     = $0F50
   
   ; *$35377-$35450 JUMP LOCATION
   Sprite_Octorock:
   {
       !force_hflip = $00
       !gfx_vert    = $00
       
       ; ------------------------------
       
       ; Octorock Routine (Sprites 0x08 and 0x0A)
       LDY !direction, X : PHY
       
       LDA !timer_1, X : BEQ .timer_1_elapsed
       
       LDA .next_direction, Y : STA !direction, X
   
   .timer_1_elapsed
   
       STZ $00
       
       LDA !graphic, X : CMP.b #$07 : BNE .no_forced_hflip
       
       LDA.b #$40 : STA !force_hflip
   
   .no_forced_hflip
   
       LDA !oam_4, X : AND.b #$BF
       
       ORA $D2AE, Y : ORA !force_hflip : STA !oam_4, X
       
       JSR Octorock_Draw
       
       PLA : STA !direction, X
       
       JSR Sprite_CheckIfActive
       JSR Sprite_CheckIfRecoiling
       JSR Sprite_Move
       JSR Sprite_CheckDamage
       
       LDA !ai_state, X : AND.b #$01 : BNE .stop_and_spit_maybe
       
       LDA !direction, X : AND.b #$02 : ASL A : STA !gfx_vert
       
       INC $0E80, X
       
       LDA $0E80, X : LSR #3 : AND.b #$03 : ORA !gfx_vert : STA !graphic, X
       
       LDA !timer_0, X : BNE .wait_1
       
       ; Switch to the other main AI state.
       INC !ai_state, X
       
       LDY !type, X
       
       LDA .delays-8, Y : STA !timer_0, X
       
       RTS
   
   .wait_1
   
       LDY !direction, X
       
       ; Make this little bugger move.
       LDA .x_speed, Y : STA $0D50, X
       LDA .y_speed, Y : STA $0D40, X
       
       JSR Sprite_CheckTileCollision
       
       LDA $0E70, X : BEQ .epsilon
       
       LDA !direction, X : EOR.b #$01 : STA !direction, X
       
       BRA .return_2
   
   .epsilon
   
       RTS
   
   .stop_and_spit_maybe
   
       JSR Sprite_Zero_XY_Velocity
       
       LDA !timer_0, X : BNE .wait_2
       
       INC !ai_state, X
       
       LDA !direction, X : PHA
       
       ; Set a new countdown timer and direction slightly at random.
       JSL GetRandomInt : AND.b #$3F : ADC.b #$30 : STA !timer_0, X
       
       AND.b #$03 : STA !direction, X
       
       ; Note this odd... certainty that both outcomes result in the same
       ; branch location.
       PLA : CMP !direction, X : BEQ .same_direction
       EOR !direction, X       : BNE .different_direction
       
       ; Thus, this line of code is not reachable, as far as I can tell.
       LDA.b #$08 : STA !timer_1, X
   
   .same_direction
   .different_direction
   .return_2
   
       RTS
   
   .wait_2
   
       LDA !type, X : SUB.b #$08 : REP #$30 : AND.w #$00FF : ASL A : TAY
       
       ; Hidden Jump table, Argghghh!
       LDA Octorock_AI_Table, Y : DEC A : PHA
       
       SEP #$30
       
       RTS
   
   .handlers
   
       !nullptr = 0
       
       dw Octorock_Normal
       dw !nullptr
       dw Octorock_FourShooter
   }
==============================================================================
   ; $35451-$3546E DATA
   pool Octorock_Normal:
   {
   
   .unknown
       db 0, 2, 2, 2, 1, 1, 1, 0
       db 0, 0, 0, 0, 2, 2, 2, 2
       db 2, 1, 1  0
   }
       
==============================================================================
   ; $35465-$3546E DATA
   pool Octorock_FourShooter:
   {
   
   .unknown
       db 2, 2, 2, 2 2, 2, 2, 2, 1, 0
   }
==============================================================================
   ; $3546F-$35485 JUMP LOCATION (LOCAL)
   Octorock_Normal:
   {
       LDA !timer_0, X : CMP.b #$1C : BNE .dont_spit_rock
       
       PHA
       
       JSR Octorock_SpitOutRock
       
       PLA
   
   .dont_spit_rock
   
       LSR #3 : TAY
       
       LDA .unknown, Y : STA $0DB0, X
       
       RTS
   }
==============================================================================
   ; $35486-$35489 DATA
   pool Octorock_FourShooter:
   {
   
   .next_direction
       db 2, 3, 1, 0
   }
==============================================================================
   ; $3548A-$354B4 JUMP LOCATION (LOCAL)
   Octorock_FourShooter:
   {
       LDA !timer_0, X : PHA
       
       CMP.b #$80 : BCS .just_animate
       AND.b #$0F : BNE .dont_rotate
       
       PHA
       
       LDY !direction, X
       
       LDA .next_direction, Y : STA !direction, X
       
       PLA
   
   .dont_rotate
   
       CMP.b #$08 : BNE .dont_shoot
       
       JSR Octorock_SpitOutRock
   
   .dont_shoot
   .just_animate
   
       PLA : LSR #4 : TAY
       
       LDA .unknown, Y : STA $0DB0, X
       
       RTS
   }
==============================================================================
   ; $354B5-$354CC DATA
   pool Octorock_SpitOutRock:
   {
   
   ; \task Label these sublabels.
   
       db  12, -12,   0,   0
   
   ; $354B9
       db   0,  -1,   0,   0
   
   ; $354BD
       db   4,   4,  12, -12
   
   ; $354C1
       db   0,   0,   0,  -1
   
   ; $354C5
       db  44, -44,   0,   0
   
   ; $354C9
       db   0,   0,  44, -44
   }
==============================================================================
   ; $354CD-$35513 LOCAL
   Octorock_SpitOutRock:
   {
       LDA.b #$07 : JSL Sound_SetSfx2PanLong
       
       LDA.b #$0C
       
       JSL Sprite_SpawnDynamically : BMI .spawn_failed
       
       PHX
       
       ; The position and velocity of the newly created rock depends on the
       ; direction that the Octorok is currently facing.
       LDA !direction, X : TAX
       
       LDA $00 : ADD $D4B5, X : STA $0D10, Y
       LDA $01 : ADC $D4B9, X : STA $0D30, Y
       
       LDA $02 : ADD $D4BD, X : STA $0D00, Y
       LDA $03 : ADC $D4C1, X : STA $0D20, Y
       
       LDA !direction, Y : TAX
       
       LDA $D4C5, X : STA $0D50, Y
       LDA $D4C9, X : STA $0D40, Y
       
       PLX
   
   .spawn_failed
   
       RTS
   }
==============================================================================
   ; $35514-$35549 DATA
   pool Octorock_Draw:
   {
   
   .x_offsets
       dw  8,  0,  4,  8,  0,  4,  9, -1,  4
   
   .y_offsets
       dw  6,  6,  9,  6,  6,  9,  6,  6,  9
   
   .chr
       db $BB, $BB, $BA, $AB, $AB, $AA, $A9, $A9, $B9
   
   .properties
       db $65, $25, $25, $65, $25, $25, $65, $25, $25
   }
==============================================================================
   ; *$3554A-$355B8 LOCAL
   Octorock_Draw:
   {
       !top_x_bit_low  = $0E
       !top_x_bit_high = $0F
       
       JSR Sprite_PrepOamCoord
       
       ; perhaps this draws the octorock's snout?
       LDA !direction, X : CMP.b #$03 : BEQ .dont_draw_this_part
       
       ; $07 = [3 * $0DB0, X] + !direction
       LDA $0DB0, X : ASL A : ADC $0DB0, X : ADC !direction, X : STA $07
       
       PHX : PHA
       
       ASL A : TAX
       
       REP #$20
       
       LDA $00 : ADD .x_offsets, X : STA ($90), Y
       
       AND.w #$0100 : STA !top_x_bit_low
       
       LDA $02 : ADD .y_offsets, X : INY : STA ($90), Y
       
       ADD.w #$0010 : CMP.w #$0100 : SEP #$20 : BCC .not_off_screen
       
       LDA.b #$F0 : STA ($90), Y
   
   .not_off_screen
   
       PLX
       
       LDA .chr, X : INY : STA ($90), Y
       
       LDA .properties, X : INY : ORA $05 : STA ($90), Y
       
       LDA !top_x_bit_high : STA ($92)
       
       PLX
   
   .dont_draw_this_part
   
       REP #$20
       
       LDA $90 : ADD.w #$0004 : STA $90
       
       INC $92
       
       SEP #$20
       
       DEC $0E40, X
       
       LDY.b #$00
       
       JSR Sprite_PrepAndDrawSingleLarge.just_draw
       
       INC $0E40, X
       
       RTS
   }