Patch:EGAGRAPH
EGAGRAPH.CKx is the file that contains all of the graphics in Keen Galaxy. The file is external and can be modified with two programs, ModKeen and keengraph. There are two other related files, EGAHEAD.CKx and EGADICT.CKx. In order to use altered graphics, one or both of these files must be patched.
EGAHEAD.CKx is the graphics 'header'; it is basically a list of locations of various graphics in the EGAGRAPH.CKx. EGADICT.CKx is the 'huffman dictionary' used to compress the graphics. The EGAGRAPH.CKx itself consists of a number of graphics 'blocks' or chunks; the game refers to all graphics by their chunk number. (Confusingly Modkeen does not number things by chunk number.)
Keen Dreams uses a different name for its graphics file.
File names
The EGAHEAD.CKx and EGADICT.CKx files are internal and thus can be called anything, but the EGAGRAPH.CKx file's name can be patched. The file name is read once to open the file and read graphics from it. Keen 4 and 5 also check the existence of EGAGRAPH.CKx. (See below.)
EGAGRAPH file name
#Keen 4 :
%patch $131C3 [$3ABBW] #Text called from
%patch $3292B "EGAGRAPH.CK4" $00
#Keen 5 :
%patch $14160 [$3211W] #Text called from
%patch $33551 "EGAGRAPH.CK5" $00
#Keen 6 :
%patch $12CF4 [$34BBW] #Text called from
%patch $341EB "EGAGRAPH.CK6" $00
#Keen Dreams
%patch $B7DD [$2809W] #Text called from
%patch $26279 "KDREAMS.EGA" $00
Patching new graphics
As mentioned above,using new graphics requires that the EGAHEAD.CKx and maybe EGADICT.CKx need to be patched (depending on whether Modkeen or Keengraph is being used, see their respective pages for details.) The patches used rely on a special command in CKPatch.
Patch new graphics
#Keen 4
%egahead EGAHEAD.CK4
%egadict EGADICT.CK4
#Keen 5
%egahead EGAHEAD.CK5
%egadict EGADICT.CK5
#Keen 6
%egahead EGAHEAD.CK6
%egadict EGADICT.CK6
#Keen Dreams
%egahead EGAHEAD.CK7
%egadict EGADICT.CK7
Don't scramble EGA dictionary
This patch prevents the graphics dictionary being 'scrambled' which occurs when the game runs. This patch can only be used if the graphics file is not compressed , otherwise the game will crash. This is useful since it frees up 1Kb of data segment space for patches and text.
This patch can also be used with an identical one for the AUDIODCT; this will increase the freed space to 2KB and also free up code space. ($12CE3-$12D2B in Keen 4, $13C80-$13CC8 in Keen 5 and $12814-$1285C in Keen 6).
Don't scramble EGADICT
#Don't scramble EGADICT -Keen 4
%patch $131B7 $90 $90 $90 $90
#Don't scramble EGADICT -Keen 5
%patch $14154 $90 $90 $90 $90
#Don't scramble EGADICT -Keen 6
%patch $12CE8 $90 $90 $90 $90
EGAGRAPH file check
In Keen 4 the game contains code both to check for EGAGRAPH and if it is not found to create it from two files, EGA1.CK4 and EGA2.CK4. Keen 5 has the code but it is defective, and Keen 6 does not have this ability at all.
If this check is disabled in Keen 4\6 then almost 400 bytes of space are freed up for patches. This check is separate from the EGAGRAPH.CKx filename which is only used if this check is passed. (See above.)
Check for EGAGRAPH
#Keen 4 :
%patch $3CD4 [$0112W] #Check for this file (EGAGRAPH) if not found...
%patch $3CF7 [$011FW] #Combining text
%patch $3D03 [$015DW] #Prepare to write data to this file (EGAGRAPH)
%patch $3D07 [$0154W] #Check for this file (EGA1)
%patch $3D18 [$016AW] #Can't rename file
%patch $3D34 [$0181W] #Rename EGA1 data to this (EGAGRAPH)
%patch $3D47 [$018EW] #Can't open EGAGRAPH to dump data
%patch $3D74 [$01A7W] #Check for this file (EGA2)
%patch $3D87 [$01B0W] #Can't find EGA2
%patch $3E6A [$01C5W] #Rename this file (EGA2)
%patch $2EF82 "EGAGRAPH.CK4" $00 #Check for this file
%patch $2EF8F "Combining EGA1.CK4 and EGA2.CK4 into EGAGRAPH.CK4..." $00
%patch $2EFCD "EGAGRAPH.CK4" $00 #Create this file
%patch $2EFC4 "EGA1.CK4" $00 #Check, read from this file...
%patch $2EFDA "Can't rename EGA1.CK4!" $00
%patch $2EFF1 "EGAGRAPH.CK4" $00 #...rename to this file
%patch $2EFFE "Can't open EGAGRAPH.CK4!" $00
%patch $2F017 "EGA2.CK4" $00 #Check, read from this file...
%patch $2F020 "Can't find EGA2.CK4!" $00
%patch $2F035 "EGA2.CK4" $00 #Rename this file?
#Keen 5 :
%patch $3CCE [$00E5W] #Check for this file (EGAGRAPH) if not found...
%patch $3CF1 [$00F2W] #Combining text
%patch $3D01 [$0127W] #Check for this file (EGA1)
%patch $3D12 [$0130W] #Can't rename file
%patch $3D41 [$0147W] #Can't open EGAGRAPH to dump data
%patch $3D6E [$0160W] #Check for this file (EGA2)
%patch $3D81 [$0169W] #Can't find EGA2
%patch $30425 "EGAGRAPH.CK5" $00 #Check for this file
%patch $30432 "Combining EGA1.CK5 and EGA2.CK5 into EGAGRAPH.CK5..." $00
%patch $30467 "EGA1.CK5" $00 #Check, read from this file...
%patch $30470 "Can't rename EGA1.CK5!" $00
%patch $30487 "Can't open EGAGRAPH.CK5!" $00
%patch $304A0 "EGA2.CK5" $00 #Check, read from this file...
%patch $304A9 "Can't find EGA2.CK5!" $00
Disable file check for patch space
This patch disables the EGAGRAPH file check when the game boots up. Since EGAGRAPH should always be present this check should be redundant. (It is absent in Keen 5.) It creates 389 bytes of free space.
Disable EGAGRAPH check
#Disable EGAGRAPH check in Keen 4 (Frees 389 bytes at $3CF6)
%patch $3CE5 $90 $90
#Disable EGAGRAPH check in Keen 5 (Frees 389 bytes at $3CF0)
%patch $3CDF $90 $90
Number of each graphic type
It is possible to alter the number of each of the different types of graphic (Converting, say, unmasked 16x16 tiles into masked 16x16 tiles.) This is best done before a project is started as it will drastically alter things such as the levels when implemented. The main way graphics chunks are differentiated and limited is the graphics decompression code. The first set of patches in this section deals with this code and a brief explanation of the patches on a kind-by-kind basis is as follows:
Masked and unmasked bitmaps: These are defined by the first sprite chunk; any graphic less than this is a bitmap of some kind. It is not currently known how masked and unmasked bitmaps are differentiated.
Sprites: Sprites are defined by one value giving the first chunk that is treated like a sprite and another that is the 8x8 unmasked chunk. The difference between these two values gives the total number of sprite chunks. Note that there are two matching entries for the 8x8 unmasked value for reasons.
Unmasked 8x8 tiles: Unmasked 8x8 tiles are defined by three sets of values. The first is the chunk used for the tiles. The second is the first 'non-8x8-unmasked' chunk which is the previous value plus one. It is the the masked 8x8 tiles chunk value. The third is the memory set aside for the tiles; each tile requires 32 or $20 bytes of memory, so this value divided by 32 gives the number of tiles the game can display. This is not the same as the number of tiles there actually are, it is usually slightly higher, possibly as a buffer of some sort. (In Keen 4 for example 4 extra tiles worth of memory is set aside.)
Unmasked 8x8 tiles: These are treated very similarly to the unmasked 8x8 tiles. They are defined by a value for the chunk they use and a value for the first 16x16 background tile, which is the first value plus one. They too have a value that gives how much memory is set aside. Masked tiles require 40 or $28 bytes of memory. The game usually sets aside massively more memory than is required, usually twice as much, again possibly as a buffer.
Unmasked 16x16 tiles: 'Background tiles' are defined by a value giving the first chunk that will be treated like a background tile as well as another value defining the fist chunk to be a foreground tile. The difference between these two values gives the total number of background tiles. The first value is also defined elsewhere in the code as mentioned below. 16x16 tiles have a memory value like 8x8 tiles but this is just the size of the individual tile and shouldn't be patched.
Masked 16x16 tiles: 'Foreground tiles' are defined by a value giving the first non-background chunk as well as several values that give the first 'non-tile' chunk. The difference between these values is the number of foreground tiles.
Misc: All remaining graphics are 'miscellaneous.' These include the first and last few graphics chunks. As such these are defined solely elsewhere in the code, often on a chunk-by-chunk basis.
Other chunk definitions: 16x16 tiles are also defined in the 'display level' code. There are two values for both masked and unmasked tiles, one for animating tiles and one for non-animating. The two values for each tile type should match and also match those in the graphics decompression code.
Things like the story texts or B800 screens are defined individually with each chunk having a single purpose and being capable of being placed anywhere in the EGAHEAD. The only exceptions are the demos; like tiles only a first value is given.
Note that Keen Dreams handles things slightly differently due to being an alpha of the Galaxy engine.
Keen 4
#What different graphics chunks are loaded as
%patch $139F9 [$7C] #First sprite chunk
%patch $13971 [$0209W] #Unmasked 8x8 Tiles chunk 1
%patch $139FE [$0209W] #Unmasked 8x8 Tiles chunk 2
%patch $13989 [$0D80W] #Number of unmasked 8x8 tiles (108)
%patch $1397D [$020AW] #Masked 8x8 Tiles
%patch $1399B [$05A0W] #Number of masked 8x8 tiles (36)
%patch $1398F [$020BW] #First unmasked 16x16 chunk
%patch $139A1 [$071BW] #First masked 16x16 chunk
%patch $13977 [$127FW] #First non tile chunk 1
%patch $139B3 [$127FW] #First non tile chunk 2
%patch $139C5 [$127FW] #First non tile chunk 3
#First tile chunks used when displaying levels
%patch $168D1 [$020BW] #Unmasked 16x16 tiles (Unanimated)
%patch $169D7 [$020BW] #Unmasked 16x16 tiles (Animated)
%patch $16A99 [$071BW] #Masked 16x16 tiles (Unanimated)
%patch $16BA8 [$071BW] #Masked 16x16 tiles (Animated)
#Demo chunks start
%patch $5913 [$128BW]
#B800 screens
%patch $3A13 [$127FW] #Exiting game
%patch $3B4C [$1282W] #Not enough memory
#'Terminator text' chunks
%patch $4EE8 [$1281W] #COMMANDER
%patch $4EF4 [$1280W] #KEEN
#Help section documents
%patch $2F586 [$1283W] #Computerwrist
[$1285W] #Controlling Keen
[$1284W] #Story
[$1289W] #Hints and tips
[$1286W] #Order
#Ending sequence document
%patch $9CB8 [$1287W]
Keen 5
#What different graphics chunks are loaded as
%patch $14996 [$66] #First sprite chunk
%patch $1490E [$01C0W] #Unmasked 8x8 Tiles chunk 1
%patch $1499B [$01C0W] #Unmasked 8x8 Tiles chunk 2
%patch $14926 [$0D80W] #Number of unmasked 8x8 tiles (108)
%patch $1491A [$01C1W] #Masked 8x8 Tiles
%patch $14938 [$05A0W] #Number of masked 8x8 tiles (36)
%patch $1492C [$01C2W] #First unmasked 16x16 chunk
%patch $1493E [$07AAW] #First masked 16x16 chunk
%patch $14914 [$1332W] #First non tile chunk 1
%patch $14950 [$1332W] #First non tile chunk 2
%patch $14962 [$1332W] #First non tile chunk 3
#First tile chunks used when displaying levels
%patch $1786E [$01C2W] #Unmasked 16x16 tiles (Unanimated)
%patch $17974 [$01C2W] #Unmasked 16x16 tiles (Animated)
%patch $17A36 [$07AAW] #Masked 16x16 tiles (Unanimated)
%patch $17B45 [$07AAW] #Masked 16x16 tiles (Animated)
#Values for purging chunks from memory
%patch $5C1F [$0066W] #First sprite chunk
%patch $5C45 [$01C0W] #Last sprite chunk
%patch $5C4A [$01C2W] #Last 8x8 tile chunk
%patch $5C70 [$1332W] #Last 16x16 tile chunk
#Window tiles locked in at game start
%patch $393B [$01C0W] #8x8 unmasked
%patch $3942 [$01C1W] #8x8 masked
Keen 6
#What different graphics chunks are loaded as
%patch $1352A [$2E] #First sprite chunk
%patch $134A2 [$01B4W] #Unmasked 8x8 Tiles chunk 1
%patch $1352F [$01B4W] #Unmasked 8x8 Tiles chunk 2
%patch $134BA [$0D80W] #Number of unmasked 8x8 tiles (108)
%patch $134AE [$01B5W] #Masked 8x8 Tiles
%patch $134CC [$05A0W] #Number of masked 8x8 tiles (36)
%patch $134C0 [$01B6W] #First unmasked 16x16 chunk
%patch $134D2 [$0AFEW] #First masked 16x16 chunk
%patch $134A8 [$15AEW] #First non tile chunk 1
%patch $134E4 [$15AEW] #First non tile chunk 2
%patch $134F6 [$15AEW] #First non tile chunk 3
#First tile chunks used when displaying levels
%patch $16440 [$01B6W] #Unmasked 16x16 tiles (Unanimated)
%patch $16599 [$01B6W] #Unmasked 16x16 tiles (Animated)
%patch $1665E [$0AFEW] #Masked 16x16 tiles (Unanimated)
%patch $167C5 [$0AFEW] #Masked 16x16 tiles (Animated)
Keen Dreams
#What different graphics chunks are loaded as
%patch $BF98 [$47] #First sprite chunk
%patch $BF18 [$0170W] #Unmasked 8x8 Tiles chunk 1
%patch $BF9D [$0170W] #Unmasked 8x8 Tiles chunk 2
%patch $BF2A [$0900W] #Number of unmasked 8x8 tiles (108)
%patch $BF1E [$0171W] #Masked 8x8 Tiles
%patch $BF3C [$05A0W] #Number of masked 8x8 tiles (36)
%patch $BF30 [$0172W] #First unmasked 16x16 chunk 1
%patch $BF42 [$0712W] #First masked 16x16 chunk
%patch $BF54 [$0BC8W] #First non tile chunk 1
%patch $BF66 [$0BC8W] #First non tile chunk 2
#Maximum size of EGAHEAD
%patch $C510 [$0BC8W] #Errorcheck 1?
%patch $C517 [$0BC8W] #Errorcheck 2?
%patch $C5FE [$0BC8W] #Caching 1?
%patch $C88B [$0BC8W] #Caching 2?
%patch $C8A5 [$0BC8W] #Max chunks when loading level
%patch $C931 [$0BC8W] #Loading 1
%patch $C935 [$0BC8W] #Loading 2
%patch $CA0F [$0BC8W] #Cacheable chunks (Size of cache pointer list)