+==========================================================================================+ |Shadow Knights graphics format: | +==========================================================================================+ This covers the files EGAHEAD, EGATILES, EGAPLANE and S_*, the header, tile, font and masked (sprite) files respectively. SK uses EGA type graphics, in which an image is stored as 4 (or 5) 'planes' of data. (4 for unmasked graphics, blue, green, red and intensity, 5 for unmasked graphics, which also has a 'masked' plane.) In each plane 8 pixels are stored per byte, (this is why graphic sizes tend to be multiples of 8 pixels wide.) giving in total an approximately 4-bit form of storage. When uncompressed the files are usually 'raw data'; much like a bitmap without a header. The egahead file tells Keen where in the files to read from, and how much. A pixel (Or rather 8 pixels) is composed by adding all the values from the four planes for each pixel. So black is 0000, and dark blue is 1000 (Light blue is 1001) etc. In summary: GRAPHICS -> 4 PLANES -> 8 PIXEL LINES -> 0\1 BITS BGRL: COLOR 0000: Black 0001: Dark grey 0010: Red 0011: Light red 0100: Green 0101: Light green 0110: Brown 0111: Light brown (Yellow) 1000: Dark blue 1001: Light blue 1010: Purple 1011: Light purple (Pink) 1100: Turqoise 1101: Light Turquoise 1110: Grey 1111: White +------------------------------------------------------------------------------------------+ |Shadow Knights Graphics Header ('EGAHEAD.NIN'): | +------------------------------------------------------------------------------------------+ This is the gaphics header, of course. An important note is that it can only retrieve data from 'rounded ($X0) addresses; this means that all pointers end in 0 ($00030, $00150...) and that any data not stored starting at a rounded address will be 'clipped' (Though the sprites have a way around this...) The graphic names are not required and do little. Many of the values in SK are zero and so can be ignored, unless you want to do something fancy with your files. Notable differences from Keen are that there are no unmasked bitmaps, and that the font and tiles are stored in seperate files. ------------------------------------------------------------------------------- EGAHEAD STRUCTURE: HEADER MASKED ENTRIES ... .. . ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- HEADER: 0 4 Egaplansiz Size of font plane, on quarter of the EGAPLANE file in bytes. 4 4 Sprplansiz Size of EGASPRIT plane; this is blank since SK doesn't have one. 8 4 Bmpdatstart Where in the EGAHEAD the entries for unmasked graphics (Excluding font and tiles.) start. Should always be byte 64. There are NO entries, oddly enough... 12 4 Sprdatstart Where in the EGAHEAD the entries for masked graphics (Sprites) start; by default this is right after the unmasked graphics, at byte 64! 16 2 Fontnum Number of 8x8 font entries in EGAPLANE, this MUST be 33 for some reason 18 4 Fontloc Offset in EGAPLANE file where font data starts. Is of course, zero. 22 2 Unknum Used for the ending screen until this was removed. Number of screen graphics. 24 4 Unkloc Used for screen graphics until removal. Offset in plane where screen data starts. 28 2 Tilenum Number of 16x16 tiles 30 4 Egaplansiz Same as value at 0 (e.g tiles after font.) 34 2 Bmpnum Number of unmasked bitmaps (Zero) 36 4 Bmploc Offset in plane where unmasked bitmap data starts, kept blank. 40 2 Spritenum Number of sprite images IN TOTAL, stuck at 180 at present 42 4 Spriteloc Offset in sprite plane of start of sprite data. Is 0 52 12 ??? Unknown, four variables and some blanks 64 128x Msk Ent Masked graphic entries of 128 bytes each. ------------------------------------------------ UNMASKED BITMAP ENTRIES: (ABSENT) ? 2 Size h The width of the graphic divided by 8 +2 2 Size v The height of the graphic in pixels; if this cannot be divided into neat 16 byte pieces, the extra data, usually 8 bytes, is added to the size. +4 4 Loc When added to the graphic offset in the header, gives the location of the start of the graphic data in the plane. For the first graphic this is thus zero. +8 8 Name Name of the graphic, padded with nuls ------------------------------------------------ ------------------------------------------------ MASKED BITMAP ENTRIES: (SPRITES) ? 2 Size h The width of the graphic divided by 8 +2 2 Size v The height of the graphic in pixels; the same rule applies as for unmasked graphics except now we have: +4 2 Loc offset Usually 8, this is the number of bytes 'extra' that must be added to the location to reach the start of the sprite dats. This appears when a sprite is so small, usually 8x8 pixels, that it doesn't fill a multiple of 16 bytes. This will affect ALL sprites after the abberation until another one occurs to fix the shortfall. +6 2 Location Multiplying this by 16 bytes gives the location of the start of the sprite data in the EGA plane. +8 4 Hitbox ul Location of the upper-left corner of the sprite's hitbox or colision rectangle, in pixels, starting from 0,0. First two bytes are the h location and the next two are the v location. Values are the actual value multiplied by 16 +12 4 Hitbox br Same as above, for the bottom left corner. +16 12 Name The sprite name, usually includes a number and is usually only 10 bytes long. +28 2 Offs h H offset of the animation from the sprite, like in Keen 4-6 Often zero. +30 2 Offs v V offset, note that offsets, like the hitbox are the value * 16 +32 3*32 Copies Keen uses these entries for smooth movement; each 32 byte entry is a copy of the inital sprite shifted 2 pixels left. Keen automatically generates these copies, but needs the size bytes (The width is always 8 pixels wider than initial.), everything else can be blank. ------------------------------------------------ ------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------+ |Unmasked Graphics (EGATILES.NIN): | +------------------------------------------------------------------------------------------+ This stores the 16x16 tiles in Dave as uncompressed raw EGA data, as for Keen 1-3 Notable however is the ega plane size; instead of the entire tileset being divided into four color planes, each TILE is instead, so the overall structure is Tile 1 blue, Tile 1 green, Tile 1 red, Tile 1 intensity, Tile 2 blue, Tile 2 green... This is because unlike Keen, where the whole tileset is loaded, in SK only the tiles used in the level are loaded, each one seperately. ------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------+ |Sprite Graphics (S_*.NIN): | +------------------------------------------------------------------------------------------+ There are a variety of sprite files, each of which contains one 'set' of sprites. These are assigned sprite numbers depending on what sprites are actually present in the level, but the ABSOLUTE value given is assigned by the game by loading the files into memory in this order: S_NINJA; S_THUG; S_ARCHER; S_BATS; S_DOGS; S_SKEL; S_DEMON and S_DRAGON. By default there are 180 sprites. Each file is of the same format, RLE-NW compressed raw EGA data as for Keen 1-3 ------------------------------------------------------------------------------- COMPRESSED: 0 4 Size Size of uncompressed file + 2. 4 ? Data RLE-NW compressed data. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- UNCOMPRESSED: 0 4 Size Decompressed File size + 2 4 2 Planesize File planesize, roughly filesize / 5 6 x Plane 1 Raw data for the BLUE plane x x Plane 2 Raw data for the GREEN plane 2x x Plane 3 Raw data for the RED plane 3x x Plane 4 Raw data for the LIGHT plane 4x x Plane 5 Raw data for the MASK plane ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- COMPRESSION: RLE-NW is like RLE-W and a slight modification of standard RLE. Whereas in normal RLE there are two types of control byte, one to say 'repeat the next character x times' and the other to say 'copy the next y characters' RLE-NW however has only one. It copies everything to output until it finds the character $FE. When it does, it copies the x + 2 character x + 1 times. A summary is as follows for decompression: 1.) Get a byte -> If at end of file, stop. 2.) Is this byte $FE (254)? -> No, then copy it to file and goto 1.) -> If yes then... -> Get the next byte, this is our COUNT -> Get the next next byte, this is our CHARACTER, now goto 3.) 3.) Copy CHARACTER to file COUNT times, then goto 1.) ------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------+ |ENDPIC.NIN | +------------------------------------------------------------------------------------------+ This is RLE-NW compressed data, like the sprites. When uncompressed it is almost identical to the Keen 1-3 FINALE files. By default the image is 640x200 ------------------------------------------------------------------------------- COMPRESSED: 0 4 Size Size of uncompressed file. 4 ? Data RLE-NW compressed data. ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- UNCOMPRESSED: 0 2 Width Width of image \ 8 2 2 Height Image height 4 x Pane 1 Raw data for the BLUE plane +x x Pane 2 Raw data for the GREEN plane +2x x Pane 3 Raw data for the RED plane +3x x Pane 4 Raw data for the INTENSITY plane -------------------------------------------------------------------------------