Background Graphics
Each cell of the dungeon can have its own 'Skin'. A 'Skin' consists of zero to four graphics assocated with the 'Floor', 'Middle', 'Ceiling', and 'Walls' and four masks which describe what part of the graphics are to be displayed and where.. The Skin number for each Cell is stored in the dungeon file. The definition of each Skin (the IDs of the four graphics and four masks) is contained in the CSBgraphics.dat file. The graphics themselves are also stored in the CSBGraphics.dat file. And, finally, the graphic 'masks' are also stored in CSBGraphics.dat.. All the graphics associated with backgrounds (including masks and skin definitions) are stored as a single 'Graphic Type' identified as 'Background Graphics' when using CSBGraphics.exe.
The dungeon can contain up to 255 'Skins'. There can be up to 65535 graphics and masksfor the floors, middle, ceiling, and walls combined. Each of the Floor, Middle, and Ceiling graphics is a single graphic that is (in the simplest case) the size of the entire area. For the Floor and Ceiling graphics there are 16 separate 'Masks' that define what part of the graphic is to be displayed for each of the 16 cells that can be seen by the party and where in the viewport area it is to be displayed. There are only 5 'Masks' for the 'Middle' area as only 5 cells can be seen at the distance where the 'Middle' graphic is displayed. The cells are numbered from 0 to 15 starting at the farthest visible cell to the far left and working to the right and closer. Here is a diagram with the party looking north (P = party):
--------------------------
| 0 | 2 | 4 | 3 | 1 |
| | | | | |
--------------------------
| 5 | 7 | 9 | 8 | 6 |
| | | | | |
--------------------------
| 10 | 12 | 11 |
| | | |
----------------
| 13 | 15 | 14 |
| | P | |
----------------
The definition of the skins is stored as 'Background Graphic' with ID = 1.. Each skin is defined by eight 16-bit values. Very simple. Skin 0 existes in the definitions but is never used because Skin 0 means to use no custom background. Skin 1 follows, then Skin 2, etc, each occupying 16 bytes. The first four 16-bit values represent the Floor Graphic ID, the Middle graphic ID, the Ceiling graphic ID, and the Wall graphic ID associated with that skin. The second four 16-bit values identify the mask to be used for Floor, Middle, Ceiling, and Walls. If any of the graphic IDs (or mask ID) is zero then no custom graphic is used for the corresponding portion of the viewport.
The graphics themselves (other than the skin definition) can have any ID you choose although it is wasteful to use very large graphic numbers because it causes memory to be wasted at runtime.
The graphics and the masks are in the Atari 'Bit-Plane' format in which four 16-bit words are used to represent 16 pixels. The first of the four words contains the least significant bit of each of the 16 pixels. The second 16-bit word contains the next least significant bits, etc. The most significant bit in each of the four words provide the four bits for the first pixel, etc. In this way the four words define 16 pixels. The mask need only contain one word for the 16 pixels because the masks for each of the four words are identical and can be constructed at runtime by replicating just one word. So, in the mask graphic 16 pixels are represented by one 16-bit word and in the 'picture' graphic 16 pixels are represented by four words.
The Mask graphic has the following format:
struct index
{
i32 maskOffset[16] // [5] for the middle graphic
};
maskOffset is the byte offset within the file of the start of the 16 masks for the 16 cells. If any of these is zero then that corresponding cell will not be drawn. Each mask (pointed at by the index entry) is of the following format:
struct maskEntry
{
i32 sourceX;
i32 sourceY;
i32 destinationX;
i32 dstinationY;
i32 width;
i32 height;
i16 pixels[width*height/16];
};
The 'sourceX', 'sourceY', 'destinationWidth', 'destinationHeight', 'width' and 'height' are all in units of one pixel. Therefore, 'sourceX', 'destinationX', and 'width' must be multiples of 16; 'destinationX' and 'destinationY' are relative to the top left of the viewport. As a result of this, you can draw floor graphics on the ceiling or anywhere else in the vieport that you choose. Moreover, the graphics can be any size. So if you want to draw trees or columns you can do so. Moreover, the graphics are drawn from cell 0 to cell 15 so that the most distant are drawn first, allowing nearer objects to overlay farther objects.
The 'picture' graphic has the following format:
struct picture
{
i32 width; //In units of pixels. Multiple of 16;
i16 pixels[#pixels in graphic/4]
};