Roo file specification

From Meridian 59 - Open Source Wiki
Jump to: navigation, search

A room file contains the BSP tree for a single room. The file can be encrypted to prevent tampering; the client can load both encrypted and unencrypted versions. Building the BSP tree splits walls into smaller pieces. However, these splits should not appear when the room is later loaded back into the editor. Thus, we store the original walls (before the creation of the BSP tree) in the file separately. The editor loads the original walls and ignores the BSP tree, while the client loads the BSP tree but ignores the original walls.

The editor builds the “server section” of the file so that the server can have some basic knowledge of the room’s geometry. Neither the client nor the editor loads this section.

4 bytes magic number = 52 4F 4F B1 (hexadecimal)
4 bytes version = 11
4 bytes <security>
4 bytes offset of <main info>
4 bytes offset of <server info>

<main info>
<server info>

<main info> =
<size>
<data>

<size> =
4 bytes width of room (in client units)
4 bytes height of room (in client units)
If the width of the room is -1, then the <data> section is encrypted.
In this case, these bytes appear here:
4 bytes length of <data>
4 bytes response to challenge of room security check (used in decryption)
and the <data> section is encrypted by the hexadecimal password x15x20x53x01xFCxAAx64.

<data> =
4 bytes offset of <node subsection>
4 bytes offset of <client wall subsection>
4 bytes offset of <roomedit wall subsection>
4 bytes offset of <sidedef subsection>
4 bytes offset of <sector subsection>
4 bytes offset of <thing subsection>

<node subsection> =
2 bytes number of <BSPnode>s
<BSP node>∗ nodes of BSP tree; root must appear first

<client wall subsection> =
2 bytes number of <client wall>s
<client wall>∗

<roomedit wall subsection> =
2 bytes number of <roomedit wall>s
<roomedit wall>∗

<sidedef subsection> =
2 bytes number of <sidedef>s
<sidedef>∗

<sector subsection> =
2 bytes number of <sector>s
<sector>∗

<thing subsection> =
2 bytes number of <thing>s
<thing>∗

<BSP node> =
1 byte node type
1 internal node
2 leaf node
<box> bounding box of node
<internal node> or <leaf node>

<internal node> =
<line> equation of a line that splits the BSP tree
<node id> BSP node number of + subtree (0 if none, 1 = first wall in file)
<node id> BSP node number of - right subtree (0 if none, 1 = first wall in file)
2 bytes wall number of first wall in this plane (starts at 1 = first wall in file; 0 if none)

<leaf node> =
2 bytes sector number corresponding to this node (1 = first sector in file)
2 bytes number of points in polygon defining leaf node
<point>∗ points of polygon defining leaf node (clockwise order as seen from above)

<client wall> =
2 bytes next wall in list of walls in plane (0 if none)
2 bytes sidedef on + side of wall (0 = none, 1 = first sidedef in file)
2 bytes sidedef on - side of wall (0 = none, 1 = first sidedef in file)
<point> coordinates of start of wall
<point> coordinates of end of wall (positive side is on right going start to end)
2 bytes length of wall (units: 1 server coordinate unit = length 64)
2 bytes texture x offset on positive side (in pixels)
2 bytes texture x offset on negative side (in pixels)
2 bytes texture y offset on positive side (in pixels)
2 bytes texture y offset on negative side (in pixels)
2 bytes sector number on + side of wall (0 = none, 1 = first sector in file)
2 bytes sector number on - side of wall (0 = none, 1 = first sector in file)

<line> =
4 bytes A in line equation Ax + By + C = 0
4 bytes B in line equation Ax + By + C = 0
4 bytes C in line equation Ax + By + C = 0

<box> =
point coordinates of NW corner of bounding box
point coordinates of SE corner of bounding box

<point> =
4 bytes x coordinate
4 bytes y coordinate

<node id> =
2 bytes

<sidedef> =
2 bytes user-defined id (used for referencing from server)
2 bytes bitmap number of normal bitmap
2 bytes bitmap number of above bitmap
2 bytes bitmap number of below bitmap
<wall flags> various characteristics of the wall
1 byte animation speed of bitmap on wall, in tenths of a frame per second

<sector> =
2 bytes user-defined id (used for referencing from sector)
2 bytes bitmap number of floor bitmap
2 bytes bitmap number of ceiling bitmap
2 bytes x coordinate of origin of floor and ceiling textures (in pixels)
2 bytes y coordinate of origin of floor and ceiling textures (in pixels)
2 bytes floor height (units: size of one server coordinate = 64)
2 bytes ceiling height (units: size of one server coordinate = 64)
<light level> light level in sector
<sector flags> various characteristics of the sector
1 byte animation speed of bitmaps in sector, in tenths of a frame per second
if <sector flags> indicates a sloped floor, then
<slope info> info on sloped floor
if <sector flags> indicates a sloped ceiling, then
<slope info> info on sloped ceiling

<light level> =
1 byte
    0-127 sector not affected by ambient light; 0 = darkest, 127 = brightest
    128-255 sector affected by ambient light; 128 = darkest, 255 = brightest, 192 = neutral

<roomedit wall> =
2 bytes sidedef on + side of wall (0 = none, 1 = first sidedef in file)
2 bytes sidedef on - side of wall (0 = none, 1 = first sidedef in file)
2 bytes texture x offset on positive side (in pixels)
2 bytes texture x offset on negative side (in pixels)
2 bytes texture y offset on positive side (in pixels)
2 bytes texture y offset on negative side (in pixels)
2 bytes sector number on + side of wall
2 bytes sector number on - side of wall
<point> coordinates of start of wall

<point> coordinates of end of wall (positive side is on right going start to end)

<thing> =
<point> location of thing

<wall flags> =
4 bytes
    bit 0 1 if bitmaps on wall should be drawn backwards (left-right reversed)
    bit 1 1 if normal wall has some transparency
    bit 2 1 if objects can pass through wall
    bit 3 1 if wall should never be shown on map
    bit 4 1 if wall should always be shown on map
    bit 5 1 if wall is transparent, but there’s nothing behind it
    bit 6 1 if upper wall should be drawn bottom up (default is top down)
    bit 7 1 if lower wall should be drawn top down (default is bottom up)
    bit 8 1 if normal wall should be drawn top down (default is bottom up)
    bit 9 1 if wall shouldn’t tile vertically (must also be transparent)
    bits 10-11 texture scrolling speed, 0 = none, ... 3 = fast
    bits 12-14 texture scrolling direction (used only if scroll speed nonzero)
               0 = N, 1 = NE, ... 7 = NW

<sector flags> =
4 bytes
    bits 0 and 1 “depth” of sector (for wading effects)
    0 = no depth, 1 = shallow, 2 = deep, 3 = very deep
    bits 2-3 texture scrolling speed, 0 = none, ... 3 = fast
    bits 4-6 texture scrolling direction (used only if scroll speed nonzero)
    0 = N, 1 = NE, ... 7 = NW
    bit 7 1 if floor texture should be scrolled
    bit 8 1 if ceiling texture should be scrolled
    bit 9 1 if light in sector should flicker
    bit 10 1 if sector has a sloped floor
    bit 11 1 if sector has a sloped ceiling

<slope info> =
4 bytes a coefficient in plane equation ax + by + cz + d = 0
4 bytes b coefficient in plane equation ax + by + cz + d = 0
4 bytes c coefficient in plane equation ax + by + cz + d = 0
4 bytes d coefficient in plane equation ax + by + cz + d = 0
<point> texture origin
<angle> direction of positive u axis (for texture orientation)
2 bytes vertex number of user-specified sector vertex #1 (used in editor)
2 bytes z coordinate of vertex #1 (in room editor units)
2 bytes vertex number of user-specified sector vertex #2 (used in editor)
2 bytes z coordinate of vertex #2 (in room editor units)
2 bytes vertex number of user-specified sector vertex #3 (used in editor)
2 bytes z coordinate of vertex #3 (in room editor units)

<server info> =
4 bytes number of grid rows (= r)
4 bytes number of grid cols (= c)
<move grid> inter-square movement grid
<flag grid> server square flags

<move grid> =
r ∗ c bytes one byte for each square in the room, row major order:
    bit 0 1 if possible to move to adjacent square to N
    bit 1 1 if possible to move to adjacent square to NE
    bit 2 1 if possible to move to adjacent square to E
    bit 3 1 if possible to move to adjacent square to SE
    bit 4 1 if possible to move to adjacent square to S
    bit 5 1 if possible to move to adjacent square to SW
    bit 6 1 if possible to move to adjacent square to W
    bit 7 1 if possible to move to adjacent square to NW

<flag grid> =
r ∗ c bytes one byte for each square in the room, row major order:
    bit 0 1 if square is entirely within playable region (i.e. a real floor covers square)

The <security> value is calculated as follows:

1) Calculate the 32 bit signed sum of the following things in the file:

file version number
for each internal node in main section:
    a,b,c coefficients of line
    wall number of first wall in plane
for each leaf node in main section:
    x and y coordinates of each point
for each client wall in client section:
    + and - sidedef numbers
    x and y coordinates of start and end of wall
    + and - sector numbers
for each sidedef in main section:
    user-defined id
    bitmap numbers of normal, above, and below walls
    wall flags value
for each sector in client section:
    user-defined id
    bitmap numbers of floor and ceiling
    floor and ceiling heights
    light level
    sector flags value
2) exclusive or with 0x89ab786c