+ loadmodel->synctype = ST_RAND;
+
+ // byteswap header
+ header.version = LittleLong(header.version);
+ header.filesize = LittleLong(header.filesize);
+ header.flags = LittleLong(header.flags);
+ header.num_text = LittleLong(header.num_text);
+ header.ofs_text = LittleLong(header.ofs_text);
+ header.num_meshes = LittleLong(header.num_meshes);
+ header.ofs_meshes = LittleLong(header.ofs_meshes);
+ header.num_vertexarrays = LittleLong(header.num_vertexarrays);
+ header.num_vertexes = LittleLong(header.num_vertexes);
+ header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
+ header.num_triangles = LittleLong(header.num_triangles);
+ header.ofs_triangles = LittleLong(header.ofs_triangles);
+ header.ofs_neighbors = LittleLong(header.ofs_neighbors);
+ header.num_joints = LittleLong(header.num_joints);
+ header.ofs_joints = LittleLong(header.ofs_joints);
+ header.num_poses = LittleLong(header.num_poses);
+ header.ofs_poses = LittleLong(header.ofs_poses);
+ header.num_anims = LittleLong(header.num_anims);
+ header.ofs_anims = LittleLong(header.ofs_anims);
+ header.num_frames = LittleLong(header.num_frames);
+ header.num_framechannels = LittleLong(header.num_framechannels);
+ header.ofs_frames = LittleLong(header.ofs_frames);
+ header.ofs_bounds = LittleLong(header.ofs_bounds);
+ header.num_comment = LittleLong(header.num_comment);
+ header.ofs_comment = LittleLong(header.ofs_comment);
+ header.num_extensions = LittleLong(header.num_extensions);
+ header.ofs_extensions = LittleLong(header.ofs_extensions);
+
+ if (header.version == 1)
+ {
+ if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
+ pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
+ {
+ Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
+ return;
+ }
+ }
+ else
+ {
+ if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
+ pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
+ {
+ Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
+ return;
+ }
+ }
+ if (pbase + header.ofs_text + header.num_text > pend ||
+ pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
+ pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
+ pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
+ (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
+ pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
+ pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
+ (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
+ pbase + header.ofs_comment + header.num_comment > pend)
+ {
+ Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
+ return;
+ }
+
+ // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
+ if (header.num_vertexarrays)
+ vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
+ if (header.num_anims)
+ anims = (iqmanim_t *)(pbase + header.ofs_anims);
+ if (header.ofs_bounds)
+ bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
+ if (header.num_meshes)
+ meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
+
+ for (i = 0;i < (int)header.num_vertexarrays;i++)
+ {
+ iqmvertexarray_t va;
+ size_t vsize;
+ va.type = LittleLong(vas[i].type);
+ va.flags = LittleLong(vas[i].flags);
+ va.format = LittleLong(vas[i].format);
+ va.size = LittleLong(vas[i].size);
+ va.offset = LittleLong(vas[i].offset);
+ vsize = header.num_vertexes*va.size;
+ switch (va.format)
+ {
+ case IQM_FLOAT: vsize *= sizeof(float); break;
+ case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
+ default: continue;
+ }
+ if (pbase + va.offset + vsize > pend)
+ continue;
+ // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
+ switch (va.type)
+ {
+ case IQM_POSITION:
+ if (va.format == IQM_FLOAT && va.size == 3)
+ vposition = (const float *)(pbase + va.offset);
+ break;
+ case IQM_TEXCOORD:
+ if (va.format == IQM_FLOAT && va.size == 2)
+ vtexcoord = (const float *)(pbase + va.offset);
+ break;
+ case IQM_NORMAL:
+ if (va.format == IQM_FLOAT && va.size == 3)
+ vnormal = (const float *)(pbase + va.offset);
+ break;
+ case IQM_TANGENT:
+ if (va.format == IQM_FLOAT && va.size == 4)
+ vtangent = (const float *)(pbase + va.offset);
+ break;
+ case IQM_BLENDINDEXES:
+ if (va.format == IQM_UBYTE && va.size == 4)
+ vblendindexes = (const unsigned char *)(pbase + va.offset);
+ break;
+ case IQM_BLENDWEIGHTS:
+ if (va.format == IQM_UBYTE && va.size == 4)
+ vblendweights = (const unsigned char *)(pbase + va.offset);
+ break;
+ case IQM_COLOR:
+ if (va.format == IQM_FLOAT && va.size == 4)
+ vcolor4f = (const float *)(pbase + va.offset);
+ if (va.format == IQM_UBYTE && va.size == 4)
+ vcolor4ub = (const unsigned char *)(pbase + va.offset);
+ break;
+ }
+ }
+ if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
+ {
+ Con_Printf("%s is missing vertex array data\n", loadmodel->name);
+ return;
+ }
+
+ text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
+