Patch:Text windows

From KeenWiki
Jump to navigation Jump to search

This page deals with the text windows in Keen. These are a subset of Patch:Text patches, involving windows that appear in-game (Usually in-level) with text (and in Galaxy, images) in them.

In essence the execution is quite simple. Some event (flag) will trigger the window. The window will appear (In Keen Galaxy\Dreams instantly, in Vorticons via a step-by-step expansion as the window rapidly grows to full size and displays text.) with text in it. The player can often exit the window by pressing a key (or by waiting a set period of time.) at which point the window will vanish and other events may occur.

There is some difference between Keen Vorticons and Keen Galaxy\Dreams windows due to the different engines being used.


The window

In Keen the window is made up of 8x8 unmasked tiles. Keen Vorticons is rather unique in also storing its font in this manner, making the entire window a grid of 8x8 squares. The windows use 8 tiles from the tileset (Four corners, four sides, which tiles can be patched, though there is little point to this.)

The main attribute of a window is its size\location. (The two are interchangeable to some extent.) There are in general two ways to patch this. The first defines the location of all four corners of a window. As this is complicated, it is not often used. (For example in the Keen Vorticons ending sequences, where windows of different sizes in different locations are needed.) For these there will be four patches such as follows:

Keen 1 Map ending textbox

%patch $821E $0F $00 #Top
%patch $8216 $14 $00 #Bottom
%patch $821A $2A $00 #Right side
%patch $8222 $05 $00 #left side

The second method is to simply specify the window's height and width, the window will be 'centered' somewhere on the screen (usually the center, but not always.)

Keen 1 Yorp messages textbox

%patch $2508 $0A $00 #Height
%patch $250C $15 $00 #Width

In both these cases the screen is divided into 8x8 blocks, with the top left of the screen being 2,2.


Text

Most windows will contain text, rather similar in format to Patch:Text patches. All windows will need to call their text from the text segment in the executable, as detailed on that page. Text that is too large for the window to contain will write right through the window (Vorticons) or give a 'string exceeds width' error (Galaxy)

Vorticons text is 8x8 tiles, meaning it is easy to calculate what will fit in a window. Galaxy and Dreams use a standard monochrome font where each letter has a differing width, which makes this more difficult.

There are some text characters that cannot be patched as characters, but must be patched as hex values. These are double quotation marks ($22), end of line ($0A) and end of text ($00) as well as any characters that will be altered by the program being used to edit the patchfile.


Bitmaps, music and sound

The biggest difference is that Galaxy Windows (And only Galaxy windows, not Dreams.) can display bitmap images and play sounds, as well as switch music. Because of memory constraints, these are not cached when the level is loaded, taking up valuable memory space. These are instead loaded when the window is opened, meaning if there is not enough free memory, the game can crash. Also, because of how the windows operate, bitmaps for a windows sequence must be cached before the first window is opened. An example is from Keen 6's Grabbiter window:

Keen 6 Grabbiter window

%patch $F54E  $23 $00 #Store this bitmap (35 - 6 = 29)
%patch $F57B  $23 $00 #Show this bitmap (35 - 6 = 29)

The bitmap is cached before the first window is opened and can be displayed in any further windows. The bitmap's value is also interesting, the game refers to graphics by chunk number, while modkeen exports differently, meaning a patcher must add a certain value to the bitmap they want to use to get the chunk number the game uses. For Keen 6 this is, oddly enough, +6.


Differences between Galaxy and Vorticons windows

  • Vorticons windows use 8x8 tiles for letters and can display 'images' in the window in this manner, Galaxy\Dreams use a monochrome font where letters have differing widths and are drawn over the window
  • Galaxy windows can play music, sounds and display images
  • Galaxy windows are always centered, almost always on the center of the screen
  • It is impossible to have text longer than the window in Galaxy without crashing the game
  • Galaxy windows use only one line of text per window. If the text changes a new window must be opened


Example window codes

This section shows an example of text window code; a patch that contains the complete code to draw a window in various games.


Keen 4: can't swim window

This is the complete 'can't swim' window code. This window is displayed on the map when Keen tries to enter water-type tiles and doesn't have the Wetsuit. It is a standalone window containing a single bitmap image and a message.

On the first line chunk 111 is cached for display. On the second line the window's height and width are set. On the third line chunk 111 is displayed in the window. The fourth line contains the 'image width variable' used to position the text in the window along with the image.

The text itself is called at the end of line 5. At the start of line 7 is a pause where the window can't be dismissed. (Vital to stop the player accidentally skipping it.)

Complete Can't swim window code

#Complete Can't swim window code
%patch $F356 $55 $8B $EC $9A $18740AFDRL     $9A $12A614CDRL     $B8 [$006FW]
             $50 $9A $12A61117RL     $83 $C4 $02 $B8 [$0008W]  $50 $B8 [$001AW]
             $50 $9A $19311070RL     $83 $C4 $04 $B8 [$006FW]  $50 $FF $36 $DE
             $A7 $A1 $33 $A5 $03 $06 $31 $A5 $2D [$0030W]  $50 $9A $1D060C79RL
                 $83 $C4 $06 $83 $2E $31 $A5 $30 $83 $06 $35 $A5 $0C $B8 [$1BCDW]
                 $50 $9A $19310EBDRL     $83 $C4 $02 $9A $1D060A9BRL     $B8
             [$001EW]  $50 $9A $1E0A0AD3RL     $83 $C4 $02 $9A $146008A8RL   
             $9A $14600EDFRL     $9A $12A614EDRL     $5D $CB


Keen 5: simple fuse window

This is a simplified version of the Fuse window. This window is displayed when Keen breaks a fuse in levels It is a standalone window containing a single bitmap image and a message. It has been simplified from the original window that displayed one of two messages and two bitmaps, requiring two keypresses to dismiss.

On the second line chunk 90 is cached for display. On the third and fourth lines the window's height and width are set. On the fifth line chunk 90 is displayed in the window.

The text itself is called at the end of line 6. At the start of line 7 is a pause where the window can't be dismissed. (Vital to stop the player accidentally skipping it.)

Simplified Fuse window code

#Simplified Fuse window code
%patch $F844 $55 $8B $EC $9A $196E0AFBRL     $9A $13A014CARL     $B8 $2B7BRW
             $8A $16 $EC $6F $8E $C0 $26 $08 $16 [$005AW]  $33 $C0 $50 $9A
         $13A01848RL     $83 $C4 $02 $9A $1E000995RL     $B8 [$0008W]  $50 $B8
             [$001AW]  $50 $9A $1A2B106ERL     $83 $C4 $04 $83 $2E $99 $9B $30
             $B8 [$005AW]  $50 $FF $36 $46 $9E $A1 $9B $9B $03 $06 $99 $9B $50
             $9A $1E000C75RL     $83 $C4 $06 $83 $06 $9D $9B $0C $B8 [$18E0W]
             $50 $9A $1A2B0EBBRL $83 $C4 $02 $9A $1E000A97RL     $B8 [$001EW] 
             $50 $9A $1F030ADFRL     $83 $C4 $02 $9A $155A08A5RL     $9A $155A0EDCRL
                         $9A $13A014EARL     $9A $06B9204ERL     $5D $CB


Keen 6: Rocket Passcard Obtained window

This is the complete window code for the window that appears when the Rocket Passcard is obtained. The first line plays sound $2D, the second line caches Keen's head bitmap ($0023W) which is then displayed on line 4. Notice that bitmaps are referred to by their 'chunk number', that is, what graphic chunk they are in EGAGRAPH.CK6; this is the bitmap number (When exported via ModKeen, Keengraph numbers the bitmaps 'correctly') plus six. The window's size is set on line 3 as being $08x$1A

The image is aligned right by $0030W pixels. By default this is the same as the image's width so that the displayed bitmap is 'right aligned'. Paired with this is a second, equal variable that moves the text in the opposite direction so that it is not centered in the window (and thus overwriting the bitmap.) These variables can be 'reversed' by making them negative. (Changing $0030W to $FFD0W and $30 to $D0 for example.)

Finally the text call on line 6 which determines where the window's text is called from. (See Patch:Text patches.) The value $001EW is the 'pause' before the player can dismiss the window by pressing a key. Finally after the window has been displayed the rocket passcard variable is set to 1 on the last line. (The card is given.)

Keen 6

#Complete Rocket Pass got window code
%patch $EF38 $55 $8B $EC $9A $183B0AFDRL     $B8 [$002DW]  $50 $9A $183B09F1RL
                 $83 $C4 $02 $9A $125A14BERL     $B8 [$0023W]  $50 $9A $125A1108RL
                     $83 $C4 $02 $B8 [$0008W]  $50 $B8 [$001AW]  $50 $9A
         $18F81070RL     $83 $C4 $04 $B8 [$0023W]  $50 $FF $36 $6C $A9 $A1 $C1 $A6
             $03 $06 $BF $A6 $2D [$0030W]  $50 $9A $1CF70C83RL     $83 $C4 $06
             $83 $2E $BF $A6 [$30] $83 $06 $C3 $A6 $04 $B8 [$18EAW]  $50 $9A
         $18F80EBDRL     $83 $C4 $02 $9A $1CF70AA5RL     $B8 [$001EW]  $50 $9A
             $1DFB0ADDRL     $83 $C4 $02 $9A $141308A9RL     $9A $14130EE0RL
             $9A $125A14DERL     $C7 $06 {$7598W}  [$0001W]  $5D $CB


Window border tiles

This patch allows a modder to alter the 8x8 masked tiles used for window borders. This probably won't be needed under most circumstances.

Any line can be omitted or included without affecting the others. The exception is the patch for the top left corner of the box, which requires the last two lines of code to make it work.

Keen Dreams

#Window tiles used
%patch $13B52 [$0006W] #Bottom left corner of box
%patch $13B71 [$0001W] #Top of box
%patch $13B7F [$0007W] #Bottom of box
%patch $13BA0 [$0002W] #Top right corner of box
%patch $13BB0 [$0008W] #Bottom right corner of box
%patch $13BCC [$0003W] #Left side of box
%patch $13BDC [$0005W] #Right side of box

#Top left corner of box
%patch $13B42 $B8 [$0000W] $50 $57 $FF $76 $FE $9A $0CA5094BRL     $44 $44
%patch $13B65 $0A


Add Message Windows to Keen Dreams

This patch adds a 'note tile' to Keen Dreams. It exploits the default property 'Top of fire', which does nothing in the original game. With this patch any tile of that property can be 'read' if the player presses the up key while in front of it. (Unless the tile is at their feet, in which case the down key will suffice.)

Reading the note plays sound $04, changes the player's animation to $63 and, after a short pause, brings up a text window. The window is $09 by $1C in size and reads from a text list at $23A70 + $012CW = $23B9C.

This allows a different message in every game level (Except level 0, the map, which Keen cannot behave normally in.) This patch uses some unused 'napping Keen tile collision' code and also moves some of Keen's pole gripping code to another location. This will make it incompatible with some pole patches.

Keen Dreams

#Note reading action
%patch $24BDC [$0063W $0063W] $0000W $0000W $0000W $0040W $0000W $0000W
              $05E81D64RL   $05E817FCRL   $05E81AE2RL   $0ED8W

#Modify Keen's code to trigger note (+2)
%patch $6C6C $74 $04 $7D $05 $EB $25 $E9 $0F3EW $C7 $44 $1E $116CW  $B8 [$0004W]
             $50 $9A $10BB1282RL     $44 $44 $B8 $0001W  $5F $5E $8B $E5 $5D $CB

#Move pole grip to here
%patch $7BB3 $8B $C7 $D3 $E0 $05 $FF80W  $2B $44 $0A $89 $44 $12 $A1 $7020W
             $B1 $05 $D3 $E0 $89 $44 $14 $89 $7C $44 $C7 $44 $06 $0000W  $C7
             $44 $1E $118AW  $B8 $0001W  $EB $02 $33 $C0 $5F $5E $8B $E5 $5D $CB

#Message window =$05E81D64RL
%patch $7BE4 $55 $8B $EC $4C $4C $56 $B8 [$0009W]  $50 $B8 [$001CW]  $50 $9A
         $11FA1C64RL     $83 $C4 $04 $8B $1E $8F3EW  $D1 $E3 $FF $B7 [$012CW]
             $9A $11FA1ABBRL     $44 $44 $9A $0CA508C0RL     $9A $0FE40C8ERL
                     $9A $0E450A00RL    $5E $8B $E5 $5D $CB

#Message pointer list
%patch $23B9E [$014EW] #Level 1
              [$014EW] #Level 2
              [$014EW] #Level 3
              [$014EW] #Level 4
              [$014EW] #Level 5
              [$01A9W] #Level 6
              [$01A9W] #Level 7
              [$01A9W] #Level 8
              [$01A9W] #Level 9
              [$01A9W] #Level 10
              [$0218W] #Level 11
              [$0218W] #Level 12
              [$0218W] #Level 13
              [$0218W] #Level 14
              [$0218W] #Level 15
              [$0218W] #Level 16

#Texts
%patch $23BBE "First message." $00
%patch $23C19 "Second message." $00
%patch $23C88 "Third message." $00


Add a second\third window type to Keen Dreams

These patches allow a modder to add a second and\or third type of window to Keen Dreams. That is to say, certain windows can use a different set of border tiles giving them a different appearance. The first patch involves overwriting the game's startup low memory check. while the second overwrites an unused screen fade. Both patches are independent but share some code. (The duplicate code only needs to be patched once.) They also involve using unused 8x8 masked tiles from the game's graphics.

The default values for the window border are stored in the first blue list. The blue $0C values are what are added to each value to get the new border tile used for 'special' windows. In this patch the new border tiles are 12 tiles 'ahead' of the normal ones. (The values do not have to be the same, nor do all need to change.)

The brown values in the text window call list match up with those in the border alteration code. For example $01CDW is the variable for the bottom left corner. The final list is a selection of optional patches that apply the new border to various game windows.

Keen Dreams 2nd window border type patch

#Ignore low memory (Frees $3A45-$3AB8)
%patch $3A43 $EB $74

#Default window values
%patch $23C3B [$0000W $0006W $0001W $0007W $0002W $0008W $0003W $0005W]

#Text windows call default variables
%patch $13B51 $A1 {$01CDW} #Bottom left corner of box
%patch $13B70 $A1 {$01CFW} #Top of box
%patch $13B7E $A1 {$01D1W} #Bottom of box
%patch $13BA1 $A1 {$01D3W} #Top right corner of box
%patch $13BAF $A1 {$01D5W} #Bottom right corner of box
%patch $13BCB $A1 {$01D7W} #Left side of box
%patch $13BDB $A1 {$01D9W} #Right side of box
%patch $13B42 $A1 {$01CBW} #Top left corner of box
              $50 $57 $FF $76 $FE $9A $0CA5094BRL     $44 $44
%patch $13B65 $0A

#Window border alteration code =$00003A45RL
%patch $3A45 $55 $8B $EC $56 $57 $8B $76 $06 $8B $7E $08 $9A $00003A78RL 
             $57 $56 $B8 $0019W  $2B $C7 $D1 $E8 $50 $B8 $0028W  $2B $C6 $D1 $E8 $50
             $9A $11FA1B27RL     $83 $C4 $08 $9A $00003A78RL     $5F $5E $5D $CB
%patch $3A78 $55 $8B $EC $83 $36 {$01CBW}  [$0C] $83 $36 {$01CDW}  [$0C] $83 $36 {$01CFW}
                 [$0C] $83 $36 {$01D1W}  [$0C] $83 $36 {$01D3W}  [$0C] $83 $36 {$01D5W}
             [$0C] $83 $36 {$01D7W}  [$0C] $83 $36 {$01D9W}  [$0C] $5D $CB

#Make windows use new border:
%patch $37D2  $00003A45RL #F10-G cheat window
%patch $381B  $00003A45RL #F10-I cheat window
%patch $386A  $00003A45RL #F10-J cheat window
%patch $38C9  $00003A45RL #F10-S cheat window
%patch $3919  $00003A45RL #F10-W cheat window
%patch $3CA8  $00003A45RL #Game over window
%patch $3CD8  $00003A45RL #Status window
%patch $4521  $00003A45RL #Pause window
%patch $456B  $00003A45RL #Loading window
%patch $5920  $00003A45RL #1st ending window
%patch $595F  $00003A45RL #2nd ending window
%patch $5999  $00003A45RL #3rd ending window
%patch $59FC  $00003A45RL #Didn't make it past window
%patch $5DAD  $00003A45RL #Unknown loading window
%patch $6A68  $00003A45RL #Can't defeat window
%patch $C576  $00003A45RL #Level entry window
%patch $12036 $00003A45RL #(R)etry window

Keen Dreams 3rd window border type patch

#Ignore low memory (Frees $3A45-$3AB8)
%patch $3A43 $EB $74

#Default window values
%patch $23C3B [$0000W $0006W $0001W $0007W $0002W $0008W $0003W $0005W]

#Text windows call default variables
%patch $13B51 $A1 {$01CDW} #Bottom left corner of box
%patch $13B70 $A1 {$01CFW} #Top of box
%patch $13B7E $A1 {$01D1W} #Bottom of box
%patch $13BA1 $A1 {$01D3W} #Top right corner of box
%patch $13BAF $A1 {$01D5W} #Bottom right corner of box
%patch $13BCB $A1 {$01D7W} #Left side of box
%patch $13BDB $A1 {$01D9W} #Right side of box
%patch $13B42 $A1 {$01CBW} #Top left corner of box
              $50 $57 $FF $76 $FE $9A $0CA5094BRL     $44 $44
%patch $13B65 $0A

#Window border alteration code =$0CA5019BRL
%patch $CBEB $55 $8B $EC $56 $57 $8B $76 $06 $8B $7E $08 $9A $0CA501CERL
             $57 $56 $B8 $0019W  $2B $C7 $D1 $E8 $50 $B8 $0028W  $2B $C6 $D1 $E8 $50
             $9A $11FA1B27RL     $83 $C4 $08 $9A $0CA501CERL     $5F $5E $5D $CB
%patch $CC1E $55 $8B $EC $83 $36 {$01CBW}  [$14] $83 $36 {$01CDW}  [$14] $83 $36 {$01CFW}
                 [$14] $83 $36 {$01D1W}  [$14] $83 $36 {$01D3W}  [$14] $83 $36 {$01D5W}
             [$14] $83 $36 {$01D7W}  [$14] $83 $36 {$01D9W}  [$14] $5D $CB

#Make windows use new border:
%patch $37D2  $0CA5019BRL #F10-G cheat window
%patch $381B  $0CA5019BRL #F10-I cheat window
%patch $386A  $0CA5019BRL #F10-J cheat window
%patch $38C9  $0CA5019BRL #F10-S cheat window
%patch $3919  $0CA5019BRL #F10-W cheat window
%patch $3CA8  $0CA5019BRL #Game over window
%patch $3CD8  $0CA5019BRL #Status window
%patch $4521  $0CA5019BRL #Pause window
%patch $456B  $0CA5019BRL #Loading window
%patch $5920  $0CA5019BRL #1st ending window
%patch $595F  $0CA5019BRL #2nd ending window
%patch $5999  $0CA5019BRL #3rd ending window
%patch $59FC  $0CA5019BRL #Didn't make it past window
%patch $5DAD  $0CA5019BRL #Unknown loading window
%patch $6A68  $0CA5019BRL #Can't defeat window
%patch $C576  $0CA5019BRL #Level entry window
%patch $12036 $0CA5019BRL #(R)etry window