/* ================== Mod_LoadModel Loads a model into the cache ================== */ model_t *Mod_LoadModel (model_t *mod, qboolean crash) { void *d; unsigned *buf; byte stackbuf[1024]; // avoid dirtying the cache heap if (!mod->needload) { if (mod->type == mod_alias) { d = Cache_Check (&mod->cache); if (d) return mod; } else return mod; // not cached at all } // // because the world is so huge, load it one piece at a time // if (!crash) { } // // load the file // buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf)); if (!buf) { if (crash) Sys_Error ("Mod_NumForName: %s not found", mod->name); return NULL; } // // allocate a new model // COM_FileBase (mod->name, loadname); loadmodel = mod; // // fill it in // // call the apropriate loader mod->needload = false; switch (LittleLong(*(unsigned *)buf)) { case IDPOLYHEADER: Mod_LoadAliasModel (mod, buf); break; case IDSPRITEHEADER: Mod_LoadSpriteModel (mod, buf); break; default: Mod_LoadBrushModel (mod, buf); break; } return mod; }
/* ================== 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; }
/* ================== Mod_ForName Loads in a model for the given name ================== */ model_t *Mod_ForName (char *name, qboolean crash) { model_t *mod; int i; FILE *file; long base; int type; char *extradata; 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_FOpenFile (mod->name, &file); if (modfilelen < 0) { 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; extradata = Hunk_Alloc(&hunk_ref, 0); // // fill it in // base = ftell(file); // call the apropriate loader ri.FS_Read(&type, sizeof(type), file); fseek(file, base, SEEK_SET); switch (LittleLong(type)) { case IDALIASHEADER: Mod_LoadAliasModel (mod, file, base); break; case IDSPRITEHEADER: Mod_LoadSpriteModel (mod, file, base); break; case IDBSPHEADER: Mod_LoadBrushModel (mod, file, base); break; default: ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name); break; } loadmodel->extradatasize = (char *)Hunk_Alloc (&hunk_ref, 0) - extradata; ri.FS_FCloseFile(file); return mod; }
/* ================== Mod_LoadModel Loads a model into the cache ================== */ model_t *Mod_LoadModel (model_t *mod, qboolean crash) { unsigned *buf; // >>> FIX: For Nintendo Wii using devkitPPC / libogc // Deferring allocation. Stack in this device is pretty small: //byte stackbuf[1024]; // avoid dirtying the cache heap byte* stackbuf; // avoid dirtying the cache heap // <<< FIX if (mod->type == mod_alias) { if (Cache_Check (&mod->cache)) { mod->needload = NL_PRESENT; return mod; } } else { if (mod->needload == NL_PRESENT) return mod; } // // because the world is so huge, load it one piece at a time // // // load the file // // >>> FIX: For Nintendo Wii using devkitPPC / libogc // Allocating for previous fixes (and, this time, expanding the allocated size), in big stack: stackbuf = Sys_BigStackAlloc(4096 * sizeof(byte), "Mod_LoadModel"); // <<< FIX // >>> FIX: For Nintendo Wii using devkitPPC / libogc // Adjusting for previous fix: //buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf)); buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, 4096); // <<< FIX if (!buf) { if (crash) Sys_Error ("Mod_NumForName: %s not found", mod->name); // >>> FIX: For Nintendo Wii using devkitPPC / libogc // Deallocating from previous fixes: Sys_BigStackFree(4096 * sizeof(byte), "Mod_LoadModel"); // <<< FIX return NULL; } // // allocate a new model // COM_FileBase (mod->name, loadname); loadmodel = mod; // // fill it in // // call the apropriate loader mod->needload = NL_PRESENT; switch (LittleLong(*(unsigned *)buf)) { case IDPOLYHEADER: Mod_LoadAliasModel (mod, buf); break; case IDSPRITEHEADER: Mod_LoadSpriteModel (mod, buf); break; default: Mod_LoadBrushModel (mod, buf); break; } // >>> FIX: For Nintendo Wii using devkitPPC / libogc // Deallocating from previous fixes: Sys_BigStackFree(4096 * sizeof(byte), "Mod_LoadModel"); // <<< FIX return mod; }
/* ================== 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; }