Пример #1
0
 private IField ToField(ModuleSchema schema, ModuleJson module, string name, int offset, string description, FieldCondition?condition)
 {
     // TODO: Validate that we don't have "extra" parameters?
     return(Type switch
     {
         "boolean" => (IField) new BooleanField(BuildCommon(1)),
         "boolean32" => new BooleanField(BuildCommon(4)),
         "range8" => BuildNumericField(1),
         "range16" => BuildNumericField(2),
         "range32" => BuildNumericField(4),
         "enum" => BuildEnumField(1),
         "enum16" => BuildEnumField(2),
         "enum32" => BuildEnumField(4),
         "dynamicOverlay" => BuildDynamicOverlay(),
         "instrument" => new InstrumentField(BuildCommon(4),
                                             ValidateNotNull(BankOffset, nameof(BankOffset)).Value,
                                             ValidateNotNull(VeditOffset, nameof(VeditOffset)).Value),
         "musicalNote" => new EnumField(BuildCommon(4), MusicalNoteValues, 0, 0),
         "volume32" => new NumericField(BuildCommon(4), -601, 60, 0, 10, null, 0, "dB", (-601, "-INF")),
         "string" => BuildStringField(1),
         "string16" => BuildStringField(2),
         "midi32" => new MidiNoteField(BuildCommon(4)),
         string text when text.StartsWith(ContainerPrefix) => BuildContainer(),
         _ => throw new InvalidOperationException($"Unknown field type: {Type}")
     });
 private VisualTreeConversionContext(
     ModuleJson moduleJson,
     FixedContainer containerContext,
     IReadOnlyDictionary <string, string> lookupsByPath,
     List <KeyValuePair <string, string> > indexes)
 {
     this.moduleJson       = moduleJson;
     this.ContainerContext = containerContext;
     this.lookupsByPath    = lookupsByPath;
     this.indexes          = indexes;
 }
Пример #3
0
        internal Container ToContainer(ModuleSchema schema, ModuleJson module, string name, int offset, string description, FieldCondition?condition)
        {
            // TODO: This works and is pleasantly efficient, but it's pretty ugly.
            if (cachedFields == null)
            {
                // TODO: Check that all fields are either primitive or container, check the size etc.
                cachedFields = Fields
                               .SelectMany(fieldJson => fieldJson.ToFields(schema, module))
                               .ToList()
                               .AsReadOnly();
            }
            var lastField = Fields.LastOrDefault();
            int size      = Size?.Value ?? lastField?.Offset?.Value ?? 0;
            var common    = new FieldBase.Parameters(schema, name, offset, size, description, condition);

            return(new Container(common, cachedFields));
        }
Пример #4
0
        internal IEnumerable <IField> ToFields(ModuleSchema schema, ModuleJson module)
        {
            string         description = ValidateNotNull(Description, nameof(Description));
            string         name        = Name ?? description;
            int?           repeat      = module.GetCount(Repeat);
            var            offset      = ValidateNotNull(Offset, nameof(Offset)).Value;
            FieldCondition?condition   = GetCondition();

            if (repeat == null)
            {
                yield return(ToField(schema, module, name, offset, description, condition));
            }
            else
            {
                var           gap    = ValidateNotNull(Gap, nameof(Gap)).Value;
                List <string>?lookup = null;
                if (DescriptionLookup != null)
                {
                    ValidateNotNull(module.Lookups, nameof(module.Lookups));
                    lookup = module.Lookups.FirstOrDefault(candidate => candidate.Name == DescriptionLookup)?.Values;
                    Validate(lookup != null, "Lookup ${DescriptionLookup} not found for descriptions.");
                    Validate(lookup !.Count == repeat,
                             $"Lookup ${DescriptionLookup} has {lookup.Count} elements; field has repeats {repeat} times.");
                }
                for (int i = 1; i <= repeat; i++)
                {
                    string indexedName     = Invariant($"{name}[{i}]");
                    string indexValue      = i.ToString(CultureInfo.InvariantCulture);
                    string?lookupValue     = lookup?[i - 1];
                    string fullDescription = string.Format(Description, indexValue, lookupValue);
                    yield return(ToField(schema, module, indexedName, offset, fullDescription, condition));

                    offset += gap;
                    // TODO: This is ugly. We need it because otherwise in SetList we end up with offsets of
                    // 0x03_00_00_00
                    // 0x03_00_10_00
                    // 0x03_00_20_00
                    // ....
                    // 0x03_00_70_00
                    // 0x03_00_80_00 => This will be promoted to an *address* of 0x03_01_00_00 automatically...
                    // ...
                    // 0x03_00_f0_00
                    // 0x03_01_00_00 => We now get 0x03_01_00_00 again :(
                    // 0x03_01_10_00
                    // But it's annoying to have this *here*...

                    if ((offset & 0x80) != 0)
                    {
                        offset += 0x80;
                    }
                    if ((offset & 0x80_00) != 0)
                    {
                        offset += 0x80_00;
                    }
                    if ((offset & 0x80_00_00) != 0)
                    {
                        offset += 0x80_00_00;
                    }
                }
            }

            FieldCondition?GetCondition()
            {
                if (Condition is null)
                {
                    return(null);
                }
                int conditionOffset = ValidateNotNull(Condition.Offset, nameof(Condition.Offset)).Value;
                int requiredValue   = ValidateNotNull(Condition.RequiredValue, nameof(Condition.RequiredValue));

                return(new FieldCondition(conditionOffset, requiredValue));
            }
        }
 internal static VisualTreeConversionContext Create(
     ModuleJson moduleJson,
     FixedContainer containerContext,
     IReadOnlyDictionary <string, string> lookupsByPath) =>
 new VisualTreeConversionContext(moduleJson, containerContext, lookupsByPath, new List <KeyValuePair <string, string> >());