XPR

From xboxdevwiki
Revision as of 03:17, 22 September 2023 by QuantX (talk | contribs) (Complete rewrite based on my reverse engineering of the XPR0 format as used by Steel Battalion and Steel Battalion: Line of Contact)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

XPR probably stands for Xbox Packed Resource. It's a structure and file-format used by the Microsoft XDK. It is being used in parts of XAPI.

XPRs can store a variety of different data types that are useful for Xbox D3D. XPRs are storing data similar to internal structures in the D3D driver. So D3D has mechanisms to simply load such resources into D3D objects (by moving them into GPU accessible memory).

An XPR header consists of a number of resource entries which each look something like this[FIXME]:

struct {
  union {
    uint32_t resource_type; // Type information and who "owns" this resource
    struct {
      uint32_t ref_count:16; // (lowest bits)
      uint32_t type:3;
      uint32_t unk3:13; // (highest bits)
    };
  };
  uint32_t data; // Offset of this resource's data in the file
  uint32_t unknown; // Always zero

  union {
    struct XPR_Vertexbuffer; // Vertexbuffer (type 0x0)
      ...
    } XPR_Vertexbuffer;
    struct { // Indexbuffer (type 0x1)
      ...
    } XPR_Indexbuffer;
    struct { // Unknown (type 0x2)
      ...
    } ...;
    struct { // Unknown (type 0x3)
      ...
    } ...;
    struct { // Texture (type 0x4)
      ...;
    } XPR_Texture;
    struct { // Unknown (type 0x5)
      ...
    } ...;
    struct { // Unknown (type 0x6)
      ...
    } ...;
    struct { // Unknown (type 0x7)
      ...
    } ...;
  };
} XPR_Resource;

The XPR header as a whole looks like this:

union {
  struct {
    char magic[4]; // Always "XPR0" / 0x30525058
    uint32_t size; // Size of XPR (including magic and this field)
    uint32_t header_size; // Size of this header rounded up to the nearest 2048 byte boundary
    XPR_Resource resources[]; // An array of XPR_Resource entries
    uint32_t last_resource; // Always 0xFFFFFFFF
  };
  uint8_t pad[XPR.header_size]; // Padded with 0xAD bytes
} XPR;

The headers are then followed by the resource data.


Texture data can be stored in a variety of hardware defined formats as specified by the architecture of the NV2A GPU. The format used, along with other information such as width, height, depth, and mipmap levels is stored in the resource header for the texture.

The format for an XPR texture resource is as follows:

struct {
  union {
    uint32_t gpu; // This 32-bit value is placed in the NV097_SET_TEXTURE_FORMAT GPU register
    struct {
      uint32_t dma : 4; (lowest bits)
      uint32_t dimensions : 4; // Is this a 1D, 2D, or 3D texture
      uint32_t format : 8; // The format of the texture data (see the table below)
      uint32_t levels : 4; // Number of mipmap levels
      uint32_t width : 4; // Width of the texture in the following format: actual_width = (1 << width)
      uint32_t height : 4; // Height of the texture in the following format: actual_height = (1 << height)
      uint32_t depth: 4; (highest bits) // Depth of the texture (for 3D textures) in the following format: actual_depth = (1 << depth)
    };
  };
  union {
    uint32_t size; // Describes the size of a texture who's dimensions are not a power-of-2
    struct {
      uint32_t width : 12; (lowest bits) // The width of the texture in the following format: actual_width = width + 1
      uint32_t height : 12; // The height of the texture in the following format: actual_height = height + 1
      uint32_t depth : 8; (highest bits) // The depth of the texture (for 3D textures) in the following format: actual_depth = depth + 1
    }
  };
} XPR_Texture;


For textures that use arbitrary dimensions the width, height, and depth attributes of the gpu field should be zero. For textures such as DXT that use power-of-2 dimensions the size field should be zero.

The following as a list of texture formats which can be used for the format attribute of the gpu field:

NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A1R5G5B5       0x02
NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X1R5G5B5       0x03
NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A4R4G4B4       0x04
NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R5G6B5         0x05
NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8R8G8B8       0x06
NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X8R8G8B8       0x07
NV097_SET_TEXTURE_FORMAT_COLOR_SZ_I8_A8R8G8B8    0x0B
NV097_SET_TEXTURE_FORMAT_COLOR_L_DXT1_A1R5G5B5   0x0C
NV097_SET_TEXTURE_FORMAT_COLOR_L_DXT23_A8R8G8B8  0x0E
NV097_SET_TEXTURE_FORMAT_COLOR_L_DXT45_A8R8G8B8  0x0F
NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_R5G6B5   0x11
NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A8R8G8B8 0x12
NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8             0x19
NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8 0x1E
NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_Y16_FIXED 0x30
NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8B8G8R8       0x3A
NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A8B8G8R8 0x3F