/// <summary> /// Creates a new enum or bitmask type definition in the current code object. /// </summary> /// <param name="codeScope">Code scope of the enum for ensuring each flag option is unique.</param> /// <param name="field">Enum definition from Guerilla.</param> public void AddEnumOrBitmask(MutationCodeScope codeScope, enum_definition field) { // Determine the underlying type for the enum based on the field type. Type fieldType = ValueTypeDictionary[field.type]; // Create the enum field by creating a new CodeTypeDeclaration. CodeTypeDeclaration @enum = new CodeTypeDeclaration(codeScope.Namespace); @enum.IsEnum = true; @enum.BaseTypes.Add(fieldType); // Check if this field is a bitmask and if so add the Flags attribute. if (codeScope.Type == MutationCodeScopeType.Bitmask) { // Setup a code attribute declaration object for the Flags attribute. CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(new CodeTypeReference(typeof(FlagsAttribute).Name)); @enum.CustomAttributes.Add(attribute); } // Loop through all of the enum options and add each one to the enum field. for (int i = 0; i < field.option_count; i++) { // Check if the option name is valid and if not skip it. if (field.options[i] == string.Empty) { continue; } // Create a code safe field name for the enum option. string displayName, units, tooltip; EditorMarkUpFlags markupFlags; string optionName = codeScope.CreateCodeSafeFieldName(field_type._field_enum_option, field.options[i], out displayName, out units, out tooltip, out markupFlags); // Create a new CodeMemberField for the enum option. CodeMemberField option = new CodeMemberField { Name = optionName, // Set the flag value accordingly. InitExpression = new CodeSnippetExpression(string.Format("0x{0}", (codeScope.Type == MutationCodeScopeType.Bitmask ? (1 << i) : i).ToString("x"))), }; // Create a new UI markup attribute and add it to the enum option. option.CustomAttributes.Add(EditorMarkUpAttribute.CreateAttributeDeclaration(flags: markupFlags, displayName: displayName, unitsSpecifier: units, tooltipText: tooltip)); // Add the option to the enum. @enum.Members.Add(option); } // Add the enum to the class definition. this.CodeClass.Members.Add(@enum); }
private void ReadTagBlockDefinition(int address, bool isSound, TagBlockDefinition parent) { // Check if this tag_block_definition has already been read. if (this.TagBlockDefinitions.ContainsKey(address) == true) { //// Check if this definition has a parent and if so add a reference to it. //if (parent != null) //{ // // Add the parent defintion as a reference. // this.TagBlockDefinitions[address].AddReference(parent); //} // Don't process the tag block. return; } // Seek to the definition address. this.reader.BaseStream.Position = address - Guerilla.BaseAddress; // Initialize and read the tag_block_definition struct. TagBlockDefinition tagBlockDef = new TagBlockDefinition(); tagBlockDef.s_tag_block_definition.address = address; tagBlockDef.s_tag_block_definition.Read(h2LangLib, reader); // Special case tags may need the field set addresses adjusted. if (isSound == true) { tagBlockDef.s_tag_block_definition.field_sets_address = 0;// 0x906178; tagBlockDef.s_tag_block_definition.field_set_count = 6; tagBlockDef.s_tag_block_definition.field_set_latest_address = 0x906178; } // Initialize the tag field set arrays. tagBlockDef.TagFieldSets = new tag_field_set[tagBlockDef.s_tag_block_definition.field_set_count]; tagBlockDef.TagFields = new List <tag_field> [tagBlockDef.s_tag_block_definition.field_set_count]; //// Check if this definition has a parent and if so add a reference to it. //if (parent != null) //{ // // Add the parent defintion as a reference. // tagBlockDef.AddReference(parent); //} // Add the tag block definition to the dictionary. this.TagBlockDefinitions.Add(address, tagBlockDef); // Loop through all the tag_field_set's and read each one. for (int i = 0; i < tagBlockDef.s_tag_block_definition.field_set_count; i++) { // Special case tags may need the field set addresses adjusted. if (isSound == true) { // Initialize the field set. tagBlockDef.TagFieldSets[i] = new tag_field_set(); // Manuall fill in the information. if (i == 0) { // Seek to the tag_field_set definition address. reader.BaseStream.Position = 0x957A60 - Guerilla.BaseAddress; tagBlockDef.TagFieldSets[i].Read(h2LangLib, reader); } else if (i == 1 || i == 2 || i == 3) // 2 & 3 { // Seek to the tag_field_set definition address. reader.BaseStream.Position = 0x957448 - Guerilla.BaseAddress; tagBlockDef.TagFieldSets[i].Read(h2LangLib, reader); } else if (i == 4) // 4 { tagBlockDef.TagFieldSets[i].version.fields_address = 0x906078; tagBlockDef.TagFieldSets[i].version.index = 0; tagBlockDef.TagFieldSets[i].version.upgrade_proc = 0x49F700; tagBlockDef.TagFieldSets[i].version.size_of = -1; tagBlockDef.TagFieldSets[i].size = 176; tagBlockDef.TagFieldSets[i].alignment_bit = 0; tagBlockDef.TagFieldSets[i].parent_version_index = -1; tagBlockDef.TagFieldSets[i].fields_address = 0x906078; tagBlockDef.TagFieldSets[i].size_string = "sizeof(struct sound_definition_v1)"; } else if (i == 5) // 5 { tagBlockDef.TagFieldSets[i].version.fields_address = 0x906178; tagBlockDef.TagFieldSets[i].version.index = 0; tagBlockDef.TagFieldSets[i].version.upgrade_proc = 0; tagBlockDef.TagFieldSets[i].version.size_of = -1; tagBlockDef.TagFieldSets[i].size = 172; tagBlockDef.TagFieldSets[i].alignment_bit = 0; tagBlockDef.TagFieldSets[i].parent_version_index = -1; tagBlockDef.TagFieldSets[i].fields_address = 0x906178; tagBlockDef.TagFieldSets[i].size_string = "sizeof(sound_definition)"; } } else { // Seek to the tag_field_set definition address. reader.BaseStream.Position = tagBlockDef.s_tag_block_definition.field_sets_address + (i * 76) - Guerilla.BaseAddress; // Initialize and read the tag_field_set struct. tagBlockDef.TagFieldSets[i] = new tag_field_set(); tagBlockDef.TagFieldSets[i].Read(h2LangLib, reader); } // Check if this is the latest tag field set. if (tagBlockDef.s_tag_block_definition.field_set_latest_address == tagBlockDef.TagFieldSets[i].address) { tagBlockDef.TagFieldSetLatestIndex = i; } // Initialize the tag field list. tagBlockDef.TagFields[i] = new List <tag_field>(); // Seek to the tag field set address. this.reader.BaseStream.Position = tagBlockDef.TagFieldSets[i].fields_address - Guerilla.BaseAddress; // Loop through all the tag fields and read each one. tag_field field = new tag_field(); do { // Save the current address. long currentAddress = this.reader.BaseStream.Position; // Read the field type from the stream. field_type fieldType = (field_type)this.reader.ReadInt16(); // Create the field type accordingly. switch (fieldType) { case field_type._field_tag_reference: field = new tag_reference_definition(); break; case field_type._field_struct: field = new tag_struct_definition(); break; case field_type._field_data: field = new tag_data_definition(); break; case field_type._field_byte_flags: case field_type._field_long_flags: case field_type._field_word_flags: case field_type._field_char_enum: case field_type._field_enum: case field_type._field_long_enum: field = new enum_definition(); break; case field_type._field_char_block_index2: case field_type._field_short_block_index2: case field_type._field_long_block_index2: field = new block_index_custom_search_definition(); break; case field_type._field_explanation: field = new explaination_definition(); break; default: field = new tag_field(); break; } // Read the tag field from the stream. this.reader.BaseStream.Position = currentAddress; field.Read(h2LangLib, reader); // Add the field to the list. tagBlockDef.TagFields[i].Add(field); // Read any tag_block definitions. switch (field.type) { case field_type._field_byte_block_flags: case field_type._field_word_block_flags: case field_type._field_long_block_flags: case field_type._field_char_integer: case field_type._field_short_integer: case field_type._field_long_integer: case field_type._field_block: { // Check if the definition address is valid. if (field.definition_address != 0) { ReadTagBlockDefinition(field.definition_address, false, tagBlockDef); } break; } case field_type._field_struct: { ReadTagBlockDefinition(((tag_struct_definition)field).block_definition_address, false, tagBlockDef); break; } } // Seek to the next tag_field. this.reader.BaseStream.Position = currentAddress + 16; //sizeof(tag_field) }while (field.type != field_type._field_terminator); } }
private void ProcessFields(List <tag_field> fields, GuerillaReader reader, MutationCodeCreator blockCodeCreator, MutationCodeScope blockCodeScope, MutationCodeScope parentScope) { // Loop through all of the fields in the collection. for (int i = 0; i < fields.Count; i++) { // Create a new field and add it to the scope for this block. string displayName, units, tooltip; EditorMarkUpFlags markupFlags; string fieldName = blockCodeScope.CreateCodeSafeFieldName(fields[i].type, fields[i].Name, out displayName, out units, out tooltip, out markupFlags); // Create an attribute collection for any attributes we might add to the field. CodeAttributeDeclarationCollection attributeCollection = new CodeAttributeDeclarationCollection(); // Make sure at least one of the required fields for a UI markup attribute is valid. if (markupFlags != EditorMarkUpFlags.None || displayName != string.Empty || units != string.Empty || tooltip != string.Empty) { // Create the UI markup attribute using the information provided. attributeCollection.Add(EditorMarkUpAttribute.CreateAttributeDeclaration(flags: markupFlags, displayName: displayName, unitsSpecifier: units, tooltipText: tooltip)); } // Handle each field accordingly. switch (fields[i].type) { case field_type._field_char_enum: case field_type._field_enum: case field_type._field_long_enum: { // Cast the field to a enum_definition struct. enum_definition enumDefinition = (enum_definition)fields[i]; // Check if there is an existing code scope for this enum type. MutationCodeScope enumScope = blockCodeScope.FindExistingCodeScope(enumDefinition.definition_address); if (enumScope == null) { // Create a new code scope for the enum type. enumScope = blockCodeScope.CreateCodeScopeForType(enumDefinition.Name, enumDefinition.definition_address, MutationCodeScopeType.Enum); // Create a new enum in the block definition for this field. blockCodeCreator.AddEnumOrBitmask(enumScope, enumDefinition); } // Add a field to the block definition for this enum type. blockCodeCreator.AddCustomTypedField(fields[i].type, fieldName, enumScope.Namespace, attributeCollection); break; } case field_type._field_byte_flags: case field_type._field_word_flags: case field_type._field_long_flags: { // Cast the field to a enum_definition struct. enum_definition enumDefinition = (enum_definition)fields[i]; // Check if there is an existing code scope for this bitmask type. MutationCodeScope bitmaskScope = blockCodeScope.FindExistingCodeScope(enumDefinition.definition_address); if (bitmaskScope == null) { // Create a new code scope for the bitmask type. bitmaskScope = blockCodeScope.CreateCodeScopeForType(enumDefinition.Name, enumDefinition.definition_address, MutationCodeScopeType.Bitmask); // Create a new bitmask in the block definition for this field. blockCodeCreator.AddEnumOrBitmask(bitmaskScope, enumDefinition); } // Add a field to the block definition for this bitmask type. blockCodeCreator.AddCustomTypedField(fields[i].type, fieldName, bitmaskScope.Namespace, attributeCollection); break; } case field_type._field_block: { // Get the definition struct from the field address. TagBlockDefinition tagBlockDefinition = reader.TagBlockDefinitions[fields[i].definition_address]; // Check if the tag block definition already exists in the parent code scope. MutationCodeScope tagBlockScope = parentScope.FindExistingCodeScope(tagBlockDefinition.s_tag_block_definition.address); if (tagBlockScope == null) { // Create a new code scope for the tag block definition. tagBlockScope = parentScope.CreateCodeScopeForType(tagBlockDefinition.s_tag_block_definition.Name, tagBlockDefinition.s_tag_block_definition.address, MutationCodeScopeType.TagBlock); // Compute the size of the definition. int definitionSize = TagLayoutValidator.ComputeMutationDefinitionSize(reader, tagBlockDefinition.TagFields[tagBlockDefinition.GetFieldSetIndexClosestToH2Xbox()]); // Create a new class for the tag block definition. MutationCodeCreator childBlockCodeCreator = this.CodeCreator.CreateTagBlockClass(tagBlockScope.Namespace, TagBlockDefinitionAttribute.CreateAttributeDeclaration(tagBlockDefinition, definitionSize)); // Process the tag block definition. ProcessTagBlockDefinition(reader, tagBlockDefinition, childBlockCodeCreator, tagBlockScope, parentScope); } // Create a field for the tag block. blockCodeCreator.AddTagBlockField(fieldName, tagBlockScope.Namespace, attributeCollection); break; } case field_type._field_struct: { // Cast the field to a tag_struct_definition. tag_struct_definition tagStruct = (tag_struct_definition)fields[i]; // Get the definition struct from the field address. TagBlockDefinition tagBlockDefinition = reader.TagBlockDefinitions[tagStruct.block_definition_address]; // Check if the tag block definition already exists in the parent code scope. MutationCodeScope tagBlockScope = parentScope.FindExistingCodeScope(tagBlockDefinition.s_tag_block_definition.address); if (tagBlockScope == null) { // Create a new code scope for the tag block definition. tagBlockScope = parentScope.CreateCodeScopeForType(tagBlockDefinition.s_tag_block_definition.Name, tagBlockDefinition.s_tag_block_definition.address, MutationCodeScopeType.Struct); // Compute the size of the definition. int definitionSize = TagLayoutValidator.ComputeMutationDefinitionSize(reader, tagBlockDefinition.TagFields[tagBlockDefinition.GetFieldSetIndexClosestToH2Xbox()]); // Create a new class for the tag block definition. MutationCodeCreator childBlockCodeCreator = this.CodeCreator.CreateTagBlockClass(tagBlockScope.Namespace, TagBlockDefinitionAttribute.CreateAttributeDeclaration(tagBlockDefinition, definitionSize)); // Process the tag block definition. ProcessTagBlockDefinition(reader, tagBlockDefinition, childBlockCodeCreator, tagBlockScope, parentScope); } // Build the tag block definition attribute for the field. attributeCollection.Add(TagStructAttribute.CreateAttributeDeclaration()); // Create a field for the tag block. blockCodeCreator.AddCustomTypedField(field_type._field_struct, fieldName, tagBlockScope.Namespace, attributeCollection); break; } case field_type._field_tag_reference: { // Cast the field to a tag_reference_definition definition. tag_reference_definition tagRegDefinition = (tag_reference_definition)fields[i]; // Build the tag reference attribute for the field. attributeCollection.Add(TagReferenceAttribute.CreateAttributeDeclaration(tagRegDefinition)); // Add the field with the group tag filter attribute. blockCodeCreator.AddField(fields[i].type, fieldName, attributeCollection); break; } case field_type._field_pad: case field_type._field_skip: case field_type._field_useless_pad: { // Build the padding attribute for the field. attributeCollection.Add(PaddingAttribute.CreateAttributeDeclaration(fields[i].type, fields[i].definition_address)); // Add the field with the padding attribute. blockCodeCreator.AddPaddingField(fieldName, fields[i].definition_address, attributeCollection); break; } case field_type._field_explanation: { // Cast the field to a explanation_definition. explaination_definition explanation = (explaination_definition)fields[i]; // Create a field for the explanation block. blockCodeCreator.AddExplanationField(fieldName, explanation.Name, explanation.Explaination); break; } case field_type._field_array_start: { // Build a list of fields inside of the array. List <tag_field> arrayFields = CreateArrayFieldList(fields, i); // Loop for the length of the array and process the fields. for (int x = 0; x < fields[i].definition_address; x++) { // Process the array fields. ProcessFields(arrayFields, reader, blockCodeCreator, blockCodeScope, parentScope); } // Skip the fields we just processed and the array terminator. i += arrayFields.Count + 1; break; } case field_type._field_data: { // Cast the field to a tag_dat_definition. tag_data_definition tagData = (tag_data_definition)fields[i]; // Create a tag data attribute for this field. attributeCollection.Add(TagDataAttribute.CreateAttributeDeclaration(tagData)); // Add the field to the collection. blockCodeCreator.AddField(fields[i].type, fieldName, attributeCollection); break; } case field_type._field_custom: break; case field_type._field_terminator: break; default: { // Check if the value type dictionary contains this field type. if (MutationCodeCreator.ValueTypeDictionary.Keys.Contains(fields[i].type) == false) { break; } // Add the field to the collection. blockCodeCreator.AddField(fields[i].type, fieldName, attributeCollection); break; } } } }