/* ================ Mod_Free ================ */ void Mod_Free (model_t *mod) { model_t *hashstart; model_t **prev; unsigned hash; hash = hashify (mod->name) % MODEL_HASH_SIZE; prev = &models_hash[hash]; for (;;) { hashstart = *prev; if (!hashstart) break; if (hashstart == mod) { *prev = hashstart->hash_next; break; } prev = &hashstart->hash_next; } Hunk_Free (mod->extradata); memset (mod, 0, sizeof(*mod)); }
/* @@@@@@@@@@@@@@@@@@@@@ RE_EndRegistration @@@@@@@@@@@@@@@@@@@@@ */ void RE_EndRegistration(void) { int i; model_t *mod; for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) { if (!mod->name[0]) continue; if (mod->registration_sequence != registration_sequence) { // don't need this model Hunk_Free(mod->extradata); memset(mod, 0, sizeof(*mod)); } else { // make sure it is paged in Com_PageInMemory(mod->extradata, mod->extradatasize); } } R_FreeUnusedImages(); }
/* ================ Mod_Free ================ */ void Mod_Free (model_t *mod) { Hunk_Free (mod->extradata); memset (mod, 0, sizeof(*mod)); }
/* ================= Mod_LoadAliasModel ================= */ qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length) { dmd2header_t header; dmd2frame_t *src_frame; //dmd2trivertx_t *src_vert; dmd2triangle_t *src_tri; dmd2stvert_t *src_st; maliasframe_t *dst_frame; //maliasvert_t *dst_vert; maliastri_t *dst_tri; maliasst_t *dst_st; char skinname[MAX_QPATH]; char *src_skin; int i, j; qerror_t ret; if (length < sizeof(header)) { return Q_ERR_FILE_TOO_SMALL; } // byte swap the header header = *(dmd2header_t *)rawdata; for (i = 0; i < sizeof(header) / 4; i++) { ((uint32_t *)&header)[i] = LittleLong(((uint32_t *)&header)[i]); } // validate the header ret = MOD_ValidateMD2(&header, length); if (ret) { if (ret == Q_ERR_TOO_FEW) { // empty models draw nothing model->type = MOD_EMPTY; return Q_ERR_SUCCESS; } return ret; } Hunk_Begin(&model->hunk, 0x400000); model->type = MOD_ALIAS; // load triangle indices model->tris = MOD_Malloc(header.num_tris * sizeof(maliastri_t)); model->numtris = header.num_tris; src_tri = (dmd2triangle_t *)((byte *)rawdata + header.ofs_tris); dst_tri = model->tris; for (i = 0; i < header.num_tris; i++, src_tri++, dst_tri++) { for (j = 0; j < 3; j++) { unsigned idx_xyz = LittleShort(src_tri->index_xyz[j]); unsigned idx_st = LittleShort(src_tri->index_st[j]); if (idx_xyz >= header.num_xyz || idx_st >= header.num_st) { ret = Q_ERR_BAD_INDEX; goto fail; } dst_tri->index_xyz[j] = idx_xyz; dst_tri->index_st[j] = idx_st; } } // load base s and t vertices model->sts = MOD_Malloc(header.num_st * sizeof(maliasst_t)); model->numsts = header.num_st; src_st = (dmd2stvert_t *)((byte *)rawdata + header.ofs_st); dst_st = model->sts; for (i = 0; i < header.num_st; i++, src_st++, dst_st++) { dst_st->s = (int16_t)LittleShort(src_st->s); dst_st->t = (int16_t)LittleShort(src_st->t); } // load the frames model->frames = MOD_Malloc(header.num_frames * sizeof(maliasframe_t)); model->numframes = header.num_frames; model->numverts = header.num_xyz; src_frame = (dmd2frame_t *)((byte *)rawdata + header.ofs_frames); dst_frame = model->frames; for (i = 0; i < header.num_frames; i++, dst_frame++) { for (j = 0; j < 3; j++) { dst_frame->scale[j] = LittleFloat(src_frame->scale[j]); dst_frame->translate[j] = LittleFloat(src_frame->translate[j]); } // verts are all 8 bit, so no swapping needed dst_frame->verts = MOD_Malloc(header.num_xyz * sizeof(maliasvert_t)); // TODO: check normal indices memcpy(dst_frame->verts, src_frame->verts, header.num_xyz * sizeof(maliasvert_t)); src_frame = (dmd2frame_t *)((byte *)src_frame + header.framesize); } // register all skins src_skin = (char *)rawdata + header.ofs_skins; for (i = 0; i < header.num_skins; i++) { if (!Q_memccpy(skinname, src_skin, 0, sizeof(skinname))) { ret = Q_ERR_STRING_TRUNCATED; goto fail; } FS_NormalizePath(skinname, skinname); model->skins[i] = IMG_Find(skinname, IT_SKIN); src_skin += MD2_MAX_SKINNAME; } model->numskins = header.num_skins; Hunk_End(&model->hunk); return Q_ERR_SUCCESS; fail: Hunk_Free(&model->hunk); return ret; }