.EMD (Resident Evil) - pmandin/reevengi-tools GitHub Wiki
The .EMD file format is used by Resident Evil. It contains the description of 3D models of the game (enemies, player, etc...).
The values are stored in Little-Endian order.
There is a directory, which is stored at the end of the file, it contains 4 offsets. So its position is filesize-4*4 bytes.
This section starts with a header:
typedef struct { unsigned short bone_offset;/* Relative offset to emd1_skel_armature_t[] array */ unsigned short length; /* Relative offset to emd1_skel_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 emd1_skel_data[] array */ } emd1_skel_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 (emd1_skel_mesh[] array) */ } emd1_skel_armature_t; emd1_skel_relpos_t emd1_skel_relpos[count]; emd1_skel_armature_t emd1_skel_armature[count]; unsigned char emd1_skel_mesh[count]; /* Mesh number on which to apply relative position */
Finally an array of elements which have a size of emd1_skel_header.size 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; short angles[3*15]; /* angle for each bone/model around x,y,z axis */ short unknown; } emd1_skel_anim_t; emd1_skel_anim_t emd1_skel_anim[];
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-16: Bitmasks for flags */ /* Bits 15-0: Number of frame to display ? */
Then you'll finally find the 'unsigned long' byte length of the section.
unsigned long length;
The last object holds the 3D stuff. Maybe the rest of the file is use to store animations, and links between primitives.
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;
The model is separated in 'obj_count' 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 dummy; } emd_model_triangles_t;
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 long unknown; /* id 0x34000609 */ unsigned char tu0; /* u,v texture coordinates of vertex 0 */ unsigned char tv0; unsigned short clutid; /* Texture clut id, bits 0-5 */ unsigned char tu1; unsigned char tv1; unsigned short page; /* Texture page */ unsigned char tu2; unsigned char tv2; unsigned short dummy; 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 */
And finally, an embedded .TIM image, which is the texture to apply to the model.