boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping, void *structptr, char *name, char *value) { deh_mapping_entry_t *entry; void *location; entry = GetMappingEntryByName(context, mapping, name); if (entry == NULL) { return false; } // Sanity check: if (!entry->is_string) { DEH_Error(context, "Tried to set '%s' as string (BUG)", name); return false; } location = GetStructField(structptr, mapping, entry); // Copy value into field: M_StringCopy(location, value, entry->size); return true; }
static void DEH_FrameOverflow(deh_context_t *context, char *varname, int value) { if (!strcasecmp(varname, "Duration")) { weaponinfo[0].ammo = value; } else if (!strcasecmp(varname, "Codep frame")) { weaponinfo[0].upstate = value; } else if (!strcasecmp(varname, "Next frame")) { weaponinfo[0].downstate = value; } else if (!strcasecmp(varname, "Unknown 1")) { weaponinfo[0].readystate = value; } else if (!strcasecmp(varname, "Unknown 2")) { weaponinfo[0].atkstate = value; } else { DEH_Error(context, "Unable to simulate frame overflow: field '%s'", varname); } }
boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping, void *structptr, char *name, int value) { deh_mapping_entry_t *entry; void *location; entry = GetMappingEntryByName(context, mapping, name); if (entry == NULL) { return false; } // Sanity check: if (entry->is_string) { DEH_Error(context, "Tried to set '%s' as integer (BUG)", name); return false; } location = GetStructField(structptr, mapping, entry); // printf("Setting %p::%s to %i (%i bytes)\n", // structptr, name, value, entry->size); // Set field content based on its type: switch (entry->size) { case 1: * ((uint8_t *) location) = value; break; case 2: * ((uint16_t *) location) = value; break; case 4: * ((uint32_t *) location) = value; break; default: DEH_Error(context, "Unknown field type for '%s' (BUG)", name); return false; } return true; }
static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag) { state_t *state; char *variable_name, *value; int ivalue; if (tag == NULL) return; state = (state_t *) tag; // Parse the assignment if (!DEH_ParseAssignment(line, &variable_name, &value)) { // Failed to parse DEH_Warning(context, "Failed to parse assignment"); return; } // all values are integers ivalue = atoi(value); // Action pointer field is a special case: if (!strcasecmp(variable_name, "Action pointer")) { void *func; if (!GetActionPointerForOffset(ivalue, &func)) { SuggestOtherVersions(ivalue); DEH_Error(context, "Unknown action pointer: %i", ivalue); return; } state->action = func; } else { // "Next frame" numbers need to undergo mapping. if (!strcasecmp(variable_name, "Next frame")) { ivalue = DEH_MapHereticFrameNumber(ivalue); } DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue); } }
static void DEH_CheatParseLine(deh_context_t *context, char *line, void *tag) { deh_cheat_t *cheat; char *variable_name; char *value; unsigned char *unsvalue; unsigned int i; if (!DEH_ParseAssignment(line, &variable_name, &value)) { // Failed to parse DEH_Warning(context, "Failed to parse assignment"); return; } unsvalue = (unsigned char *) value; cheat = FindCheatByName(variable_name); if (cheat == NULL) { DEH_Warning(context, "Unknown cheat '%s'", variable_name); return; } // write the value into the cheat sequence i = 0; while (unsvalue[i] != 0 && unsvalue[i] != 0xff) { // If the cheat length exceeds the Vanilla limit, stop. This // does not apply if we have the limit turned off. if (!deh_allow_long_cheats && i >= cheat->seq->sequence_len) { DEH_Warning(context, "Cheat sequence longer than supported by " "Vanilla dehacked"); break; } if (deh_apply_cheats) { cheat->seq->sequence[i] = unsvalue[i]; } ++i; // Absolute limit - don't exceed if (i >= MAX_CHEAT_LEN - cheat->seq->parameter_chars) { DEH_Error(context, "Cheat sequence too long!"); return; } } if (deh_apply_cheats) { cheat->seq->sequence[i] = '\0'; } }
static void DEH_ParseContext(deh_context_t *context) { deh_section_t *current_section = NULL; char section_name[20]; void *tag = NULL; boolean extended; char *line; // Read the header and check it matches the signature if (!CheckSignatures(context)) { DEH_Error(context, "This is not a valid dehacked patch file!"); } // Read the file while (!DEH_HadError(context)) { // Read the next line. We only allow the special extended parsing // for the BEX [STRINGS] section. extended = current_section != NULL && !strcasecmp(current_section->name, "[STRINGS]"); line = DEH_ReadLine(context, extended); // end of file? if (line == NULL) { return; } while (line[0] != '\0' && isspace(line[0])) ++line; if (line[0] == '#') { // comment DEH_ParseComment(line); continue; } if (IsWhitespace(line)) { if (current_section != NULL) { // end of section if (current_section->end != NULL) { current_section->end(context, tag); } //printf("end %s tag\n", current_section->name); current_section = NULL; } } else { if (current_section != NULL) { // parse this line current_section->line_parser(context, line, tag); } else { // possibly the start of a new section sscanf(line, "%19s", section_name); current_section = GetSectionByName(section_name); if (current_section != NULL) { tag = current_section->start(context, line); //printf("started %s tag\n", section_name); } else { //printf("unknown section name %s\n", section_name); } } } } }
static void *DEH_TextStart(deh_context_t *context, char *line) { char *repl_text; char *orig_text; int orig_offset, repl_len; int i; if (sscanf(line, "Text %i %i", &orig_offset, &repl_len) != 2) { DEH_Warning(context, "Parse error on section start"); return NULL; } repl_text = malloc(repl_len + 1); // read in the "to" text for (i=0; i<repl_len; ++i) { int c; c = DEH_GetChar(context); repl_text[i] = c; } repl_text[repl_len] = '\0'; // We don't support all strings, but at least recognise them: if (StringIsUnsupported(orig_offset)) { DEH_Warning(context, "Unsupported string replacement: %i", orig_offset); } // Find the string to replace: else if (!GetStringByOffset(orig_offset, &orig_text)) { SuggestOtherVersions(orig_offset); DEH_Error(context, "Unknown string offset: %i", orig_offset); } // Only allow string replacements that are possible in Vanilla Doom. // Chocolate Doom is unforgiving! else if (!deh_allow_long_strings && repl_len > MaxStringLength(strlen(orig_text))) { DEH_Error(context, "Replacement string is longer than the maximum " "possible in heretic.exe"); } else { // Success. DEH_AddStringReplacement(orig_text, repl_text); } // We must always free the replacement text. free(repl_text); return NULL; }