Patch:Patching Galaxy Sprites

From KeenWiki
Jump to navigation Jump to search

This patch is a tutorial on patching Galaxy sprites. It will give a demonstration of making an entirely new sprite in Keen 4 and altering its properties and behaviors while utilizing all the different kinds of sprite patches. If there is something in this tutorial that you do not understand, skip it, since the easier patches will come last, not first. However it is beneficial to be able to go through the entire tutorial in the right order.

A related page for Keen Vorticons) is Patch:Patching Vorticon Sprites

The first step is to take a clean copy of Keen 4 and place the 'I Keen', 'Mom' and 'Dad' sprites in level 1. By default this is only good for switches as it does nothing at all. Testing the level works fine, there is no indication the sprite is there. (If you do not know what the 'I Keen' and other sprites are, they have value $24-$26 (36-38) and have tile graphics that look like their description.)

Patches on this page will rely heavily on the Keen 4 sprite spawning patches.


Make unused sprites do something

The first step then is to make this sprite do something. This is done by changing the sprite's 'initiation pointer' from its default of 'BLANK' to something else. Looking at the Keen 4 initiation pointer list we see the following three entries for the sprites we placed:

Keen 4 pointer list

%patch $EECB [$050DW] #'I Keen' (At $EDFD)
%patch $EECD [$050DW] #'Mom' (At $EDFD)
%patch $EECF [$050DW] #'Dad' (At $EDFD)

%patch $EF1B [$04FBW] #Easy Bird(At $EDEB)
%patch $EF1D [$04F4W] #Medium Bird (At $EDE4)
%patch $EF1F [$04EDW] #Hard Bird (At $EDDD)


This is what stops the sprite doing anything; changing these values to that of another sprite will make our new sprites behave like existing sprites. As an example the following patches replace the default values with those of the Patch:Blue Bird.

New sprites behave exactly like Blue birds

%patch $EECB [$04FBW] #'I Keen' (At $EDFD)
%patch $EECD [$04F4W] #'Mom' (At $EDFD)
%patch $EECF [$04EDW] #'Dad' (At $EDFD)


Playing the level now results in the three new sprites behaving exactly like Easy, Medium and hard Blue Birds. On its own this patch is pretty pointless, but it is the start for the next step in creating a totally new sprite.


Making new sprites initiate differently

The next step is to patch in some new initiation code, that is the code that controls what circumstances cause the sprite to actually appear in the level, as well as what animations are cached. By default the conditions involved are usually the game difficulty, leading to more enemies on harder difficulty levels.

Initiation code must be placed after the start of the sprite spawn segment, which is $E8F0 in Keen 4. This limits possible code locations severely and means that something will need to be sacrificed to provide space. In this example Keen's swimming behaviors at $F707 - $F89D are going to be sacrificed. The following patch makes the new sprites act just like Blue Birds, but only appear when Keen has more than 0, 10 or 20 shots:

New sprites behave exactly like Blue birds

#Sprites use new initiation code
%patch $EECB [$0E25W] #0 ammo Bird (At $F715)
%patch $EECD [$0E1EW] #10 ammo Bird (At $F70E)
%patch $EECF [$0E17W] #20 ammo Bird (At $F707)

#New initiation code
%patch $F707 $83 $3E [$7A58W]  {$14 $7C} $19 $83 $3E [$7A58W]  {$0A $7C} $12 $FF $76
             $FC $57 $9A {$0FA805B9RL}     $83 $C4 $04 $C7 $06 $5F $CB $0001W  $E9 $F6D3W


The first thing to notice is that the new initiation code is based on the original Blue Bird spawning code. Secondly the game stat 'difficulty' has been changed to 'ammo' and the values from 2 and 3 to 20 and 10. The third thing to notice is that since the code's new location is F707 and the old location EDDD a jump $E9 $F6D6W is added to the end to meet up with the sprite spawning code which is now $92A or 2346 bytes away. ($100000 - $92A - 3 = $F6D3; the -3' is due tot he length of the jump, three bytes.)

Another thing to note is the values used for initiation pointers. The 0, 10 and 20 ammo Birds start in different places in this chunk of code and thus have different values. (They are the Bird's values plus $92A.) The pointer value is this code location minus $E8F0. (The start of the sprite spawn segment.)

Running the game with this patch will always spawn a Blue Bird in level 1, 2 if Keen has more than 10 ammo and 3 is Keen has more than 20 ammo.


Adding custom spawn code

The previous patch allows existing enemies to appear in the level under novel circumstances. The next step is to add a spawning behavior to give the new sprites new properties. Spawn cod is called in the initiation code and can be placed anywhere in the executable. Since Keen's swimming behavior has already been sacrificed, the new spawn code will be placed right after the initiation code in this example:

New sprites behave exactly like Blue birds, but alterable

#Sprites use new initiation code
%patch $EECB [$0E25W] #0 ammo Bird (At $F715)
%patch $EECD [$0E1EW] #10 ammo Bird (At $F70E)
%patch $EECF [$0E17W] #20 ammo Bird (At $F707)

#New initiation code
%patch $F707 $83 $3E [$7A58W]  {$14 $7C} $19 $83 $3E [$7A58W]  {$0A $7C} $12 $FF $76
             $FC $57 $9A {$0E8F0E3ARL}     $83 $C4 $04 $C7 $06 $5F $CB $0001W  $E9 $F6D3W

#New spawning code ($0E8F0E3ARL)
%patch $F72A  $55 $8B $EC $B8 $01 $00 $50 $9A $06BD1E11RL     $83 $C4 $02 $8B
              $1E $D8 $A7 $C7 $07 [$001BW]  $C7 $47 $02 [$0001W]  $C7 $47 $20 [$0002W]
                  $8B $46 $06 $B1 $08 $D3 $E0 $89 $47 $0A $8B $46 $08 $D3 $E0
              $05 [$FF0FW]  $89 $47 $0C $8B $47 $0A $8B $1E $A7D6W  $3B $47 $0A
              $73 $0B $8B $1E $D8 $A7 $C7 $47 $0E [$0001W ] $EB $09 $8B $1E $D8
              $A7 $C7 $47 $0E [$FFFFW]  $8B $1E $D8 $A7 $C7 $47 $10 [$0001W]  $B8
              [$21B6W]  $50 $53 $9A $09DC118CRL     $83 $C4 $04 $5D $CB

The first thing to notice is that the 'new' spawn code here is exactly identical to the default Blue Bird spawn code found on its page. Running this patch in our setup will have results exactly identical to the previous patch, Blue Birds that appear when Keen has a certain number of shots.

The second thing to notice is that the initiation code has been altered; the second line now calls the new spawning code instead of the original Blue Bird code ($0FA805B9RL). Handily the new spawn code is in the same segment as the initiation code.

There are a number of things that can be done at this stage; altering the sprite action at the start of the last line can change the Blue Birds into Bounders or Underwater Mines or many other enemies. Changing the sprite type in the first line ($001B) can allow Keen to stand on the new sprites, or even use them as items. Following that are the (slightly less useful) clipping and foreground variables. It is also possible (maybe even simpler) to copy other enemy spawning codes to this same location to spawn various enemies.

At this point it may pay to revisit the sprite spawning page to check how spawning codes work.


A note on $xxxxxxxxRL patches

A patcher may question the use of $0E8F0E3ARL to represent the custom spawn code at $F72A; how is this value arrived at? This is an example of a 'far call' using 'executable segments'. In brief, when calling a specific location in this manner a four byte patch is needed specifying a big chunk of the executable (segment) and the location of the code within that chunk (offset). Checking the link in this paragraph reveals that the spawning code is located in segment $E8F0; $E8F0 + $0E3A = $F72A. (If confusion remains, read the executable segments page.)


Adding custom actions

The previous patch is very versatile, but it still results in enemies that behave mostly like the originals. While some surprises are possible (Such as Birds you can ride.) in general little changes. A lot more potential is created if custom actions are added to the game. Actions are the control center of sprites, governing their appearance, behavior and more. The following patch adds a few simple custom actions to the sprites:

New sprites have unique characteristics

#Sprites use new initiation code
%patch $EECB [$0E25W] #0 ammo bottle (At $F715)
%patch $EECD [$0E1EW] #10 ammo bottle (At $F70E)
%patch $EECF [$0E17W] #20 ammo bottle (At $F707)

#New initiation code
%patch $F707 $83 $3E [$7A58W]  {$14 $7C} $19 $83 $3E [$7A58W]  {$0A $7C} $12 $FF $76
             $FC $57 $9A {$0E8F0E3ARL}     $83 $C4 $04 $C7 $06 $3F $CB $0001W  $E9 $F6D3W

#New spawning code ($0E8F0E3ARL)
%patch $F72A  $55 $8B $EC $33 $C0 $50 $9A $06BD1E11RL     $83 $C4 $02 $8B $1E
              $D8 $A7 $C7 $07 [$0009W]  $C7 $47 $02 [$0001W]  $C7 $47 $20 [$0000W] 
              $8B $46 $06 $B1 $08 $D3 $E0 $89 $47 $0A $8B $46 $08 $D3 $E0 $05
              [$FF0FW]  $89 $47 $0C $C7 $47 $0E [$0001W]  $C7 $47 $10 [$0001W]  $B8
              [$016AW]  $50 $53 $9A $09DC118CRL     $83 $C4 $04 $5D $CB

#New actions, 2 frames of bouncing coke can ($016A and $0188W)
%patch $2EFDA [$00E3W $00E4W] $0003W $0000W $0000W $0008W [$0040W] $0000W
              $0FA80493RL   $0FA804BERL   $0FA804ECRL   $0188W
%patch $2EFF8 [$00E4W $00E3W] $0003W $0000W $0000W $0008W [$0040W] $0000W
              $0FA80493RL   $0FA804BERL   $0FA804ECRL   $016AW


The first thing to notice is that the spawn code is totally different. The basic code is that of the Mad Mushroom (See link for details.) since this new enemy will be more like the Mushroom than the Bird. There is however one difference from the default Mushroom spawn code; the sprite's action, initially $20E4W (Mad Mushroom) has been changed to a custom value, $016AW.

The custom actions (two of them in this example) follow the spawning code. They use the Mad Mushroom's values, with a few interesting tweaks. Firstly the soda can item's animations, so they appear as bouncing items. Secondly, unlike Mushrooms, they have animation motion and will thus bounce towards Keen, attacking him. (These changed values are highlighted in blue in the actions.)

The custom actions are being stored over the EGAGRAPH error messages, that are not used by the game. (There is space for only 3 new actions here.) When adding new actions it is best to either overwrite other sprite actions, sacrificing that sprite, or to use the same space as error texts (Which should not be used in a properly functioning game and may well be hard o trigger even when modding.)

Another thing to notice is that the sprite cache in the initiation code has been altered, originally this was the Blue Bird's cache, $C7 $06 $5F $CB $0001W, but now it is the soda bottle's, $C7 $06 $3F $CB $0001W. This is to stop the level crashing with an uncached sprite error when the new enemy appears.

The result when running this patch is a novel enemy made from existing sprite codes.


Adding custom behaviors

Now we are in a position to add custom behaviors. While a lot can be done with actions, there are still severe limitations imposed by the default sprite codes; the Mad Mushroom behavior and tile collision for example are one of the few codes that will not result in the new enemy transforming into another sprite. The following patch replaces the Mad Mushroom's 'turn towards Keen' behavior with one that does the opposite, the bottle now flees Keen:

New sprites are Keen-fleeing deadly soda bottles

#Sprites use new initiation code
%patch $EECB [$0E25W] #0 ammo bottle (At $F715)
%patch $EECD [$0E1EW] #10 ammo bottle (At $F70E)
%patch $EECF [$0E17W] #20 ammo bottle (At $F707)

#New initiation code
%patch $F707 $83 $3E [$7A58W]  {$14 $7C} $19 $83 $3E [$7A58W]  {$0A $7C} $12 $FF $76
             $FC $57 $9A {$0E8F0E3ARL}     $83 $C4 $04 $C7 $06 $3F $CB $0001W  $E9 $F6D3W

#New spawning code ($0E8F0E3ARL)
%patch $F72A  $55 $8B $EC $33 $C0 $50 $9A $06BD1E11RL     $83 $C4 $02 $8B $1E
              $D8 $A7 $C7 $07 [$0009W]  $C7 $47 $02 [$0001W]  $C7 $47 $20 [$0000W] 
              $8B $46 $06 $B1 $08 $D3 $E0 $89 $47 $0A $8B $46 $08 $D3 $E0 $05
              [$FF0FW]  $89 $47 $0C $C7 $47 $0E [$0001W]  $C7 $47 $10 [$0001W]  $B8
              [$016AW]  $50 $53 $9A $09DC118CRL     $83 $C4 $04 $5D $CB

#New actions, 2 frames of bouncing coke can ($016A and $0188W)
%patch $2EFDA $00E3W $00E4W $0003W $0000W $0000W $0008W $0040W $0000W
              [$0E8F0E88RL]   $0FA804BERL   $0FA804ECRL   $0188W
%patch $2EFF8 $00E4W $00E3W $0003W $0000W $0000W $0008W $0040W $0000W
              [$0E8F0E88RL]   $0FA804BERL   $0FA804ECRL   $016AW

#New behavior, turn away from Keen (Makes bottle flee Keen. = $0E8F0E88RL)
%patch $F778  $55 $8B $EC $56 $8B $76 $06 $8B $1E $A7D6W  $8B $47 $0A $3B $44
              $0A {$73 $07} $C7 $44 $0E [$0001W]  $EB $05 $C7 $44 $0E [$FFFFW]  $56
              $9A $09DC1315RL     $83 $C4 $02 $5E $5D $CB


Notice that since there is still space available, the new behavior is placed right after the new spawning code, where swimming Keen's sacrificed behavior was. This new behavior ($0E8F0E88RL)) now appears in the custom actions replacing the Mad Mushroom's ($0FA80493RL). The value is highlighted in blue.

Another thing to notice is that the 'new' behavior is just a copy of the Mad Mushroom's behavior, with its Keen seeking reversed. Those who know what they are doing can create a new behavior completely from scratch, but those who do not can simply copy an existing behavior from a sprite's page and tweak it slightly, as was done here for simplicity.

Running this patch results in a deadly soda bottle that runs away from Keen.


A note on code locations

At this point some modders may be confused as to how to calculate the locations of everything in the above patch. The location of the initiation code is simple enough, it simply replaces an existing behavior at a certain spot. The same logic would apply if the spawn code overwrote something else, such as the Mad Mushroom's behavior. (Simply look up the relevant patch page and find the address there.) But how is the spawn code's location calculated, or the behavior's?

If a modder has access to hex editor then it is a simple enough matter of using the %dump patch to see where various bits of patch code end. (Trial and error.) However there is an alternate method. The initiation code is exactly $23 (35) bytes long, where $xx counts as one byte, $xxxxW as two and $xxxxxxxxRL as four. $F707 + $23 = $F72A. A similar calculation works for the new behavior code. (Anyone unable to add in hexadecimal will be unable to do any of the patches on this page.)


Adding custom tile collision

Adding a custom tile collision is similar to the above, however it is more tricky since tile collisions are rarer than behaviors and often more complex. It is often best just to copy an existing tile collision from an enemy, or use a versatile default such as the 'turn at walls or edges' collision used by many sprites (E.g. the Poison Slug.)


Adding custom sprite collision

Adding a custom sprite collision is similar again to adding a new behavior, and about as difficult. The following patch makes the bottle lethal but be stunable:

New sprites are Keen-fleeing pushy soda bottles

#Sprites use new initiation code
%patch $EECB [$0E25W] #0 ammo bottle (At $F715)
%patch $EECD [$0E1EW] #10 ammo bottle (At $F70E)
%patch $EECF [$0E17W] #20 ammo bottle (At $F707)

#New initiation code
%patch $F707 $83 $3E [$7A58W]  {$14 $7C} $19 $83 $3E [$7A58W]  {$0A $7C} $12 $FF $76
             $FC $57 $9A {$0E8F0E3ARL}     $83 $C4 $04 $C7 $06 $3F $CB $0001W  $E9 $F6D3W

#New spawning code ($0E8F0E3ARL)
%patch $F72A  $55 $8B $EC $33 $C0 $50 $9A $06BD1E11RL     $83 $C4 $02 $8B $1E
              $D8 $A7 $C7 $07 [$0009W]  $C7 $47 $02 [$0001W]  $C7 $47 $20 [$0000W] 
              $8B $46 $06 $B1 $08 $D3 $E0 $89 $47 $0A $8B $46 $08 $D3 $E0 $05
              [$FF0FW]  $89 $47 $0C $C7 $47 $0E [$0001W]  $C7 $47 $10 [$0001W]  $B8
              [$016AW]  $50 $53 $9A $09DC118CRL     $83 $C4 $04 $5D $CB

#New actions, 2 frames of bouncing coke can ($016A and $0188W)
%patch $2EFDA $00E3W $00E4W $0003W $0000W $0000W $0008W $0040W $0000W
              $0E8F0E88RL   [$0E8F0EB3RL]   $0FA804ECRL   $0188W
%patch $2EFF8 $00E4W $00E3W $0003W $0000W $0000W $0008W $0040W $0000W
              $0E8F0E88RL   [$0E8F0EB3RL]   $0FA804ECRL   $016AW

#New behavior, turn away from Keen (Makes bottle flee Keen. = $0E8F0E88RL)
%patch $F778  $55 $8B $EC $56 $8B $76 $06 $8B $1E $A7D6W  $8B $47 $0A $3B $44
              $0A {$73 $07} $C7 $44 $0E [$0001W]  $EB $05 $C7 $44 $0E [$FFFFW]  $56
              $9A $09DC1315RL     $83 $C4 $02 $5E $5D $CB

#New collision (Deadly, can be shot = $0E8F0EB3RL)
%patch $F7A3 $55 $8B $EC $56 $57 $8B $76 $06 $8B $7E $08 $83 $3D {$02 $75} $09   #Check for Keen (Type 2)
             $9A $0B8013E9RL     $5F $5E $5D $CB $83 $3D {$03 $75} $1F $B8       #If Keen, kill him; check for shot (Type 3)
             [$01A6W]  $50 $57 $56 $9A $09DC1695RL     $83 $C4 $06 $C7 $44 $18     #If shot, become $01A6W
             [$FFE8W]  $8B $44 $0E $D1 $E0 $D1 $E0 $D1 $E0 $89 $44 $16 $5F $5E $5D #Jump into the air $FFE8
             $CB

#New stunned action ($01A6W)
%patch $2F016 $00E3W $00E3W $0002W $0000W $0000W $0000W $0000W $0000W 
              $09DC16C9RL   $00000000L    $09DC1913RL   $0000W

Notice again that the new collision is after the new behavior since there is still room in the sacrificed behavior. The new collision value ($0E8F0EB3RL) is in the new actions, replacing the old Mad Mushroom values ($0FA804BERL). This is highlighted in blue.

Notice that a new action has had to be added, since we now have a stunned soda bottle. This is shown in the new collision and the new action is placed just after the two new bouncing bottle actions. It must use the soda bottle animation since the soda bottle cache has only two animations. (If the collision action was set to $1F46W however the bottle would become a raindrop splash, as if shooting it had broken it. This works since raindrop splash animations are always cached in Keen 4.)


Final patch

This is the complete example patch, it is basically the same as the above patch, but with a few tweaks. The bottle's sprite type is changed to that of the bounder, so Keen can ride on it. It now jumps higher when shot as well. There are many more tweaks that can be done with this patch as it is and hopefully it illustrates how to create a new enemy in Keen Galaxy and Dreams.

New sprites are Keen-fleeing pushy soda bottles

#Sprites use new initiation code
%patch $EECB [$0E25W] #0 ammo bottle (At $F715)
%patch $EECD [$0E1EW] #10 ammo bottle (At $F70E)
%patch $EECF [$0E17W] #20 ammo bottle (At $F707)

#New initiation code
%patch $F707 $83 $3E [$7A58W]  {$14 $7C} $19 $83 $3E [$7A58W]  {$0A $7C} $12 $FF $76
             $FC $57 $9A {$0E8F0E3ARL}     $83 $C4 $04 $C7 $06 $3F $CB $0001W  $E9 $F6D3W

#New spawning code ($0E8F0E3ARL)
%patch $F72A  $55 $8B $EC $33 $C0 $50 $9A $06BD1E11RL     $83 $C4 $02 $8B $1E
              $D8 $A7 $C7 $07 [$000FW]  $C7 $47 $02 [$0001W]  $C7 $47 $20 [$0000W] 
              $8B $46 $06 $B1 $08 $D3 $E0 $89 $47 $0A $8B $46 $08 $D3 $E0 $05
              [$FF0FW]  $89 $47 $0C $C7 $47 $0E [$0001W]  $C7 $47 $10 [$0001W]  $B8
              [$016AW]  $50 $53 $9A $09DC118CRL     $83 $C4 $04 $5D $CB

#New actions, 2 frames of bouncing coke can ($016A and $0188W)
%patch $2EFDA $00E3W $00E4W $0003W $0000W $0000W $0008W $0040W $0000W
              $0E8F0E88RL   $0E8F0EB3RL   $0FA804ECRL   $0188W
%patch $2EFF8 $00E4W $00E3W $0003W $0000W $0000W $0008W $0040W $0000W
              $0E8F0E88RL   $0E8F0EB3RL   $0FA804ECRL   $016AW

#New behavior, turn away from Keen (Makes bottle flee Keen. = $0E8F0E88RL)
%patch $F778  $55 $8B $EC $56 $8B $76 $06 $8B $1E $A7D6W  $8B $47 $0A $3B $44
              $0A {$73 $07} $C7 $44 $0E [$0001W]  $EB $05 $C7 $44 $0E [$FFFFW]  $56
              $9A $09DC1315RL     $83 $C4 $02 $5E $5D $CB

#New collision (Deadly, can be shot = $0E8F0EB3RL)
%patch $F7A3 $55 $8B $EC $56 $57 $8B $76 $06 $8B $7E $08 $83 $3D {$02 $75} $09   #Check for Keen (Type 2)
             $9A $0B8013E9RL     $5F $5E $5D $CB $83 $3D {$03 $75} $1F $B8       #If Keen, kill him; check for shot (Type 3)
             [$01A6W]  $50 $57 $56 $9A $09DC1695RL     $83 $C4 $06 $C7 $44 $18     #If shot, become $01A6W
             [$FF88W]  $8B $44 $0E $D1 $E0 $D1 $E0 $D1 $E0 $89 $44 $16 $5F $5E $5D #Jump into the air $FFE8
             $CB

#New stunned action ($01A6W)
%patch $2F016 $00E3W $00E3W $0002W $0000W $0000W $0000W $0000W $0000W 
              $09DC16C9RL   $00000000L    $09DC1913RL   $0000W