Field File Section 9: Background - niemasd/PyFF7 GitHub Wiki
The Background section stores the actual background. This wiki is a useful reference for the Background section. All offsets referenced in this section do not include the Section Length.
Final Fantasy VII stores its backgrounds in a rather complex format. Basically, there are three sections:
- The palette, which is basically just a list of colors
- The background sprites (or tiles), which are just references to other bits of data
- The raw image data, which is palettized grayscale data
Each background sprite represents a 16x16 pixel block on the finished background. The sprite essentially contains the following information:
- The target block, i.e., where on the background to draw this 16x16 square
- The source block, i.e., where on the raw image data to take the pixels from
- The palette page, i.e., which 256-color palette block to apply to the raw image data
This is a very efficient way to store the image. On one hand, it's in 16-bit colour, far better than just palettizing the whole image (i.e., 256 colors over the whole background). On the other hand, each 16x16 pixel block takes much less space than if you'd stored it directly in 16-bit color format. It isn't, however, easy to decode or (especially) encode.
The image source data is split up into 256x256 pixel pages; that's why, as well as a source X and Y, you also have a source page (which 256x256 block to take data from). On the other hand, the destination background is stored as one big bitmap with no limits on size, so there, you just have a target X/Y position which can be used directly.
- This is a 4-byte unsigned integer denoting the total length (in bytes) of this section
- The first 2 bytes are an unsigned integer with unknown value
- It seems to always be 0
- The next 2 bytes are an unsigned integer denoting the depth
- It seems to almost always be 1
- I did see a file (
blin67_4
) that had 2 for this value
- I did see a file (
- The next byte is an unsigned integer with unknown value
- It seems to always be 1
This Makou Ractor code might help decode the palette subsection.
- The first 7 bytes of this subsection are the string
PALETTE
- The next 4 bytes are an unsigned integer representing the palette size
- The next 2 bytes are an unsigned integer representing PalX
- The next 2 bytes are an unsigned integer representing PalY
- The next 2 bytes are an unsigned integer representing the palette width
- The next 2 bytes are an unsigned integer representing the palette height
- Next are 6 colors, each composed of 2 bytes
- From leftmost bit to rightmost bit:
- The first bit denotes alpha (1: alpha = 255; 0: alpha = 0)
- The next 5 bits are an unsigned integer for Blue
- The next 5 bits are an unsigned integer for Green
- The next 5 bits are an unsigned integer for Red
- In other words:
ABBBBBGG GGGRRRRR
(A
= Mask,B
= Blue,G
= Green,R
= Red)
- The first 4 bytes of this subsection are the string
BACK
- The next 2 bytes are an unsigned integer representing the width
- The next 2 bytes are an unsigned integer representing the height
- The next 2 bytes are an unsigned integer representing the total number of tiles
- The next 4 bytes are an unsigned integer denoting the depth
- This seems to just be
<NULL><NULL>
(i.e.,0x0 0x0
)
- Each background tile has the following components:
- 2 bytes: Blank (seems to just be
<NULL><NULL>
) - 2 bytes: Destination X (signed int)
- 2 bytes: Destination Y (signed int)
- 4 bytes: Unknown 1
- 1 byte: Source X (unsigned integer)
- 1 byte: Unknown 2
- 1 byte: Source Y (unsigned integer)
- 1 byte: Unknown 3
- 1 byte: Source X2 (unsigned integer)
- 1 byte: Unknown 4
- 1 byte: Source Y2 (unsigned integer)
- 1 byte: Unknown 5
- 2 bytes: Width (unsigned integer) (normally unused)
- Can probably always just assume 16 (even if the value in the tile doesn't match)
- 2 bytes: Height (unsigned integer) (normally unused)
- Can probably always just assume 16 (even if the value in the tile doesn't match)
- 1 byte: Palette ID (unsigned integer)
- 1 byte: Unknown 6
- 2 bytes: ID (unsigned integer)
- 1 byte: Param (unsigned integer)
- 1 byte: State (unsigned integer)
- 1 byte: Blending (unsigned integer)
- 1 byte: Unknown 7
- 1 byte: Type Trans (unsigned integer)
- 1 byte: Unknown 8
- 1 byte: Texture ID (unsigned integer)
- 1 byte: Unknown 9
- 1 byte: Texture ID 2 (unsigned integer)
- 1 byte: Unknown 10
- 1 byte: Depth (unsigned integer) (normally unused)
- 1 byte: Unknown 11
- 4 bytes: ID Big (unsigned integer)
- 4 bytes: Source X Big (unsigned integer)
- 4 bytes: Source Y Big (unsigned integer)
- 2 bytes: Blank (seems to just be
<NULL><NULL>
)
- 2 bytes: Blank (seems to just be
- Note that, for Destination X and Destination Y, (0,0) is the center of the image, not the top-left corner
- This seems to just be
<NULL><NULL>
(i.e.,0x0 0x0
)
- This is an unsigned integer
- 1 denotes the presence of Layer 2, otherwise 0
- If 0, there is nothing else in Layer 2 after this
- The next 2 bytes are an unsigned integer representing the width
- The next 2 bytes are an unsigned integer representing the height
- The next 2 bytes are an unsigned integer representing the total number of tiles
- The next 16 bytes have unknown function and are unused
- This seems to just be
<NULL><NULL>
(i.e.,0x0 0x0
)
- Each background tile has the same components as in Layer 1
- This seems to just be
<NULL><NULL>
(i.e.,0x0 0x0
)
- This is an unsigned integer
- 1 denotes the presence of Layer 2, otherwise 0
- If 0, there is nothing else in Layer 2 after this
- The next 2 bytes are an unsigned integer representing the width
- The next 2 bytes are an unsigned integer representing the height
- The next 2 bytes are an unsigned integer representing the total number of tiles
- The next 16 bytes have unknown function and are unused
- This seems to just be
<NULL><NULL>
(i.e.,0x0 0x0
)
- Each background tile has the same components as in Layer 1
- This seems to just be
<NULL><NULL>
(i.e.,0x0 0x0
)
- This is an unsigned integer
- 1 denotes the presence of Layer 2, otherwise 0
- If 0, there is nothing else in Layer 2 after this
- The next 2 bytes are an unsigned integer representing the width
- The next 2 bytes are an unsigned integer representing the height
- The next 2 bytes are an unsigned integer representing the total number of tiles
- The next 16 bytes have unknown function and are unused
- This seems to just be
<NULL><NULL>
(i.e.,0x0 0x0
)
- Each background tile has the same components as in Layer 1
- This seems to just be
<NULL><NULL>
(i.e.,0x0 0x0
)
- The first 7 bytes of this subsection are the string
TEXTURE
- The remaining bytes in this subsection are the actual textures
- For each of the possible 42 textures:
- 2 bytes: "Exists" flag
- If the "Exists" flag is 1 (i.e., True):
- 2 bytes: Size
- 2 bytes: Depth
- Depth * 65,536 Bytes: Data
- The first 3 bytes are the string
END
- The next (and last) 14 bytes are the string
FINAL FANTASY7