// // D_OpenDiskFile // // Opens and reads a disk file. // diskfile_t *D_OpenDiskFile(const char *filename) { diskfile_t *df; diskfileint_t *dfi; uint32_t temp; // allocate a diskfile structure and internal fields df = estructalloc(diskfile_t, 1); dfi = estructalloc(diskfileint_t, 1); df->opaque = dfi; // open the physical file if(!(dfi->f = fopen(filename, "rb"))) I_Error("D_OpenDiskFile: couldn't open file %s\n", filename); // read number of files in the directory if(fread(&temp, sizeof(temp), 1, dfi->f) < 1) I_Error("D_OpenDiskFile: couldn't read number of entries\n"); // make big-endian file value host-endian dfi->numfiles = SwapBigULong(temp); // allocate directory dfi->entries = estructalloc(diskentry_t, dfi->numfiles); // read directory entries if(!D_readDiskFileDirectory(dfi)) I_Error("D_OpenDiskFile: failed reading directory\n"); return df; }
// // PushRange // // Pushes the current palette translation range into the parser state object's // list of ranges. // static void PushRange(tr_pstate_t *pstate) { tr_range_t *newrange = estructalloc(tr_range_t, 1); newrange->srcbegin = eclamp(pstate->srcbegin, 0, 255); newrange->srcend = eclamp(pstate->srcend, 0, 255); newrange->dstbegin = eclamp(pstate->dstbegin, 0, 255); newrange->dstend = eclamp(pstate->dstend, 0, 255); // normalize ranges if(newrange->srcbegin > newrange->srcend) { int temp = newrange->srcbegin; newrange->srcbegin = newrange->srcend; newrange->srcend = temp; } if(newrange->dstbegin > newrange->dstend) { int temp = newrange->dstbegin; newrange->dstbegin = newrange->dstend; newrange->dstend = temp; } newrange->next = pstate->ranges; pstate->ranges = newrange; };
// // W_FindAllMapsInLevelWad // // haleyjd 10/23/10: Finds all valid maps in a wad directory and returns them // as a sorted set of wadlevel_t's. // wadlevel_t *W_FindAllMapsInLevelWad(WadDirectory *dir) { int i, format; wadlevel_t *levels = NULL; int numlevels; int numlevelsalloc; int numlumps = dir->getNumLumps(); lumpinfo_t **lumpinfo = dir->getLumpInfo(); // start out with a small set of levels numlevels = 0; numlevelsalloc = 8; levels = estructalloc(wadlevel_t, numlevelsalloc); // find all the lumps for(i = 0; i < numlumps; i++) { if((format = P_CheckLevel(dir, i)) != LEVEL_FORMAT_INVALID) { // grow the array if needed, leaving one at the end if(numlevels + 1 >= numlevelsalloc) { numlevelsalloc *= 2; levels = erealloc(wadlevel_t *, levels, numlevelsalloc * sizeof(wadlevel_t)); } memset(&levels[numlevels], 0, sizeof(wadlevel_t)); levels[numlevels].dir = dir; levels[numlevels].lumpnum = i; strncpy(levels[numlevels].header, lumpinfo[i]->name, 9); ++numlevels; // skip past the level's directory entries i += (format == LEVEL_FORMAT_HEXEN ? 11 : 10); } }
// // P_AddActiveCeiling() // // Adds a ceiling to the head of the list of active ceilings // // Passed the ceiling motion structure // Returns nothing // void P_AddActiveCeiling(CeilingThinker *ceiling) { // ioanch 20160306 if(demo_compatibility || P_LevelIsVanillaHexen()) { for(int i = 0; i < vanilla_MAXCEILINGS; ++i) { if(!vanilla_activeceilings[i]) { vanilla_activeceilings[i] = ceiling; break; } } return; } // ioanch: normal setup ceilinglist_t *list = estructalloc(ceilinglist_t, 1); list->ceiling = ceiling; ceiling->list = list; if((list->next = activeceilings)) list->next->prev = &list->next; list->prev = &activeceilings; activeceilings = list; }
// // Adds a scroll thinker to the list // void ScrollThinker::addScroller() { list = estructalloc(scrollerlist_t, 1); list->scroller = this; if((list->next = scrollers)) list->next->prev = &list->next; list->prev = &scrollers; scrollers = list; }
// // E_CreateString // // Creates an EDF string object with the given value which is hashable // by one or two different keys. The mnemonic key is required and must // be 128 or fewer characters long. The numeric key is optional. If a // negative value is passed as the numeric key, the object will not be // added to the numeric hash table. // edf_string_t *E_CreateString(const char *value, const char *key, int num) { int keyval; edf_string_t *newStr; if((newStr = E_StringForName(key))) { // Modify existing object. E_ReplaceString(newStr->string, estrdup(value)); // Modify numeric id and rehash object if necessary if(num != newStr->numkey) { // If old key is >= 0, must remove from hash first if(newStr->numkey >= 0) E_DelStringFromNumHash(newStr); // Set new key newStr->numkey = num; // If new key >= 0, add back to hash if(newStr->numkey >= 0) E_AddStringToNumHash(newStr); } } else { // Create a new string object newStr = estructalloc(edf_string_t, 1); // copy keys into string object if(strlen(key) >= sizeof(newStr->key)) { E_EDFLoggedErr(2, "E_CreateString: invalid string mnemonic '%s'\n", key); } strncpy(newStr->key, key, sizeof(newStr->key)); newStr->numkey = num; // duplicate value newStr->string = estrdup(value); // add to hash tables keyval = D_HashTableKey(newStr->key) % NUM_EDFSTR_CHAINS; newStr->next = edf_str_chains[keyval]; edf_str_chains[keyval] = newStr; // numeric key is not required if(num >= 0) E_AddStringToNumHash(newStr); } return newStr; }
// // G_CreateAxisActionVars // // Build console variables for all axis action bindings. // void G_CreateAxisActionVars() { for(int i = 0; i < HALGamePad::MAXAXES; i++) { qstring name; variable_t *variable; command_t *command; variable = estructalloc(variable_t, 1); variable->variable = &axisActions[i]; variable->v_default = NULL; variable->type = vt_int; variable->min = axis_none; variable->max = axis_max - 1; variable->defines = axisActionNames; command = estructalloc(command_t, 1); name << "g_axisaction" << i+1; command->name = name.duplicate(); command->type = ct_variable; command->variable = variable; C_AddCommand(command); variable = estructalloc(variable_t, 1); variable->variable = &axisOrientation[i]; variable->v_default = NULL; variable->type = vt_int; variable->min = -1; variable->max = 1; command = estructalloc(command_t, 1); name.clear() << "g_axisorientation" << i+1; command->name = name.duplicate(); command->type = ct_variable; command->variable = variable; C_AddCommand(command); } }
// // E_CollectInventory // // Pre-creates and hashes by name the inventory definitions, for purpose // of mutual and forward references. // void E_CollectInventory(cfg_t *cfg) { static int currentID = 1; unsigned int i; unsigned int numInventory; // number of inventory defs defined by the cfg inventory_t *newInvDefs = NULL; // get number of inventory definitions defined by the cfg numInventory = cfg_size(cfg, EDF_SEC_INVENTORY); // echo counts E_EDFLogPrintf("\t\t%u inventory items defined\n", numInventory); if(numInventory) { // allocate inventory structures for the new thingtypes newInvDefs = estructalloc(inventory_t, numInventory); numInventoryDefs += numInventory; // create metatables for(i = 0; i < numInventory; i++) newInvDefs[i].meta = new MetaTable("inventory"); } // build hash tables E_EDFLogPuts("\t\tBuilding inventory hash tables\n"); // cycle through the thingtypes defined in the cfg for(i = 0; i < numInventory; i++) { cfg_t *invcfg = cfg_getnsec(cfg, EDF_SEC_INVENTORY, i); const char *name = cfg_title(invcfg); // This is a new inventory, whether or not one already exists by this name // in the hash table. For subsequent addition of EDF inventory defs at // runtime, the hash table semantics of "find newest first" take care of // overriding, while not breaking objects that depend on the original // definition of the inventory type for inheritance purposes. inventory_t *inv = &newInvDefs[i]; // initialize name inv->name = estrdup(name); // add to name hash inv_namehash.addObject(inv); // create ID number and add to hash table inv->numkey = currentID++; inv_numhash.addObject(inv); } }
// // INStatsManager::addScore // // Add a new score to the table. // void INStatsManager::addScore(const char *levelkey, int score, int maxscore, int scoretype, int pnum) { in_stat_t *newStat = estructalloc(in_stat_t, 1); newStat->levelkey = estrdup(levelkey); newStat->value = score; newStat->maxValue = maxscore; newStat->recordType = scoretype; newStat->skill = gameskill; newStat->playername = estrdup(players[pnum].name); pImpl->statsByLevelKey.addObject(newStat); }
// // R_GetFreePolyNode // // Gets a node from the free list or allocates a new one. // static rpolynode_t *R_GetFreePolyNode() { rpolynode_t *ret = NULL; if(polyNodeFreeList) { ret = polyNodeFreeList; polyNodeFreeList = polyNodeFreeList->children[0]; memset(ret, 0, sizeof(*ret)); } else ret = estructalloc(rpolynode_t, 1); return ret; }
// // I_AddDeferredEvent // // haleyjd 03/06/13: Some received input events need to be deferred until at // least one tic has passed before they are posted to the event queue. // "Trigger" style keys such as mousewheel up and down are the chief offenders. // Rather than shoehorning a bunch of code for this into I_GetEvent, it is // now handled here uniformly for all event types. // static void I_AddDeferredEvent(const event_t &ev, int tic) { deferredevent_t *de; if(i_deferredfreelist.head) { de = *i_deferredfreelist.head; i_deferredfreelist.remove(de); } else de = estructalloc(deferredevent_t, 1); de->ev = ev; de->tic = tic; i_deferredevents.insert(de); }
// // WadDirectory::reAllocLumpInfo // // Reallocate the lumpinfo array to contain the indicated number of pointers, // and, if makelumps is true, will also allocate that number of new lumpinfo_t // structures and return them. // lumpinfo_t *WadDirectory::reAllocLumpInfo(int numnew, int startlump) { lumpinfo_t *newlumps = NULL; numlumps += numnew; // Fill in lumpinfo lumpinfo = erealloc(lumpinfo_t **, lumpinfo, numlumps * sizeof(lumpinfo_t *)); // space for new lumps newlumps = estructalloc(lumpinfo_t, numlumps - startlump); // haleyjd: keep track of this allocation of lumps addInfoPtr(newlumps); // haleyjd: fill in new pointers here, instead of everywhere this is used. for(int i = startlump; i < numlumps; i++) lumpinfo[i] = newlumps + (i - startlump); return newlumps; }
// // MetaKey // // If the given key string is already interned, the metakey_t structure that // stores it will be returned. If not, it will be added to the collection of // keys and hashed by name. // static metakey_t &MetaKey(const char *key) { metakey_t *keyObj; unsigned int unmodHC = ENCStringHashKey::HashCode(key); // Do we already have this key? if(!(keyObj = metaKeyHash.objectForKey(key, unmodHC))) { keyObj = estructalloc(metakey_t, 1); // add it to the list metaKeys.add(keyObj); keyObj->key = estrdup(key); keyObj->index = metaKeys.getLength() - 1; keyObj->unmodHC = unmodHC; // check for table overload, and hash it MetaHashRebuild<>(metaKeyHash); metaKeyHash.addObject(keyObj, keyObj->unmodHC); } return *keyObj; }
// // INStatsMgrPimpl::parseCSVScores // // Parse the CSV input file used to save top scores. // void INStatsMgrPimpl::parseCSVScores(char *input) { Collection<qstring> fields; // Go past the first line of input, which consists of column headers while(*input && *input != '\n') ++input; // Parse each remaining line while(*input) { parseCSVLine(input, fields); if(fields.getLength() >= FIELD_NUMFIELDS) { int recordType = E_StrToNumLinear(recordTypeNames, INSTAT_NUMTYPES, fields[FIELD_RECORDTYPE].constPtr()); if(recordType < INSTAT_NUMTYPES) { in_stat_t *newStats = estructalloc(in_stat_t, 1); newStats->levelkey = fields[FIELD_LEVELKEY ].duplicate(PU_STATIC); newStats->playername = fields[FIELD_PLAYERNAME].duplicate(PU_STATIC); newStats->skill = fields[FIELD_SKILL ].toInt(); newStats->value = fields[FIELD_VALUE ].toInt(); newStats->maxValue = fields[FIELD_MAXVALUE ].toInt(); newStats->recordType = recordType; // add to hash tables statsByLevelKey.addObject(newStats); } } } }
// // E_ProcessCast // // Creates the DOOM II cast call information // static void E_ProcessCast(cfg_t *cfg) { static bool firsttime = true; int i, numcastorder = 0, numcastsections = 0; cfg_t **ci_order; E_EDFLogPuts("\t* Processing cast call\n"); // get number of cast sections numcastsections = cfg_size(cfg, SEC_CAST); if(firsttime && !numcastsections) // on main parse, at least one is required. E_EDFLoggedErr(2, "E_ProcessCast: no cast members defined.\n"); firsttime = false; E_EDFLogPrintf("\t\t%d cast member(s) defined\n", numcastsections); // haleyjd 11/21/11: allow multiple runs if(castorder) { int i; // free names for(i = 0; i < max_castorder; i++) { if(castorder[i].name) efree(castorder[i].name); } // free castorder efree(castorder); castorder = NULL; max_castorder = 0; } // check if the "castorder" array is defined for imposing an // order on the castinfo sections numcastorder = cfg_size(cfg, SEC_CASTORDER); E_EDFLogPrintf("\t\t%d cast member(s) in castorder\n", numcastorder); // determine size of castorder max_castorder = (numcastorder > 0) ? numcastorder : numcastsections; // allocate with size+1 for an end marker castorder = estructalloc(castinfo_t, max_castorder + 1); ci_order = ecalloc(cfg_t **, sizeof(cfg_t *), max_castorder); if(numcastorder > 0) { for(i = 0; i < numcastorder; ++i) { const char *title = cfg_getnstr(cfg, SEC_CASTORDER, i); cfg_t *section = cfg_gettsec(cfg, SEC_CAST, title); if(!section) { E_EDFLoggedErr(2, "E_ProcessCast: unknown cast member '%s' in castorder\n", title); } ci_order[i] = section; } } else { // no castorder array is defined, so use the cast members // in the order they are encountered (for backward compatibility) for(i = 0; i < numcastsections; ++i) ci_order[i] = cfg_getnsec(cfg, SEC_CAST, i); } for(i = 0; i < max_castorder; ++i) { int j; const char *tempstr; int tempint = 0; cfg_t *castsec = ci_order[i]; // resolve thing type tempstr = cfg_getstr(castsec, ITEM_CAST_TYPE); if(!tempstr || (tempint = E_ThingNumForName(tempstr)) == -1) { E_EDFLoggedWarning(2, "Warning: cast %d: unknown thing type %s\n", i, tempstr); tempint = UnknownThingType; } castorder[i].type = tempint; // get cast name, if any -- the first seventeen entries can // default to using the internal string editable via BEX strings tempstr = cfg_getstr(castsec, ITEM_CAST_NAME); if(cfg_size(castsec, ITEM_CAST_NAME) == 0 && i < 17) castorder[i].name = NULL; // set from DeHackEd else castorder[i].name = estrdup(tempstr); // store provided value // get stopattack flag (used by player) castorder[i].stopattack = cfg_getbool(castsec, ITEM_CAST_SA); // process sound blocks (up to four will be processed) tempint = cfg_size(castsec, ITEM_CAST_SOUND); for(j = 0; j < 4; ++j) { castorder[i].sounds[j].frame = 0; castorder[i].sounds[j].sound = 0; } for(j = 0; j < tempint && j < 4; ++j) { int num; sfxinfo_t *sfx; const char *name; cfg_t *soundsec = cfg_getnsec(castsec, ITEM_CAST_SOUND, j); // if these are invalid, just fill them with zero rather // than causing an error, as they're very unimportant // name of sound to play name = cfg_getstr(soundsec, ITEM_CAST_SOUNDNAME); // haleyjd 03/22/06: modified to support dehnum auto-allocation if((sfx = E_EDFSoundForName(name)) == NULL) { E_EDFLoggedWarning(2, "Warning: cast member references invalid sound %s\n", name); castorder[i].sounds[j].sound = 0; } else { if(sfx->dehackednum != -1 || E_AutoAllocSoundDEHNum(sfx)) castorder[i].sounds[j].sound = sfx->dehackednum; else { E_EDFLoggedWarning(2, "Warning: could not auto-allocate a DeHackEd number " "for sound %s\n", name); castorder[i].sounds[j].sound = 0; } } // name of frame that triggers sound event name = cfg_getstr(soundsec, ITEM_CAST_SOUNDFRAME); if((num = E_StateNumForName(name)) < 0) num = 0; castorder[i].sounds[j].frame = num; } } // initialize the end marker to all zeroes memset(&castorder[max_castorder], 0, sizeof(castinfo_t)); // free the ci_order table efree(ci_order); }
// // G_KeyActionForName // // Obtain a keyaction from its name // static keyaction_t *G_KeyActionForName(const char *name) { static int cons_actionnum = NUMKEYACTIONS; keyaction_t *prev, *temp, *newaction; // sequential search // this is only called every now and then for(keyaction_t &keyaction : keyactions) { if(!keyaction.name) continue; if(!strcasecmp(name, keyaction.name)) return &keyaction; } // check console keyactions // haleyjd: TOTALLY rewritten to use linked list if(cons_keyactions) { temp = cons_keyactions; while(temp) { if(!strcasecmp(name, temp->name)) return temp; temp = temp->next; } } else { // first time only - cons_keyactions was NULL cons_keyactions = estructalloc(keyaction_t, 1); cons_keyactions->bclass = kac_cmd; cons_keyactions->type = at_conscmd; cons_keyactions->name = Z_Strdup(name, PU_STATIC, 0); cons_keyactions->next = nullptr; cons_keyactions->num = cons_actionnum++; return cons_keyactions; } // not in list -- add prev = nullptr; temp = cons_keyactions; while(temp) { prev = temp; temp = temp->next; } newaction = estructalloc(keyaction_t, 1); newaction->bclass = kac_cmd; newaction->type = at_conscmd; newaction->name = Z_Strdup(name, PU_STATIC, 0); newaction->next = nullptr; newaction->num = cons_actionnum++; if(prev) prev->next = newaction; return newaction; }