/* ===================== S_BeginRegistration ===================== */ void S_BeginRegistration (void) { int i; sfx_t *sfx; // free all sounds for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++) { if (!sfx->name[0]) continue; memset (sfx, 0, sizeof(*sfx)); } num_sfx = 0; Hunk_Begin(&hunk_snd); s_registering = true; }
void R_BeginRegistration (char *model) { char fullname[MAX_QPATH]; Prof_Begin(__FUNCTION__); registration_sequence++; r_oldviewcluster = -1; // force markleafs Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model); Mod_FreeAll (); Hunk_Begin (&hunk_ref); r_worldmodel = Mod_ForName(fullname, true); r_viewcluster = -1; Prof_End(); }
/* ================== Mod_ForName Loads in a model for the given name ================== */ model_t *Mod_ForName (char *name, qboolean crash) { model_t *mod; unsigned *buf; int i; if (!name[0]) ri.Sys_Error (ERR_DROP, "Mod_ForName: NULL name"); // // inline models are grabbed only from worldmodel // if (name[0] == '*') { i = atoi(name+1); if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels) ri.Sys_Error (ERR_DROP, "bad inline model number"); return &mod_inline[i]; } // // search the currently loaded models // for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) { if (!mod->name[0]) continue; if (!strcmp (mod->name, name) ) return mod; } // // find a free model slot spot // for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) { if (!mod->name[0]) break; // free spot } if (i == mod_numknown) { if (mod_numknown == MAX_MOD_KNOWN) ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); mod_numknown++; } strcpy (mod->name, name); // // load the file // modfilelen = ri.FS_LoadFile (mod->name, &buf); if (!buf) { if (crash) ri.Sys_Error (ERR_DROP, "Mod_NumForName: %s not found", mod->name); memset (mod->name, 0, sizeof(mod->name)); return NULL; } loadmodel = mod; // // fill it in // // call the apropriate loader switch (LittleLong(*(unsigned *)buf)) { case IDALIASHEADER: loadmodel->extradata = Hunk_Begin (0x200000); Mod_LoadAliasModel (mod, buf); break; case IDSPRITEHEADER: loadmodel->extradata = Hunk_Begin (0x10000); Mod_LoadSpriteModel (mod, buf); break; case IDBSPHEADER: loadmodel->extradata = Hunk_Begin (0x1000000); Mod_LoadBrushModel (mod, buf); break; default: ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name); break; } loadmodel->extradatasize = Hunk_End (); ri.FS_FreeFile (buf); return mod; }
void LoadMD2(model_t *mod, void *buffer, int modfilelen) { int i, j; dmdl_t *pinmodel, *pheader; dstvert_t *pinst, *poutst; dtriangle_t *pintri, *pouttri; daliasframe_t *pinframe, *poutframe; int *pincmd, *poutcmd; int version; int ofs_end; pinmodel = (dmdl_t *)buffer; version = LittleLong(pinmodel->version); if (version != ALIAS_VERSION) { ri.Sys_Error(ERR_DROP, "%s has wrong version number (%i should be %i)", mod->name, version, ALIAS_VERSION); } ofs_end = LittleLong(pinmodel->ofs_end); if (ofs_end < 0 || ofs_end > modfilelen) ri.Sys_Error (ERR_DROP, "model %s file size(%d) too small, should be %d", mod->name, modfilelen, ofs_end); mod->extradata = Hunk_Begin(modfilelen); pheader = Hunk_Alloc(ofs_end); /* byte swap the header fields and sanity check */ for (i = 0; i < sizeof(dmdl_t) / 4; i++) { ((int *)pheader)[i] = LittleLong(((int *)buffer)[i]); } if (pheader->skinheight > MAX_LBM_HEIGHT) { ri.Sys_Error(ERR_DROP, "model %s has a skin taller than %d", mod->name, MAX_LBM_HEIGHT); } if (pheader->num_xyz <= 0) { ri.Sys_Error(ERR_DROP, "model %s has no vertices", mod->name); } if (pheader->num_xyz > MAX_VERTS) { ri.Sys_Error(ERR_DROP, "model %s has too many vertices", mod->name); } if (pheader->num_st <= 0) { ri.Sys_Error(ERR_DROP, "model %s has no st vertices", mod->name); } if (pheader->num_tris <= 0) { ri.Sys_Error(ERR_DROP, "model %s has no triangles", mod->name); } if (pheader->num_frames <= 0) { ri.Sys_Error(ERR_DROP, "model %s has no frames", mod->name); } /* load base s and t vertices (not used in gl version) */ pinst = (dstvert_t *)((byte *)pinmodel + pheader->ofs_st); poutst = (dstvert_t *)((byte *)pheader + pheader->ofs_st); for (i = 0; i < pheader->num_st; i++) { poutst[i].s = LittleShort(pinst[i].s); poutst[i].t = LittleShort(pinst[i].t); } /* load triangle lists */ pintri = (dtriangle_t *)((byte *)pinmodel + pheader->ofs_tris); pouttri = (dtriangle_t *)((byte *)pheader + pheader->ofs_tris); for (i = 0; i < pheader->num_tris; i++) { for (j = 0; j < 3; j++) { pouttri[i].index_xyz[j] = LittleShort(pintri[i].index_xyz[j]); pouttri[i].index_st[j] = LittleShort(pintri[i].index_st[j]); } } /* load the frames */ for (i = 0; i < pheader->num_frames; i++) { pinframe = (daliasframe_t *)((byte *)pinmodel + pheader->ofs_frames + i * pheader->framesize); poutframe = (daliasframe_t *)((byte *)pheader + pheader->ofs_frames + i * pheader->framesize); memcpy(poutframe->name, pinframe->name, sizeof(poutframe->name)); for (j = 0; j < 3; j++) { poutframe->scale[j] = LittleFloat(pinframe->scale[j]); poutframe->translate[j] = LittleFloat(pinframe->translate[j]); } /* verts are all 8 bit, so no swapping needed */ memcpy(poutframe->verts, pinframe->verts, pheader->num_xyz * sizeof(dtrivertx_t)); } mod->type = mod_alias; /* load the glcmds */ pincmd = (int *)((byte *)pinmodel + pheader->ofs_glcmds); poutcmd = (int *)((byte *)pheader + pheader->ofs_glcmds); for (i = 0; i < pheader->num_glcmds; i++) { poutcmd[i] = LittleLong(pincmd[i]); } /* register all skins */ memcpy((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins, pheader->num_skins * MAX_SKINNAME); for (i = 0; i < pheader->num_skins; i++) { mod->skins[i] = R_FindImage( (char *)pheader + pheader->ofs_skins + i * MAX_SKINNAME, it_skin); } mod->mins[0] = -32; mod->mins[1] = -32; mod->mins[2] = -32; mod->maxs[0] = 32; mod->maxs[1] = 32; mod->maxs[2] = 32; }
/* ================== Mod_ForName Loads in a model for the given name ================== */ model_t *Mod_ForName (const char *name_, qboolean crash) { model_t *mod; model_t *modelhash; mscache_t *model_size; byte *buf; int i; unsigned hash; size_t len = strlen(name_); char *name = (char *) alloca(len + 1); strcpy(name, name_); if (!name || !name[0]) VID_Error (ERR_DROP, "Mod_ForName: NULL name"); // // inline models are grabbed only from worldmodel // if (name[0] == '*') { i = atoi(name+1); if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels) VID_Error (ERR_DROP, "bad inline model number %d", i); return &mod_inline[i]; } fast_strlwr (name); hash = hashify (name) % MODEL_HASH_SIZE; for (modelhash = models_hash[hash]; modelhash; modelhash = modelhash->hash_next) { if (!strcmp (modelhash->name, name)) { return modelhash; } } for (model_size = model_size_cache[hash]; model_size; model_size = model_size->hash_next) { if (!strcmp (model_size->name, name)) break; } // // search the currently loaded models // /*for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) { if (!mod->name[0] || mod->hash != hash) continue; if (!strcmp (mod->name, name) ) return mod; }*/ // // find a free model slot spot // for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) { if (!mod->name[0]) break; // free spot } if (i == mod_numknown) { if (mod_numknown == MAX_MOD_KNOWN) VID_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); mod_numknown++; } strncpy (mod->name, name, sizeof(mod->name)-1); // // load the file // modfilelen = FS_LoadFile (name, (void **)&buf); if (!buf) { if (crash) VID_Error (ERR_DROP, "Mod_NumForName: %s not found", mod->name); mod->name[0] = 0; return NULL; } loadmodel = mod; // // fill it in // // call the apropriate loader switch (LittleLong(*(unsigned *)buf)) { case IDALIASHEADER: if (model_size) loadmodel->extradata = Hunk_Begin (model_size->size, model_size->size); else loadmodel->extradata = Hunk_Begin (0x200000, 0); Mod_LoadAliasModel (mod, buf); break; case IDSPRITEHEADER: if (model_size) loadmodel->extradata = Hunk_Begin (model_size->size, model_size->size); else loadmodel->extradata = Hunk_Begin (0x4000, 0); Mod_LoadSpriteModel (mod, buf); break; case IDBSPHEADER: if (model_size) loadmodel->extradata = Hunk_Begin (model_size->size, model_size->size); else loadmodel->extradata = Hunk_Begin (0x1000000, 0); Mod_LoadBrushModel (mod, buf); break; default: VID_Error (ERR_DROP,"Mod_NumForName: unknown 0x%.8x fileid for %s", LittleLong(*(unsigned *)buf), mod->name); break; } if (model_size) { loadmodel->extradatasize = model_size->size; } else { loadmodel->extradatasize = Hunk_End (); model_size = (mscache_t *) malloc (sizeof(*model_size)); if (!model_size) VID_Error (ERR_FATAL, "Mod_ForName: out of memory"); strcpy (model_size->name, mod->name); model_size->size = loadmodel->extradatasize; model_size->hash_next = model_size_cache[hash]; model_size_cache[hash] = model_size; } mod->hash_next = models_hash[hash]; models_hash[hash] = mod; FS_FreeFile (buf); return mod; }
/* * Loads in a model for the given name */ model_t * Mod_ForName(char *name, qboolean crash) { model_t *mod; unsigned *buf; int i; if (!name[0]) { ri.Sys_Error(ERR_DROP, "Mod_ForName: NULL name"); } /* inline models are grabbed only from worldmodel */ if (name[0] == '*') { i = (int)strtol(name + 1, (char **)NULL, 10); if ((i < 1) || !r_worldmodel || (i >= r_worldmodel->numsubmodels)) { ri.Sys_Error(ERR_DROP, "bad inline model number"); } return &mod_inline[i]; } /* search the currently loaded models */ for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) { if (!mod->name[0]) { continue; } if (!strcmp(mod->name, name)) { return mod; } } /* find a free model slot spot */ for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) { if (!mod->name[0]) { break; /* free spot */ } } if (i == mod_numknown) { if (mod_numknown == MAX_MOD_KNOWN) { ri.Sys_Error(ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); } mod_numknown++; } strcpy(mod->name, name); /* load the file */ modfilelen = ri.FS_LoadFile(mod->name, (void **)&buf); if (!buf) { if (crash) { ri.Sys_Error(ERR_DROP, "Mod_NumForName: %s not found", mod->name); } memset(mod->name, 0, sizeof(mod->name)); return NULL; } loadmodel = mod; /* call the apropriate loader */ switch (LittleLong(*(unsigned *)buf)) { case IDALIASHEADER: loadmodel->extradata = Hunk_Begin(0x200000); LoadMD2(mod, buf); break; case IDSPRITEHEADER: loadmodel->extradata = Hunk_Begin(0x10000); LoadSP2(mod, buf); break; case IDBSPHEADER: loadmodel->extradata = Hunk_Begin(0x1000000); Mod_LoadBrushModel(mod, buf); break; default: ri.Sys_Error(ERR_DROP, "Mod_NumForName: unknown fileid for %s", mod->name); break; } loadmodel->extradatasize = Hunk_End(); ri.FS_FreeFile(buf); return mod; }
static void Mod_LoadBrushModel(gl3model_t *mod, void *buffer, int modfilelen) { int i; dheader_t *header; mmodel_t *bm; if (loadmodel != mod_known) { ri.Sys_Error(ERR_DROP, "Loaded a brush model after the world"); } header = (dheader_t *)buffer; i = LittleLong(header->version); if (i != BSPVERSION) { ri.Sys_Error(ERR_DROP, "%s: %s has wrong version number (%i should be %i)", __func__, mod->name, i, BSPVERSION); } /* swap all the lumps */ mod_base = (byte *)header; for (i = 0; i < sizeof(dheader_t) / 4; i++) { ((int *)header)[i] = LittleLong(((int *)header)[i]); } // calculate the needed hunksize from the lumps int hunkSize = 0; hunkSize += calcLumpHunkSize(&header->lumps[LUMP_VERTEXES], sizeof(dvertex_t), sizeof(mvertex_t)); hunkSize += calcLumpHunkSize(&header->lumps[LUMP_EDGES], sizeof(dedge_t), sizeof(medge_t)); hunkSize += sizeof(medge_t) + 31; // for count+1 in Mod_LoadEdges() float surfEdgeCount = header->lumps[LUMP_SURFEDGES].filelen/sizeof(int); if(surfEdgeCount < MAX_MAP_SURFEDGES) // else it errors out later anyway hunkSize += calcLumpHunkSize(&header->lumps[LUMP_SURFEDGES], sizeof(int), sizeof(int)); hunkSize += calcLumpHunkSize(&header->lumps[LUMP_LIGHTING], 1, 1); hunkSize += calcLumpHunkSize(&header->lumps[LUMP_PLANES], sizeof(dplane_t), sizeof(cplane_t)*2); hunkSize += calcTexinfoAndFacesSize(&header->lumps[LUMP_FACES], &header->lumps[LUMP_TEXINFO]); hunkSize += calcLumpHunkSize(&header->lumps[LUMP_LEAFFACES], sizeof(short), sizeof(msurface_t *)); // yes, out is indeeed a pointer! hunkSize += calcLumpHunkSize(&header->lumps[LUMP_VISIBILITY], 1, 1); hunkSize += calcLumpHunkSize(&header->lumps[LUMP_LEAFS], sizeof(dleaf_t), sizeof(mleaf_t)); hunkSize += calcLumpHunkSize(&header->lumps[LUMP_NODES], sizeof(dnode_t), sizeof(mnode_t)); hunkSize += calcLumpHunkSize(&header->lumps[LUMP_MODELS], sizeof(dmodel_t), sizeof(mmodel_t)); loadmodel->extradata = Hunk_Begin(hunkSize); loadmodel->type = mod_brush; /* load into heap */ Mod_LoadVertexes(&header->lumps[LUMP_VERTEXES]); Mod_LoadEdges(&header->lumps[LUMP_EDGES]); Mod_LoadSurfedges(&header->lumps[LUMP_SURFEDGES]); Mod_LoadLighting(&header->lumps[LUMP_LIGHTING]); Mod_LoadPlanes(&header->lumps[LUMP_PLANES]); Mod_LoadTexinfo(&header->lumps[LUMP_TEXINFO]); Mod_LoadFaces(&header->lumps[LUMP_FACES]); Mod_LoadMarksurfaces(&header->lumps[LUMP_LEAFFACES]); Mod_LoadVisibility(&header->lumps[LUMP_VISIBILITY]); Mod_LoadLeafs(&header->lumps[LUMP_LEAFS]); Mod_LoadNodes(&header->lumps[LUMP_NODES]); Mod_LoadSubmodels(&header->lumps[LUMP_MODELS]); mod->numframes = 2; /* regular and alternate animation */ /* set up the submodels */ for (i = 0; i < mod->numsubmodels; i++) { gl3model_t *starmod; bm = &mod->submodels[i]; starmod = &mod_inline[i]; *starmod = *loadmodel; starmod->firstmodelsurface = bm->firstface; starmod->nummodelsurfaces = bm->numfaces; starmod->firstnode = bm->headnode; if (starmod->firstnode >= loadmodel->numnodes) { ri.Sys_Error(ERR_DROP, "%s: Inline model %i has bad firstnode", __func__, i); } VectorCopy(bm->maxs, starmod->maxs); VectorCopy(bm->mins, starmod->mins); starmod->radius = bm->radius; if (i == 0) { *loadmodel = *starmod; } starmod->numleafs = bm->visleafs; } }
void Mod_LoadBrushModel(model_t *mod, void *buffer, int modfilelen) { int i; dheader_t *header; mmodel_t *bm; /* Because Quake II is is sometimes so ... "optimized" this * is going to be somewhat dirty. The map data contains indices * that we're converting into pointers. Yeah. No comments. The * indices are 32 bit long, they just encode the offset between * the hunks base address and the position in the hunk, so 32 bit * pointers should be enough. But let's play save, waste some * allocations and just take the plattforms pointer size instead * of relying on assumptions. */ loadmodel->extradata = Hunk_Begin(modfilelen * sizeof(void*)); loadmodel->type = mod_brush; if (loadmodel != mod_known) { ri.Sys_Error(ERR_DROP, "Loaded a brush model after the world"); } header = (dheader_t *)buffer; i = LittleLong(header->version); if (i != BSPVERSION) { ri.Sys_Error(ERR_DROP, "%s: %s has wrong version number (%i should be %i)", __func__, mod->name, i, BSPVERSION); } /* swap all the lumps */ mod_base = (byte *)header; for (i = 0; i < sizeof(dheader_t) / 4; i++) { ((int *)header)[i] = LittleLong(((int *)header)[i]); } /* load into heap */ Mod_LoadVertexes(&header->lumps[LUMP_VERTEXES]); Mod_LoadEdges(&header->lumps[LUMP_EDGES]); Mod_LoadSurfedges(&header->lumps[LUMP_SURFEDGES]); Mod_LoadLighting(&header->lumps[LUMP_LIGHTING]); Mod_LoadPlanes(&header->lumps[LUMP_PLANES]); Mod_LoadTexinfo(&header->lumps[LUMP_TEXINFO]); Mod_LoadFaces(&header->lumps[LUMP_FACES]); Mod_LoadMarksurfaces(&header->lumps[LUMP_LEAFFACES]); Mod_LoadVisibility(&header->lumps[LUMP_VISIBILITY]); Mod_LoadLeafs(&header->lumps[LUMP_LEAFS]); Mod_LoadNodes(&header->lumps[LUMP_NODES]); Mod_LoadSubmodels(&header->lumps[LUMP_MODELS]); mod->numframes = 2; /* regular and alternate animation */ /* set up the submodels */ for (i = 0; i < mod->numsubmodels; i++) { model_t *starmod; bm = &mod->submodels[i]; starmod = &mod_inline[i]; *starmod = *loadmodel; starmod->firstmodelsurface = bm->firstface; starmod->nummodelsurfaces = bm->numfaces; starmod->firstnode = bm->headnode; if (starmod->firstnode >= loadmodel->numnodes) { ri.Sys_Error(ERR_DROP, "%s: Inline model %i has bad firstnode", __func__, i); } VectorCopy(bm->maxs, starmod->maxs); VectorCopy(bm->mins, starmod->mins); starmod->radius = bm->radius; if (i == 0) { *loadmodel = *starmod; } starmod->numleafs = bm->visleafs; } }
/* ================= 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; }