Patch:Keen swimming

From KeenWiki
Jump to navigation Jump to search

This page contains patches relating to Keen using the Wetsuit in a non-map level such as the Well Of Wishes in Keen 4. (For swimming on the map see Keen 4's map patch page.) The page is divided into two sections, Keen himself and the bubbles he produces when swimming.

Swimming Keen

This section contains patches relating to Keen himself as he swims.

Sprite Type

As he does when behaving normally, Swimming Keen uses the player sprite type, $02. This is what causes Keen to die when touching enemies and so is rather important.

Keen 4

#Keen swimming sprite type
%patch $F5F7 [$02]

Sprite Behavior

Swimming Keen has only one behavior, this is the one that lets him move and also governs when he produces bubbles. (Bubble production is a different behavior.) It is used by all four of his swimming actions.

$0E8F0E17RL #Keen swimming behavior

Keen 4

#Keen swimming
%patch $3086C $0E8F0E17RL
%patch $3088A $0E8F0E17RL
%patch $308A8 $0E8F0FAERL
%patch $308C6 $0E8F0FAERLL

Swimming behavior code

This is the complete Keen swimming behavior code. It is rather complex since it responds to arrow keys, ctrl and alt as well as floating and emitting bubbles.

The first two lines check Keen's horizontal and vertical speeds and keep him slowly moving, even if no input is given. (He drifts.) Line 4 counts his Misc C variable, every $3C game ticks it runs the 'produce bubble' code. The rest of the code responds to arrow and keypresses.

Keen 4

#Keen swimming behavior code
%patch $F707 $55 $8B $EC $83 $EC $0A $56 $57 $8B $76 $06 $83 $7C {$16} [$00] {$7D}
             $05 $B8 $0001W  $EB $02 $33 $C0 $89 $46 $F8 $83 $7C {$18} [$04] {$7D}
             $05 $B8 $0001W  $EB $02 $33 $C0 $89 $46 $F6 $8B $44 $44 $03 $06
             $4C $A5 $89 $44 $44 $83 $7C {$44} [$3C] {$7E} $08 $56 $0E $E8 $FEECW 
             $83 $C4 $02 $83 $3E $C5C9W  [$00] {$74} $3A $83 $3E $C5C7W  $00 $75
             $33 $C7 $06 $C5C7W  $0001W  $83 $3E $CE $A7 [$00] {$74} $0B $A1 $A7CEW
                 $BA $12 $00 $F7 $EA $89 $44 $16 $83 $3E $D0 $A7 [$00] {$74} $0B
             $A1 $A7D0W  $BA $12 $00 $F7 $EA $89 $44 $18 $8B $5C $1C $8B $47
             $1C $89 $44 $1C $83 $3E $CE $A7 [$00] {$74} $06 $A1 $A7CEW  $89 $44
             $0E $A1 $A54AW  $8B $16 $48 $A5 $2B $16 $4C $A5 $1D $0000W  $89
             $46 $FE $89 $56 $FC $E9 $00CFW  $8B $46 $FC $25 $07 $00 $0D $00
             [$00] {$74} $03 $E9 $00ABW  $83 $7C $16 $0C $7E $05 $BF $FD $FF $EB
             $19 $83 $7C $16 $00 $7E $05 $BF $FF $FF $EB $0E $83 $7C $16 $F4
             $7E $05 $BF $0001W  $EB $03 $BF $03 $00 $8B $C7 $03 $06 $CE $A7
             $8B $F8 $03 $06 $CE $A7 $8B $F8 $01 $7C $16 $83 $3E $CE $A7 $00
             $75 $17 $83 $7C $16 $00 $7D $05 $B8 $0001W  $EB $02 $33 $C0 $3B
             $46 $F8 $74 $05 $C7 $44 $16 $0000W  $83 $7C $18 $0C $7E $07 $C7
             $46 $FA $FD $FF $EB $1F $83 $7C $18 $04 $7E $07 $C7 $46 $FA $FF
             $FF $EB $12 $83 $7C $18 $F4 $7E $07 $C7 $46 $FA $0001W  $EB $05
             $C7 $46 $FA $03 $00 $8B $46 $FA $03 $06 $D0 $A7 $89 $46 $FA $03
             $06 $D0 $A7 $89 $46 $FA $01 $44 $18 $83 $3E $D0 $A7 $00 $75 $11
             $83 $7C $18 $04 $7E $0B $83 $7E $F6 $00 $74 $05 $C7 $44 $18 $00
             $00 $8B $44 $16 $01 $06 $23 $C9 $8B $44 $18 $01 $06 $21 $C9 $83
             $46 $FC $01 $83 $56 $FE $00 $8B $46 $FE $8B $56 $FC $3B $06 $4A
             $A5 $7D $03 $E9 $FF22W  $75 $09 $3B $16 $48 $A5 $73 $03 $E9 $FF17W
                 $5F $5E $8B $E5 $5D $CB

Sprite Collision

Unlike most of Keen's actions, swimming possesses its own, unique sprite interaction code that is used by nothing else.

Collision values

As mentioned above, only Keen swimming uses a unique sprite interaction. Keen's bubble has no sprite interaction at all.

Swimming Keen sprite interaction

#Keen swimming
%patch $30870 $0E8F1061RL
%patch $3088E $0E8F1061RL
%patch $308AC $0E8F1061RL
%patch $308CA $0E8F1061RL

#Keen's bubble
%patch $308E8 $00000000L
%patch $30906 $00000000L
%patch $30924 $00000000L
%patch $30942 $00000000L

Collision code

This is the complete swimming collision code. The first two lines differentiate between items (Type 4) and the Council Member (Type 6). The Member code skips to the last line of the collision where the level state is set to 3. (Executing the rest of the Council Member code.)

The rest of the collision deals with items. (This means Keen can only interact with two basic things while swimming.) This section first calls a list at the end of the code. The list is 12 items long located at $E8F0 + $1117 = $FA07. All items do the same thing (At $F980) regardless of what item kind they are which renders the list setup rather pointless.

What is done to all item sprites is covered right after the list setup (Line 3 and onwards). First a 'got item' sound is played based on the list located at $2EE70 + $13DC = $3024C. Then the sprite's sprite type is set to 1, the 'misc sprite' type. Then its foreground variable is set to 3 so it appears in front of all tiles. (So the player can see all the items they get.) After this the sprite's animation changes based on the 'got item animation list' at $2EE70 + $140C = $3027C and the player's score increases by an amount given in the list located at $2EE70 + $13F4 = $30264. This is the same basic code for all items.

After this code more specific to various types of items is run. On line 7 a check is made for the keygems which adds a gem to the player's gem counter (The first counter is shown, depending on gem this or the next three counters will be affected.) After this a check is made for the 1UP item type which increases the player's life counter by 1. Following that is the ammo type check which increases the player's ammo counter ($7A58W) by an amount that depends on the difficulty ($7A6CW). Finally the sprite's action is changed to that of the got item, $1F28W.

Keen Collision 3 code

#Keenswim collision
%patch $F951 $55 $8B $EC $56 $57 $8B $7E $06 $8B $76 $08 $8B $04 $3D [$0004W]
             {$74} $0B $3D [$0006W]  {$75} $03 $E9 $008EW  $E9 $0091W  $8B $5C $3E
             $83 $FB [$0B] {$76} $03 $E9 $0086W  $D1 $E3 $2E $FF $A7 [$1117W]  $8B
             $5C $3E $D1 $E3 $FF $B7 [$13DCW]  $9A $187409F1RL     $83 $C4 $02
             $C7 $04 [$0001W]  $C7 $44 $20 [$0003W]  $8B $5C $3E $D1 $E3 $8B $87
             [$140CW]  $89 $44 $1E $8B $5C $3E $D1 $E3 $FF $B7 [$13F4W]  $9A $06BD1EF2RL
                         $83 $C4 $02 $83 $7C $3E [$04] {$7D} $0B $8B $5C $3E $D1
             $E3 $FF $87 {$7A60W}  $EB $20 $83 $7C $3E [$0A] {$75} $06 $FF $06 {$7A6AW}
                 $EB $14 $83 $7C $3E [$0B] {$75} $0E $8B $1E {$7A6CW}  $D1 $E3 $8B
             $87 [$13D4W]  $01 $06 {$7A58W}  $B8 [$1F28W]  $50 $56 $9A $09DC120ARL
                 $83 $C4 $04 $EB $08 $EB $06 $C7 $06 {$7A70W}  [$0003W]  $83 $C7
             $4C $5F $5E $5D $CB

#Items list
%patch $FA07 [$1090W] #Red Gem (At $F980)
%patch $FA09 [$1090W] #Yellow Gem (At $F980)
%patch $FA0B [$1090W] #Blue Gem (At $F980)
%patch $FA0D [$1090W] #Green Gem (At $F980)
%patch $FA0F [$1090W] #100 points (At $F980)
%patch $FA11 [$1090W] #200 points (At $F980)
%patch $FA13 [$1090W] #500 points (At $F980)
%patch $FA15 [$1090W] #1000 points (At $F980)
%patch $FA17 [$1090W] #2000 points (At $F980)
%patch $FA19 [$1090W] #5000 points (At $F980)
%patch $FA1B [$1090W] #1UP (At $F980)
%patch $FA1D [$1090W] #Ammo (At $F980)


Swimming Keen uses far fewer animations than normal Keen, freeing up a lot of memory. There are four swimming frames, using four animations, a death frame and an invisible 'Has been eaten' frame. Note however that he also uses bubble animations cached by the Dopefish, meaning that default scuba Keen requires a Dopefish to be in the level as well to avoid an uncached sprite error.

Swimming Keen animations

%patch $30710 $0135W #Keen swimming Cache start
%patch $3075A $013AW #Keen swimming cache end

#Keen swims
%patch $3085C $0135W $0137W
%patch $30866 $0032W        #Animation speed
%patch $3087A $0136W $0138W
%patch $30884 $0032W        #Animation speed
%patch $30898 $0135W $0137W
%patch $308A2 $0032W        #Animation speed
%patch $308B6 $0136W $0138W
%patch $308C0 $0032W        #Animation speed

#Keen eaten by Dopefish
%patch $32520 $0139W $0139W
%patch $3252A $0000W        #Wait for Dopefish
%patch $3253E $FFFFW $FFFFW #Erase sprite
%patch $32548 $00B4W        #Pause before level exit box


When swimming Keen has momentum, if you press the right arrow key, Keen will move right, and continue moving right for a short time before coming to a stop. The following patches control this momentum, that is, they are not the speeds Keen has when arrows are pressed.

By default these speeds counteract Keen's speed, the left speed slows his left speed to a standstill for example. If these are set to $0000W then Keen will keep moving in that direction unless another arrow key is pressed. (He will become 'frictionless') If they are set to one value Keen will feel a constant tug in that direction, as if a current were pulling him. (For example, setting all horizontal speeds to $0001W will make Keen drift right, even if no keys are pressed, and make it harder for him to swim left.) If the values are $0003W or above the 'current' is so strong Keen will not be able to move against it, effectively making him constantly move in one direction.

Increasing all values makes Keen swim faster overall.

There are three sections, the first controls horizontal movement, the second vertical, the third is unknown. Notably, gravity is always 'on' by default, constantly pulling Keen down. There are two values for each direction, the first when no arrow key is pressed (when Keen will slowly stop moving) and the second, larger when Keen is trying to turn around (when Keen will quickly stop moving and start moving in the opposite direction.) If the 'turning' values are set to $0000W then Keen will have to stop moving before he can start moving in the opposite direction.

Swimming momentum speeds

%patch $F7C4 [$FFFDW] #Left (Change direction)
%patch $F7CF [$FFFFW] #Left
%patch $F7DA [$0001W] #Right
%patch $F7DF [$0003W] #Right (Change direction)

%patch $F819 [$FFFDW] #Up (Change direction)
%patch $F826 [$FFFFW] #Up
%patch $F833 [$0001W] #Down (This doubles as gravity)
%patch $F83A [$0003W] #Down  (Change direction)

%patch $F92D [$0001W]
%patch $F93B [$FFFFW]

Sprite positioning

Patches relating to the relative position of produced bubbles are covered under the 'bubbles' section.


Patches relating to the production sounds of bubbles are covered under the 'bubbles' section.

Clipping and foreground

Keen while swimming uses 'FullClipToWalls' which keeps him out of any tiles that aren't not-blocking, including slopes. He also has a foreground value of 1, like most sprites.

Keen 4

#Swimming Keen clipping
%patch $F622 $0002W

#Swimming Keen foreground
%patch $F601 $0001W

Sprite-tile interaction

Swimming Keen has his own, unique tile interaction not used by anything else.

Keen 4

#Swimming Keen tile interaction
%patch $30874 $0E8F112FRL
%patch $30892 $0E8F112FRL
%patch $308B0 $0E8F112FRL
%patch $308CE $0E8F112FRL

Interaction code

This is the complete code for swimming Keen's tile interaction. On the first line left walls are checked for, followed by a check of Keen's horizontal speed. If it is less than zero (moving left) then it jumps the next two checks.

On line 2 right walls are checked for, followed by a check of Keen's horizontal speed. If it is less than or equal to zero (moving left) then it jumps the following code. Said code sets Keen's horizontal speed to zero.

On line 3 the same thing is done in regards to floors and, on line 4, ceilings.(This time checking Keen's vertical speed.) The sum total of all these checks is to set Keen's horizontal speed to 0 if he's moving into a wall or floor.

Keen 4

#Swimming Keen tile interaction code
%patch $FA1F $55 $8B $EC $56 $8B $76 $06 $83 $7C $38 [$00] {$74} $06 $83 $7C $16
             [$00] {$7C} $0C $83 $7C $3C [$00] {$74} $0B $83 $7C $16 [$00] {$7E} $05 $C7
             $44 $16 [$0000W]  $83 $7C $36 [$00] {$74} $06 $83 $7C $18 [$00] {$7F} $0C
             $83 $7C $3A [$00] {$74} $0B $83 $7C $18 [$00] {$7D} $05 $C7 $44 $18 [$0000W]
                 $FF $74 $20 $33 $C0 $50 $FF $74 $1E $FF $74 $0C $FF $74 $0A
             $8B $C6 $05 $46 $00 $50 $9A $16541641RL     $83 $C4 $0C $5E $5D

Sprite spawn code

The initiation code is rather complex; notice that there are not one but three caches being set. $C7 $06 $CB7BW $0001W. Sets Keen's cache while the bubble frames between $DB and $E2 and the scorebox ($FD) are also cached.

In the spawning code the last blue highlighted value is the sprite action Keen uses as he proceeds to act in-level. $C7 $02 $xxxxW sets the sprite activity, (Here 'always active'.)$C7 $07 $xxxxW sets the sprite type, ($02,player type.) $C7 $20 $xxxxW sets the foreground value. $C7 $06 $xxxxW sets Keen's clipping, in this case the rarely used 'FullClipToWalls'.

Keen swimming always starts the level moving down and right. $C7 $47 $10 $xxxxW is the vertical direction the sprite starts moving in, either $0001W (Facing down), $FFFFW (Facing up) or $0000W (Neither, never used.) $C7 $47 $0E $xxxxW is the horizontal direction.

Keen 4

#Location of initiation code
%patch $EED7 [$03FBW] #Swimming Keen (At $ECEB)

#Swimming Keen Initiation code
%patch $ECEB $FF $76 $FC $57 $9A $0E8F0CFERL     $83 $C4 $04 $9A {$0D8F0003RL}
                 $C7 $06 $CB7BW  $0001W  $BE [$00DBW]  $EB $0F $B8 $2A3ARW $8A #Cache items got - start
             $16 $EC $7A $8E $C0 $26 $08 $94 $00 $00 $46 $81 $FE [$00E2W]  $76 #Cache items got - end
             $EB $B8 $2A3ARW $8A $16 $EC $7A $8E $C0 $26 $08 $16 [$00FDW]  $E9 #Cache scoreboard

#Swimming Keen spawning code
%patch $F5EE $55 $8B $EC $8B $1E $A7D6W  $C7 $07 [$0002W]  $C7 $47 $02 [$0002W]
             $C7 $47 $20 [$0001W]  $8B $46 $06 $B1 $08 $D3 $E0 $89 $47 $0A $8B
             $46 $08 $D3 $E0 $89 $47 $0C $C7 $47 $0E [$0001W]  $C7 $47 $10 [$0001W]
                 $C7 $47 $06 [$0002W]  $B8 [$19ECW]  $50 $53 $9A $10B1118CRL   
             $83 $C4 $04 $5D $CB

Bubble production

These patches relate to Keen producing bubbles, preventing their production and modifying their production. This is in essence bubble spawning patches.

How often bubbles are produced

Keen's swimming behavior contains a timer that produces a bubble every $3C ticks, resetting the timer to 0 each time. The timer has a maximum value of $7F ticks, to increase this further the reset value can be made negative, needing to count up to zero first.

How often bubbles are produced

#How often bubbles are produced
%patch $F73F [$3C]    #Timer
%patch $F63D [$0000W] #Reset

No bubbles produced

There are three patches in this section. The first removes each bubble independently; each line of patch can be used separately, to remove more or less of the bubbles as desired. The second patch removes all of the bubbles at once. The third patch removes all bubbles and the sound Keen makes. Each patch overwrites the patches above it.

No bubbles

#Stop bubbles being produced (Each line stops one of the above bubbles)
%patch $F6B2 $90 $90 $90 $90 $90
%patch $F6C4 $90 $90 $90 $90 $90
%patch $F6D6 $90 $90 $90 $90 $90
%patch $F6E8 $90 $90 $90 $90 $90

No bubbles

#No bubbles (Skip list, go to sound)
%patch $F6A1 $EB

No bubbles or sound

#No bubbles or sound
%patch $F740 $EB

Swimming Keen fires shots

This patch replaces the bubbles produced by swimming Keen with a projectile that resembles and acts like the sprite's shot but will stun sprites like Keen's shot. It is produced regularly and uncontrollably, just like the bubbles. This frees swimming Keen from needing Dopefish, but requires him to have a Sprite in the same level to avoid an uncached sprite error. This patch is completely incompatible with most other patches on this page excepting the sprite positioning patch, action patches and list patches.

Swimming Keen fires shots

#Bubble fires in both directions, is type 3
%patch $F676  [$0003W]  $83 $7C $0E $01 $75 $07 $C7 $47 $0E [$0001W] $EB $05 $C7
              $47 $0E [$FFFFW]  $90 $90 $90 $90 $90 $90 $90

#Bubbles act like Sprite's shot
%patch $308D4 $01B4W $01B4W $0001W $0000W $0000W $000AW $0040W $0000W
              $00000000L    $00000000L    $11A20CA1RL   $1A82W
%patch $308F2 $01B5W $01B5W $0001W $0000W $0000W $000AW $0040W $0000W
              $00000000L    $00000000L    $11A20CA1RL   $1AA0W   
%patch $30910 $01B6W $01B6W $0001W $0000W $0000W $000AW $0040W $0000W
              $00000000L    $00000000L    $11A20CA1RL   $1ABEW
%patch $3092E $01B7W $01B7W $0001W $0000W $0000W $000AW $0040W $0000W
              $00000000L    $00000000L    $11A20CA1RL   $1A64W


This section contains patches relating to the bubbles produced by Keen as he swims, their properties and how they are produced.

By default Keen regularly produces bubble sprites which then move offscreen. It is possible to alter what is produced, however if the sprites are not regularly disposed of then they will quickly build up and overload the sprite array. It is also possible to stop anything being produced at all. There are four values, each produces a bubble with a different animation.

Bubbles are different only in action, which is determined by a list. The first subsections in this section will deal with bubble production, the next with properties of the bubbles themselves.

All bubbles share these properties, that is, altering them will alter the properties of all bubbles produced by Keen. Bubbles have a sprite type of 1; a foreground variable of 3, putting them in front of all tiles; an activity value of 3, making it vanish instantly when offscreen; clipping = 0, meaning it will move through all tiles, even blocking ones (and thus not get 'stuck') and finally a vertical speed of -24 and horizontal speed of 4.

Sprite Type

Bubbles are type 1, or 'misc'. This means they don't interact with anything by default.

Keen 4

#Bubble sprite type
%patch $F676 [$0001W]

Bubble actions

There are four different bubble actions each located in a different segment of code. What specific bubble action is produced at any one time is governed by a list of code pointers so that Keen cycles between producing four different types of bubble. it is notable that the bubbles do not change their actions, they remain the same until they vanish.

$1A64W #Bubble 1
$1A82W #Bubble 2
$1AA0W #Bubble 3
$1ABEW #Bubble 4

Bubble actions

#What is produced by swimming Keen
%patch $F6AB  [$1A64W] #Bubble 1
%patch $F6BD  [$1A82W] #Bubble 2
%patch $F6CF  [$1AA0W] #Bubble 3
%patch $F6E1  [$1ABEW] #Bubble 4

%patch $308F0 [$1A64W] #Bubble 1
%patch $3090E [$1A82W] #Bubble 2
%patch $3090E [$1AA0W] #Bubble 3
%patch $3094A [$1ABEW] #Bubble 4

Bubble action list

The values used in this patch are all the absolute location of the code +$E8F0 (The location of the executable segment the code is in.) The first value is the location of the list itself, the rest are the location of the bubble code. To limit the number of kinds of bubbles keen produces, simply change the length of the list. ($00 will result in only one kind of bubble produced for example.)

Another important variable is the divisor. The game starts by generating a random number between 0-255. It then divides this by 64 ($40) to get a number between 0-3. Changing the length of the list will require changing the divisor also, otherwise some entries my be missed or over represented. (Fewer entries require a larger divisor.)

Bubble action list

#Location of Bubble action list
%patch $F6A8 $0E0FW

#Length of list
%patch $F6AA $03

%patch $F697 [$0040W]

#Swimming Keen list
%patch $F6FF $0DBAW #Bubble 1
             $0DCCW #Bubble 2
             $0DDEW #Bubble 3
             $0DF0W #Bubble 4

Sprite Behavior

Bubbles have only one behavior, that used to float up offscreen and vanish when out of sight. It is used by all bubble actions, including the Dopefish's.

$11A20974RL #Bubble behavior

Keen 4

#Keen's bubble's behaviors
%patch $308E4 $11A20974RL
%patch $30902 $11A20974RL
%patch $30920 $11A20974RL
%patch $3093E $11A20974RL


Bubbles are spawned moving upwards and slightly right. This speed is added to their animation motion which also moves them upwards.

Bubble speeds

#Bubble float speeds
%patch $F68A [$FFE8W] #Vertical speed (Upwards)
%patch $F68F [$0004W] #Horizontal speed (Right)

Animation motion

%patch $308E0 [$0000W $0018W]
%patch $308FE [$0000W $0018W]
%patch $3091C [$0000W $0018W]
%patch $3083A [$0000W $0018W]

Sprite Collision

Keen's bubbles have no sprite collision, they affect no sprites at all.

Keen's bubbles' sprite collisions

#Keen's bubbles' sprite collision
%patch $336E8 $00000000L #No collision
%patch $33706 $00000000L #No collision
%patch $33724 $00000000L #No collision
%patch $33742 $00000000L #No collision


The bubble's animations are not cached with swimming Keen, instead they are cached with the Dopefish, meaning that one must be present in the level to avoid an uncached sprite error. As their animations don't change, their animation speed does not really matter.

Bubble animations

#Bubble animations
%patch $308D4 $019DW $019DW
%patch $308DE $0014W        #Animation speed
%patch $308F2 $019EW $019EW
%patch $308FC $0014W        #Animation speed
%patch $30910 $019FW $019FW
%patch $3091A $0014W        #Animation speed
%patch $3092E $01A0W $01A0W
%patch $30938 $0014W        #Animation speed

Sprite positioning

The bubble spawns 1.5 tiles in front of Keen if Keen is facing right. This is so it always appears to be spawned by his head.

Keen 4

#Shot spawn location
%patch $F661 [$0180W] #1.5 tiles in front of rightwards Keen

Sprite-tile interaction

Bubbles do not interact with tiles in any way. They thus use the default 'sit' tile collision that does nothing.

Keen 4

%patch $308DA $09DC176ERL #Bubble 1
%patch $308F8 $09DC176ERL #Bubble 2
%patch $30916 $09DC176ERL #Bubble 3
%patch $30934 $09DC176ERL #Bubble 4

Action type

Keen's bubbles use type 2 actions, moving smoothly and waiting to go offscreen and vanish.

Keen 4

%patch $308D8 {$0002W} #Keen's Bubble 1
%patch $308F6 {$0002W} #Keen's Bubble 2
%patch $30914 {$0002W} #Keen's Bubble 3
%patch $30932 {$0002W} #Keen's Bubble 4

Deprotect and stick to ground

Keen's bubbles do not need to stick to the ground or deprotect their animations. They thus have value 0 for both these variables.

Keen 4

%patch $308DA [$0000W $0000W] #Keen's bubble 1
%patch $308F8 [$0000W $0000W] #Keen's bubble 2
%patch $30916 [$0000W $0000W] #Keen's bubble 3
%patch $30934 [$0000W $0000W] #Keen's bubble 4

Sprite positioning

Because Keen's sprite is so long, when Keen faces right bubbles need to appear on the right side of it. To do this bubbles are spawned 24 pixels more right IF Keen is NOT facing left when he emits the bubble.

Keen 4

#Bubble spawn position
%patch $F64E [$FF]    #If Keen is not facing left
%patch $F661 [$0180W] #24 pixels right

Bubble sound

This sound is produced every time swimming Keen produces a bubble (See above section) about once per second.

Bubble sound

%patch $F6F1  [$24]

#Don't play sound
%patch $F6F4 $90 $90 $90 $90 $90

Clipping, activity and foreground

Bubbles have no clipping, allowing them to always drift offscreen, even through solid tiles. This is vital to prevent runaway sprite buildup.

Bubbles have a foreground value of 3, appearing in front of even foreground tiles. This is not really necessary but is included for effect.

Bubbles have an activity of 3, they keep functioning even when offscreen. (Where they vanish.) This is to ensure that Keen doesn't leave any behind by moving quickly, also adding to sprite buildup.

Keen 4

#Bubble clipping variable
%patch $F685 [$0000W]

#Bubble activity variable
%patch $F680 [$0003W]

#Bubble foreground variable
%patch $F67B [$0003W]