Eye of the Beholder DAT File Format
This document describes the decoration rectangle data files (.dat) that are bundled with each decoration image file.
In EOB2 they have the filename extension .dec
All unsigned short are big endian! They are little endian in the PC version.
File Format
struct Decoration
{
unsigned short nbrDecorations;
struct Decoration decorations[nbrDecorations]; /* Indexed into by the WallMapping in the [[eob.inf|.inf]] file. */
unsigned short nbrDecorationRectangles;
struct DecorationRectangle rectangles[nbrDecorationRectangles];
};
Sub structures
struct Decoration
{
unsigned char rectangleIndices[10]; /* indices into DecorationData.rectangles */
unsigned char linkToNextDecoration; /* index into DecorationData.decorations */
unsigned char flags;
unsigned short xCoords[10]; /* coordinate in the game view, where to render the overlay */
unsigned short yCoords[10];
};
If rectangle index is 0xFF, there isn't a decoration for that view position.
Each of these 10 indices in the arrays corresponds to the 10 possible overlay graphics positions in the viewport.
TODO: Describe linkToNextDecoration, flags and the coordinate system. (JackAsser will fix this)
struct DecorationRectangle
{
unsigned short x; /* Multiply by 8 to get actual screen coord */
unsigned short y;
unsigned short w; /* Multiply by 8 to get actual width */
unsigned short h;
};
Each rectangle describes an area in the .cps graphics file stated by the 0xec command code in the .inf file.
Drawing a decoration + Pseudocode(EOB2)
(what about EOB1?)
decoration wall positions (0..9):
9 7 3 7 9
8 6 2 6 8
8 5 1 5 8
4 0 4
^=party pos.
The following table contains drawing information for each view position:
xflip: for side walls: 0=left, 1=right
wall: decoration position number, -1=none available for this position
xdelta: horizontal shift (decoration on wall only) in render window for this wall position (multiply with 8)
CDecPos: array [0 .. 25] of TPos = (
(XFlip: 0; Wall: -1; XDelta: 0),
(XFlip: 0; Wall: 9; XDelta: 0),
(XFlip: 0; Wall: 7; XDelta: 0),
(XFlip: 1; Wall: 7; XDelta: 0),
(XFlip: 1; Wall: 9; XDelta: 0),
(XFlip: 0; Wall: -1; XDelta: 0),
(XFlip: 0; Wall: 3; XDelta: -12),
(XFlip: 0; Wall: 3; XDelta: -6),
(XFlip: 0; Wall: 3; XDelta: 12),
(XFlip: 0; Wall: 3; XDelta: 6),
(XFlip: 0; Wall: 3; XDelta: 0), //middle front wall
(XFlip: 0; Wall: 8; XDelta: 0),
(XFlip: 0; Wall: 6; XDelta: 0),
(XFlip: 1; Wall: 6; XDelta: 0),
(XFlip: 1; Wall: 8; XDelta: 0),
(XFlip: 0; Wall: 2; XDelta: -10),
(XFlip: 0; Wall: 2; XDelta: 10),
(XFlip: 0; Wall: 2; XDelta: 0), //middle front wall
(XFlip: 0; Wall: 5; XDelta: 0),
(XFlip: 1; Wall: 5; XDelta: 0),
(XFlip: 0; Wall: 1; XDelta: -16),
(XFlip: 0; Wall: 1; XDelta: 16),
(XFlip: 0; Wall: 1; XDelta: 0), //middle front wall
(XFlip: 0; Wall: 4; XDelta: 0),
(XFlip: 1; Wall: 4; XDelta: 0),
(XFlip: 0; Wall: 0; XDelta: 0)
);
Decorations can consist of more than one rectangle, which are drawn together.
They are given as a list:
procedure DrawCompleteDecoration(GFXIndex, DecNumber, Position:longint; isAtWall:boolean);
begin
repeat
DrawDecorationPart(GFXIndex, DecNumber, Position, isAtWall); // draw a part of the decoration
DecNumber:= Decoration[DecNumber].NextDecoration; // go to next part
until DecNumber = 0;
end;
GFXIndex points to the data file where the decoration resides: for example mezz2.cps
DecNumber is the number of the Decoration.
Position (range 0..25) is the wall position (side and front walls).
isAtWall tells if the decoration is at a wall, this is true if the walltype in the
decoration mapping definition in the .inf file is unequal zero.
procedure DrawDecorationPart(GFXIndex, DecNumber, Position:longint; isAtWall:boolean);
var
i,j, //pos in cps graphics
s,t:longint; //pos on screen
q:byte;
dx,pos : longint;
mirrored : boolean;
begin
//get the horizontal shift for the decoration according to its position.
//if the decoration is drawn at a wall, we use the table above.
//otherwise the decoration is placed in the middle of a field,
// for example a pit or pressure plate...
dx := 0;
if isAtWall then
dx := 8*CDecPos[Position].XDelta
else
case Position of
6 : dx := -88;
7 : dx := -40;
8 : dx := 88;
9 : dx := 40;
15 : dx := -59;
16 : dx := 59;
20 : dx := -98;
21 : dx := 98;
end;
//translate view positions (0..25) to decoration view position (0..9)
pos := CDecPos[Position].Wall;
if pos >= 0 then
begin
//get the number of the decoration rectangle for the corresponding view position
q := Decoration[DecNumber].RectangleIndices[pos];
//if rectangle index is $FF, then there doesn't exist a decoration for this view position
if q <> $FF then
begin
//Bit 0 in Flags: for front walls (and not for side walls):
// for example, a decoration consists of two parts,
// and the second part is the first one, but mirrored..
mirrored := false;
case Position of
6..10, 15..17, 20..22, 25: mirrored := boolean(Decoration[DecNumber].Flags and $01);
end;
t:= Decoration[DecNumber].YCoords[pos];
for j:= Rectangles[q].y to Rectangles[q].y+Rectangles[q].Height-1 do
begin
if mirrored then
s := 22*8 - Decoration[DecNumber].XCoords[pos] - 1
else
s := Decoration[DecNumber].XCoords[pos];
for i := Rectangles[q].x*8 to Rectangles[q].x*8+Rectangles[q].Width*8-1 do
begin
if mirrored then
begin
PutPixel(s+dx, t, Graphics[GFXIndex][320*j + i]);
Dec(s);
end else
begin
if CDecPos[Position].XFlip = 0 then
PutPixel(s+dx, t, Graphics[GFXIndex][320*j + i]) //left side walls; front walls
else
PutPixel(22*8-(s+dx), t, Graphics[GFXIndex][320*j + i]); //right side walls only
Inc(s);
end;
end; //for i
Inc(t);
end; //for j
end; // q<>$FF
end; //pos>0
end;
Discussions
inigomartinez
PC EOB1/2
inigomartinez 08 November 2009 12:19:42
Looks like Neither EOB1 and EOB2 seems to have the unsigned short values in Big Endian. Is this annotation about the Amiga version ?
JackAsser
JackAsser 08 November 2009 15:51:06
Yes. The PC version is little-endian afaik.
inigomartinez
flags field
inigomartinez 06 September 2010 17:21:24
Looking below, I have seen that the first bit of the flags does mean that the decoration should be mirrored.
I have been checking more files and I have seen that the third bit is used sometimes too. Any idea about its meaning ? Is any other bit used.
inigomartinez
inigomartinez 20 September 2010 07:32:43
As a side note, I have noticed that the decorations with this bit active are mainly, floor and ceil decorations like holes and similar.
In my tests they look correct without doing anything special. Maybe, they have something to do with scripts data.
inigomartinez
No decoration ID
inigomartinez 09 September 2010 14:06:55
Looking to INF files, I have seen that some wall mapping commands have a decoration id of 0xFF.
Knowing that 0xFF is used to suggest that no rectangle exist for a given position, shouldn't 0xFF mean no decoration too ?
Could anyone confirm this ?
PS: Is anyone still around ?
badut
badut 09 September 2010 23:27:23
I'm still around. But sorry I can not answer your question.
My EOB project is hibernating at the moment but I hope to find time to awaken it soon ;)