.EMD (Resident Evil 2 PC) - pmandin/reevengi-tools GitHub Wiki

Table of Contents

Games

The .EMD file format is used by Resident Evil 2. It contains the description of 3D models of the game (enemies, player, etc...).

Structure

The values are stored in Little-Endian order.

Directory

The start of the file holds offset and count to a directory:

typedef struct {
    unsigned long dir_offset; /* Offset to directory */
    unsigned long dir_count;  /* Number of objects in directory */
} emd_header_t;

The directory is an array of 'unsigned long' offsets to small parts (files), and often resides at the end of the EMD file. Each file in the directory seems to have a specific purpose. File/section 0

NULL terminated list of unknown stuff

File/section 1, animation steps

This section starts with this header, a certain number of records composed of count and offsets.

emd_anim_header_t emd_anim_header[];

Following this array, you'll find another array of unsigned long. Each value (animation frame number?) is an index in emd_sec2_data array in the skeleton section.

unsigned long emd_anim_skel_t[];    /* Bits 31-12:   Bitmasks for flags */
                                    /* Bits 11-0:    Number of frame to display ? */

Then you'll finally find the 'unsigned long' byte length of the section.

unsigned long length;

File/section 2, skeleton

This section starts with a header:

typedef struct {
    unsigned short relpos_offset;/* Relative offset to emd_sec2_relpos[] array */
    unsigned short length; /* Relative offset to emd_sec2_data[] array, which is also length of relpos+armature+mesh numbers  */
    unsigned short count; /* Number of objects in relpos,data2,mesh arrays? */
    unsigned short size; /* Size of each element in emd_sec2_data[] array */
} emd_sec2_header_t;

If offset is more than 8, there are some extra stuff, namely data1,data2 and mesh arrays.

typedef struct {
    unsigned short mesh_count; /* Number of meshes linked to this one */
    unsigned short offset; /* Relative offset to mesh numbers (emc_sec2_mesh[] array) */
} emd_sec2_armature_t;

emd_sec2_relpos_t emd_sec2_relpos[count];
emd_sec2_armature_t emd_sec2_armature[count];
unsigned char emd_sec2_mesh[count]; /* Mesh number on which to apply relative position */

Finally an array of elements which have a size of 80 bytes each.

typedef struct {
	short x_offset;	/* distance from reference point */
	short y_offset;
	short z_offset;

	short x_speed;	/* speed at which moving the model */
	short y_speed;
	short z_speed;

	char angles[74];	/* angle for each bone/model around x,y,z axis */
				/* Note: they are stored as 12 bits value, so you need to split bytes */
} emd_sec2_data_t;

emd_sec2_data_t emd_sec2_data[];

The 12bits values for angles are stored in the usual little endian order, you just need to split the bytes to get all needed bits. Here is some reference (for each skeleton mesh, you have 3 angles, x,y,z to apply on it):

Byte from file Target value Bits
XX --XX bits 7-0 of x angle for mesh # 0
YX -X-- bits 3-0: bits 11-8 of x angle for mesh # 0
_ ---Y bits 7-4: bits 3-0 of y angle for mesh # 0
YY -YY- bits 11-4 of y angle for mesh # 0
ZZ --ZZ bits 7-0 of z angle for mesh # 0
XZ -Z-- bits 3-0: bits 11-8 of z angle for mesh # 0
_ ---X bits 7-4: bits 3-0 of x angle for mesh # 1
XX -XX- bits 11-4 of x angle for mesh # 1
YY --YY bits 7-0 of y angle for mesh # 1
ZY -Y-- bits 3-0: bits 11-8 of y angle for mesh # 1
_ ---Z bits 7-4: bits 3-0 of z angle for mesh # 1
ZZ -ZZ- bits 11-4 of z angle for mesh # 1
and so on ...

12 bits values mean the complete cycle is done with values from 0 to 4095.

File/section 3, animation steps

Same format as section 1.

File/section 4, skeleton

Same format as section 2.

File/section 5, animation steps

Same format as section 1.

File/section 6, skeleton

Same format as section 2.

File/section 7, meshes

The 7th object holds the 3D stuff. Maybe the rest of the file is use to store animations, and links between primitives.

Header

typedef struct {
    unsigned long length; /* Section length in bytes */
    unsigned long unknown;
    unsigned long obj_count; /* Number of objects in model */
} emd_model_header_t;

Objects

The model is separated in 'obj_count/2' objects. Following the header is the description of each object, in the form of an array of 'model_object'. Each offset is relative to the first emd_model_object_t.

typedef struct {
    unsigned long vertex_offset; /* Offset to vertex data, array of emd_vertex_t */
    unsigned long vertex_count;  /* Vertex count */
    unsigned long normal_offset; /* Offset to normal data, array of emd_vertex_t */
    unsigned long normal_count;  /* Normal count */
    unsigned long tri_offset; /* Offset to triangle data, array of emd_triangle_t */
    unsigned long tri_count;  /* Triangle count */
    unsigned long tritexture_offset; /* Offset to triangle texture data, array of emd_tritexture_t */
} emd_model_triangles_t;

typedef struct {
    unsigned long vertex_offset; /* Offset to vertex data, array of emd_vertex_t */
    unsigned long vertex_count;  /* Vertex count */
    unsigned long normal_offset; /* Offset to normal data, array of emd_vertex_t */
    unsigned long normal_count;  /* Normal count */
    unsigned long quad_offset; /* Offset to quad index data, array of emd_quad_t */
    unsigned long quad_count;  /* Quad count */
    unsigned long quadtexture_offset; /* Offset to quad texture data, array of emd_quadtexture_t */
} emd_model_quads_t;

Index arrays

Normal and vertex coordinates are saved in same format:

typedef struct {
    signed short x; /* Coordinates */
    signed short y;
    signed short z;
    signed short zero;    
} emd_vertex_t; /* Normals have same format */

A triangle is stored in this format:

typedef struct {
    unsigned short n0; /* Index of normal data for vertex 0 */
    unsigned short v0; /* Index of vertex data for vertex 0 */
    unsigned short n1;
    unsigned short v1;    
    unsigned short n2;
    unsigned short v2;    
} emd_triangle_t; /* Triangle */

Triangle texturing information in this format:

typedef struct {
    unsigned char u0; /* u,v texture coordinates of vertex 0 */
    unsigned char v0;
    unsigned short clutid; /* Texture clut id, bits 0-5 */
    unsigned char u1;
    unsigned char v1;
    unsigned short page;  /* Texture page */
    unsigned char u2;
    unsigned char v2;
    unsigned short zero;
} emd_tritexture_t; /* Triangle texture information */

A quad is stored in this format:

typedef struct {
    unsigned short n0; /* Index of normal data for vertex 0 */
    unsigned short v0; /* Index of vertex data for vertex 0 */
    unsigned short n1; /* Note: a quad is 2 triangles: v0,v1,v3 and v1,v3,v2 */
    unsigned short v1; /*  If you draw it directly, uses v0,v1,v3,v2 for a right order */    
    unsigned short n2;
    unsigned short v2;
    unsigned short n3;
    unsigned short v3;    
} emd_quad_t; /* Quad */

Quad texturing information in this format:

typedef struct {
    unsigned char u0; /* u,v texture coordinates of vertex 0 */
    unsigned char v0;
    unsigned short clutid; /* Texture clut id, bits 0-5 */
    unsigned char u1;
    unsigned char v1;
    unsigned short page;  /* Texture page */
    unsigned char u2;
    unsigned char v2;
    unsigned short zero1;
    unsigned char u3;
    unsigned char v3;
    unsigned short zero2;
} emd_quadtexture_t; /* Quad texture information */
⚠️ **GitHub.com Fallback** ⚠️