opcode_t * opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_t *op_c) { opcode_t search_op; opcode_t *op; opcode_t *sop; void **op_list; int i; search_op.name = name; search_op.type_a = op_a ? op_a->type : ev_invalid; search_op.type_b = op_b ? op_b->type : ev_invalid; search_op.type_c = op_c ? op_c->type : ev_invalid; op = Hash_FindElement (opcode_type_table, &search_op); if (op) return op; op_list = Hash_FindList (opcode_void_table, name); if (!op_list) return op; for (i = 0; !op && op_list[i]; i++) { sop = op_list[i]; if (check_operand_type (sop->type_a, search_op.type_a) && check_operand_type (sop->type_b, search_op.type_b) && check_operand_type (sop->type_c, search_op.type_c)) op = sop; } free (op_list); return op; }
lumpinfo_t * wad_find_lump (wad_t *wad, const char *lumpname) { lumpinfo_t dummy; strncpy (dummy.name, lumpname, 16); dummy.name[15] = 0; return Hash_FindElement (wad->lump_hash, &dummy); }
dfunction_t * func_find (int st_ofs) { dfunction_t f; f.first_statement = st_ofs; return Hash_FindElement (func_tab, &f); }
int wad_add (wad_t *wad, const char *filename, const char *lumpname, byte type) { lumpinfo_t *pf; lumpinfo_t dummy; QFile *file; char buffer[16384]; int bytes; strncpy (dummy.name, lumpname, 16); dummy.name[15] = 0; pf = Hash_FindElement (wad->lump_hash, &dummy); if (pf) return -1; if (wad->numlumps == wad->lumps_size) { lumpinfo_t *f; wad->lumps_size += 64; f = realloc (wad->lumps, wad->lumps_size * sizeof (lumpinfo_t)); if (!f) return -1; wad->lumps = f; } file = Qopen (filename, "rb"); if (!file) return -1; wad->modified = 1; pf = &wad->lumps[wad->numlumps++]; strncpy (pf->name, lumpname, sizeof (pf->name)); pf->name[sizeof (pf->name) - 1] = 0; Qseek (wad->handle, 0, SEEK_END); pf->filepos = Qtell (wad->handle); pf->type = type; pf->size = 0; while ((bytes = Qread (file, buffer, sizeof (buffer)))) { Qwrite (wad->handle, buffer, bytes); pf->size += bytes; } Qclose (file); if (wad->pad && pf->size & 3) { static char buf[4]; Qwrite (wad->handle, buf, 4 - (pf->size & 3)); } Hash_AddElement (wad->lump_hash, pf); return 0; }
static ex_value_t * find_value (const ex_value_t *val) { ex_value_t *value; value = Hash_FindElement (value_table, val); if (value) return value; value = new_value (); *value = *val; Hash_AddElement (value_table, value); return value; }
int wad_add_data (wad_t *wad, const char *lumpname, byte type, const void *data, int bytes) { lumpinfo_t *pf; lumpinfo_t dummy; strncpy (dummy.name, lumpname, 16); dummy.name[15] = 0; pf = Hash_FindElement (wad->lump_hash, &dummy); if (pf) return -1; if (wad->numlumps == wad->lumps_size) { lumpinfo_t *f; wad->lumps_size += 64; f = realloc (wad->lumps, wad->lumps_size * sizeof (lumpinfo_t)); if (!f) return -1; wad->lumps = f; } wad->modified = 1; pf = &wad->lumps[wad->numlumps++]; strncpy (pf->name, lumpname, sizeof (pf->name)); pf->name[sizeof (pf->name) - 1] = 0; Qseek (wad->handle, 0, SEEK_END); pf->filepos = Qtell (wad->handle); pf->type = type; pf->size = bytes; Qwrite (wad->handle, data, bytes); if (wad->pad && pf->size & 3) { static char buf[4]; Qwrite (wad->handle, buf, 4 - (pf->size & 3)); } Hash_AddElement (wad->lump_hash, pf); return 0; }
iqmblend_t * Mod_IQMBuildBlendPalette (iqm_t *iqm, int *size) { int i, j; iqmvertexarray *bindices = 0; iqmvertexarray *bweights = 0; iqmblend_t *blend_list; int num_blends; hashtab_t *blend_hash; for (i = 0; i < iqm->num_arrays; i++) { if (iqm->vertexarrays[i].type == IQM_BLENDINDEXES) bindices = &iqm->vertexarrays[i]; if (iqm->vertexarrays[i].type == IQM_BLENDWEIGHTS) bweights = &iqm->vertexarrays[i]; } if (!bindices || !bweights) { // Not necessarily an error: might be a static model with no bones // Either way, no need to make a blend palette Sys_MaskPrintf (SYS_MODEL, "bone index or weight array missing\n"); *size = 0; return 0; } blend_list = calloc (MAX_BLENDS, sizeof (iqmblend_t)); for (i = 0; i < iqm->num_joints; i++) { blend_list[i].indices[0] = i; blend_list[i].weights[0] = 255; } num_blends = iqm->num_joints; blend_hash = Hash_NewTable (1023, 0, 0, 0); Hash_SetHashCompare (blend_hash, blend_get_hash, blend_compare); for (i = 0; i < iqm->num_verts; i++) { byte *vert = iqm->vertices + i * iqm->stride; byte *bi = vert + bindices->offset; byte *bw = vert + bweights->offset; iqmblend_t blend; iqmblend_t *bl; // First, canonicalize vextex bone data: // bone indices are in increasing order // bone weight of zero is never followed by a non-zero weight // bone weight of zero has bone index of zero // if the weight is zero, ensure the index is also zero // also, ensure non-zero weights never follow zero weights for (j = 0; j < 4; j++) { if (!bw[j]) { bi[j] = 0; } else { if (j && !bw[j-1]) { swap_bones (bi, bw, j - 1, j); j = 0; // force a rescan } } } // sort the bones such that the indeces are increasing (unless the // weight is zero) for (j = 0; j < 3; j++) { if (!bw[j+1]) // zero weight == end of list break; if (bi[j] > bi[j+1]) { swap_bones (bi, bw, j, j + 1); j = -1; // force rescan } } // Now that the bone data is canonical, it can be hashed. // However, no need to check other combinations if the vertex has // only one influencing bone: the bone index will only change format. if (!bw[1]) { *(uint32_t *) bi = bi[0]; continue; } QuatCopy (bi, blend.indices); QuatCopy (bw, blend.weights); if ((bl = Hash_FindElement (blend_hash, &blend))) { *(uint32_t *) bi = (bl - blend_list); continue; } if (num_blends >= MAX_BLENDS) Sys_Error ("Too many blends. Tell taniwha to stop being lazy."); blend_list[num_blends] = blend; Hash_AddElement (blend_hash, &blend_list[num_blends]); *(uint32_t *) bi = num_blends; num_blends++; } Hash_DelTable (blend_hash); *size = num_blends; return realloc (blend_list, num_blends * sizeof (iqmblend_t)); }