diff --git a/mgs-spec-bank/charset/chaos_head_lcc-extended.json b/mgs-spec-bank/charset/chaos_head_lcc-extended.json index 59fac1e..27de43d 100644 --- a/mgs-spec-bank/charset/chaos_head_lcc-extended.json +++ b/mgs-spec-bank/charset/chaos_head_lcc-extended.json @@ -8978,5 +8978,353 @@ "text": "=" } ] + }, + { + "parameters": { + "encoding": { + "style": "italic" + }, + "rasterization": { + "font": "italic" + } + }, + "glyphs": [ + { + "units": [2368], + "text": "!" + }, + { + "units": [2369], + "text": "'" + }, + { + "units": [2370], + "text": "," + }, + { + "units": [2371], + "text": "-" + }, + { + "units": [2372], + "text": "." + }, + { + "units": [2373], + "text": "0" + }, + { + "units": [2374], + "text": "1" + }, + { + "units": [2375], + "text": "2" + }, + { + "units": [2376], + "text": "3" + }, + { + "units": [2377], + "text": "4" + }, + { + "units": [2378], + "text": "5" + }, + { + "units": [2379], + "text": "6" + }, + { + "units": [2380], + "text": "7" + }, + { + "units": [2381], + "text": "8" + }, + { + "units": [2382], + "text": "9" + }, + { + "units": [2383], + "text": ":" + }, + { + "units": [2384], + "text": "?" + }, + { + "units": [2385], + "text": "A" + }, + { + "units": [2386], + "text": "B" + }, + { + "units": [2387], + "text": "C" + }, + { + "units": [2388], + "text": "D" + }, + { + "units": [2389], + "text": "E" + }, + { + "units": [2390], + "text": "F" + }, + { + "units": [2391], + "text": "G" + }, + { + "units": [2392], + "text": "H" + }, + { + "units": [2393], + "text": "I" + }, + { + "units": [2394], + "text": "J" + }, + { + "units": [2395], + "text": "K" + }, + { + "units": [2396], + "text": "L" + }, + { + "units": [2397], + "text": "M" + }, + { + "units": [2398], + "text": "N" + }, + { + "units": [2399], + "text": "O" + }, + { + "units": [2400], + "text": "P" + }, + { + "units": [2401], + "text": "Q" + }, + { + "units": [2402], + "text": "R" + }, + { + "units": [2403], + "text": "S" + }, + { + "units": [2405], + "text": "T" + }, + { + "units": [2406], + "text": "U" + }, + { + "units": [2407], + "text": "V" + }, + { + "units": [2408], + "text": "W" + }, + { + "units": [2409], + "text": "X" + }, + { + "units": [2410], + "text": "Y" + }, + { + "units": [2411], + "text": "Z" + }, + { + "units": [2412], + "text": "a" + }, + { + "units": [2413], + "text": "b" + }, + { + "units": [2414], + "text": "c" + }, + { + "units": [2415], + "text": "d" + }, + { + "units": [2416], + "text": "e" + }, + { + "units": [2417], + "text": "f" + }, + { + "units": [2418], + "text": "g" + }, + { + "units": [2419], + "text": "h" + }, + { + "units": [2420], + "text": "i" + }, + { + "units": [2421], + "text": "j" + }, + { + "units": [2422], + "text": "k" + }, + { + "units": [2423], + "text": "l" + }, + { + "units": [2424], + "text": "m" + }, + { + "units": [2425], + "text": "n" + }, + { + "units": [2426], + "text": "o" + }, + { + "units": [2427], + "text": "p" + }, + { + "units": [2428], + "text": "q" + }, + { + "units": [2429], + "text": "r" + }, + { + "units": [2430], + "text": "s" + }, + { + "units": [2431], + "text": "t" + }, + { + "units": [2432], + "text": "u" + }, + { + "units": [2433], + "text": "v" + }, + { + "units": [2434], + "text": "w" + }, + { + "units": [2435], + "text": "x" + }, + { + "units": [2436], + "text": "y" + }, + { + "units": [2437], + "text": "z" + }, + { + "units": [2438], + "text": "—" + }, + { + "units": [2439], + "text": "‘" + }, + { + "units": [2440], + "text": "’" + }, + { + "units": [2441], + "text": "“" + }, + { + "units": [2442], + "text": "”" + }, + { + "units": [2443], + "text": "Ⅱ" + }, + { + "units": [2444], + "text": "(" + }, + { + "units": [2445], + "text": ")" + }, + { + "units": [2446], + "text": "♪" + }, + { + "units": [2447], + "text": "/" + }, + { + "units": [2448], + "text": "+" + }, + { + "units": [2449], + "text": "@" + }, + { + "units": [2450], + "text": "*" + }, + { + "units": [2451], + "text": ";" + }, + { + "units": [2452], + "text": "☆" + } + ] } ] diff --git a/mgs-spec-bank/data.yaml b/mgs-spec-bank/data.yaml index ef10c87..052ca7a 100644 --- a/mgs-spec-bank/data.yaml +++ b/mgs-spec-bank/data.yaml @@ -22,6 +22,9 @@ stringtags: - stringtags/base.yaml - stringtags/famicom_tantei_club.yaml +datadirectives: +- datadirectives/base.yaml + charset: chaos_head_lcc-extended: charset/chaos_head_lcc-extended.json chaos_head_noah: charset/chaos_head_noah.json @@ -68,6 +71,7 @@ flags: nonameid: yes multisystemmes: no option_default_arg: no + stringid_16: no memories_off_historia: new_bgmstop: yes @@ -101,6 +105,7 @@ flags: movie_01_27: yes return_labels: yes multisystemmes: no + stringid_16: no chaos_head_lcc_ps3: game_chlcc: yes @@ -135,6 +140,7 @@ flags: return_labels: no multisystemmes: no option_default_arg: yes + stringid_16: yes chaos_head_switch: game_chn: yes @@ -170,6 +176,7 @@ flags: return_labels: yes multisystemmes: no option_default_arg: no + stringid_16: no chaos_head_windows: game_chn: yes @@ -205,6 +212,7 @@ flags: return_labels: yes multisystemmes: no option_default_arg: no + stringid_16: no chaos_child_lcc_ps4: cc_common: yes @@ -243,9 +251,11 @@ flags: return_labels: yes multisystemmes: yes option_default_arg: no + stringid_16: yes famicom_tantei_club: game_ftc: yes + stringid_16: no iwakura_aria_switch: game_ia: yes @@ -275,6 +285,7 @@ flags: return_labels: yes multisystemmes: no option_default_arg: no + stringid_16: no iwakura_aria_windows: game_ia: yes @@ -307,6 +318,7 @@ flags: multilang: yes multisystemmes: no option_default_arg: no + stringid_16: no chaos_child_switch: cc_common: yes @@ -341,4 +353,5 @@ flags: movie_01_27: yes return_labels: yes multisystemmes: yes - option_default_arg: no \ No newline at end of file + option_default_arg: no + stringid_16: no \ No newline at end of file diff --git a/mgs-spec-bank/datadirectives/base.yaml b/mgs-spec-bank/datadirectives/base.yaml new file mode 100644 index 0000000..ad9facc --- /dev/null +++ b/mgs-spec-bank/datadirectives/base.yaml @@ -0,0 +1,19 @@ +- name: "StringID" + operands: [int32] + flags: [~stringid_16] + +- name: "StringID" + operands: [uint16] + flags: [stringid_16] + +- name: "dw" + operands: [uint16] + flags: [] + +- name: "Adr" + operands: [uint16] + flags: [] + +- name: "dd" + operands: [int32] + flags: [] \ No newline at end of file diff --git a/src/MagesScriptTool/DataDirectiveSpec.cs b/src/MagesScriptTool/DataDirectiveSpec.cs new file mode 100644 index 0000000..c06e766 --- /dev/null +++ b/src/MagesScriptTool/DataDirectiveSpec.cs @@ -0,0 +1,7 @@ +using System.Collections.Immutable; + +namespace MagesScriptTool; + +sealed class DataDirectiveSpec : InstructionSpec { + public DataDirectiveSpec(string name, ImmutableArray operands) : base(name, operands) {} +} diff --git a/src/MagesScriptTool/ExpressionNodeString.cs b/src/MagesScriptTool/ExpressionNodeString.cs index a5e9cc7..b964d13 100644 --- a/src/MagesScriptTool/ExpressionNodeString.cs +++ b/src/MagesScriptTool/ExpressionNodeString.cs @@ -7,7 +7,7 @@ public ExpressionNodeString(string value) { Value = value; } - public override string GetString() { + public override string GetString() { return Value; - } + } } diff --git a/src/MagesScriptTool/InstructionEncoding.cs b/src/MagesScriptTool/InstructionEncoding.cs index c393c96..dc36444 100644 --- a/src/MagesScriptTool/InstructionEncoding.cs +++ b/src/MagesScriptTool/InstructionEncoding.cs @@ -1,20 +1,24 @@ using System.Collections.Immutable; +using System.Diagnostics; using System.Text; +using System.Xml; namespace MagesScriptTool; sealed class InstructionEncoding { - readonly ImmutableTree _tree; - readonly ImmutableDictionary _table; + readonly ImmutableTree _opcodeTree; + readonly ImmutableDictionary _specTable; - InstructionEncoding(ImmutableTree tree, ImmutableDictionary table) { - _tree = tree; - _table = table; + InstructionEncoding(ImmutableTree opcodeTree, ImmutableDictionary specTable) { + _opcodeTree = opcodeTree; + _specTable = specTable; } public void Encode(Stream stream, Instruction instruction) { - InstructionSpec spec = _table[instruction.Name]; - PutBytes(stream, spec.Opcode.AsSpan()); + InstructionSpec spec = _specTable[instruction.Name]; + if (spec is VmInstructionSpec vmInstructionSpec) { + PutBytes(stream, vmInstructionSpec.Opcode.AsSpan()); + } ImmutableArray kinds = spec.Operands; ImmutableArray operands = instruction.Operands; if (operands.Length != kinds.Length) { @@ -32,9 +36,22 @@ public Instruction Decode(Stream stream) { foreach (OperandKind operandSpec in operandSpecs) { operands.Add(DecodeOperand(stream, operandSpec)); } - return new(spec.Name, [..operands]); + return new (spec.Name, [..operands]); } + public Instruction Decode(Stream stream, string dataDirective) { + DataDirectiveSpec spec = _specTable.GetValueOrDefault(dataDirective) switch { + DataDirectiveSpec dataDirectiveSpec => dataDirectiveSpec, + _ => throw new Exception($"Unrecognized data directive name: {dataDirective}") + }; + + ImmutableArray operandSpecs = spec.Operands; + List operands = []; + foreach (OperandKind operandSpec in operandSpecs) { + operands.Add(DecodeOperand(stream, operandSpec)); + } + return new (spec.Name, [..operands]); + } static void EncodeOperand(Stream stream, OperandKind kind, ExpressionNode operand) { switch (kind) { case OperandKind.Expr: { @@ -45,6 +62,7 @@ static void EncodeOperand(Stream stream, OperandKind kind, ExpressionNode operan EncodeOperandInt8(stream, operand); break; } + case OperandKind.UInt16: case OperandKind.Int16: { EncodeOperandInt16(stream, operand); break; @@ -95,17 +113,17 @@ static void PutBytes(Stream stream, ReadOnlySpan data) { stream.Write(data); } - InstructionSpec DecodeOpcode(Stream stream) { + VmInstructionSpec DecodeOpcode(Stream stream) { long start = stream.Position; - ImmutableTree cursor = _tree; + ImmutableTree cursor = _opcodeTree; while (true) { byte b = GetByte(stream); - ImmutableTree? next = cursor[b]; + ImmutableTree? next = cursor[b]; if (next is null) { throw new Exception($"Unrecognized instruction at {start}."); } cursor = next; - if (cursor.Value is InstructionSpec opcodeSpec) { + if (cursor.Value is VmInstructionSpec opcodeSpec) { return opcodeSpec; } } @@ -115,6 +133,7 @@ static ExpressionNode DecodeOperand(Stream stream, OperandKind kind) { return kind switch { OperandKind.Expr => ExpressionEncoding.Decode(stream), OperandKind.Int8 => DecodeOperandInt8(stream), + OperandKind.UInt16 => DecodeOperandUInt16(stream), OperandKind.Int16 => DecodeOperandInt16(stream), OperandKind.Int32 => DecodeOperandInt32(stream), OperandKind.Str => DecodeOperandStr(stream), @@ -138,6 +157,13 @@ static ExpressionNodeNumber DecodeOperandInt8(Stream stream) { return new(value); } + static ExpressionNodeNumber DecodeOperandUInt16(Stream stream) { + int value = 0; + value |= GetByte(stream) << 0; + value |= GetByte(stream) << 8; + return new(value); + } + static ExpressionNodeNumber DecodeOperandInt16(Stream stream) { int value = 0; value |= GetByte(stream) << 0; @@ -169,10 +195,10 @@ static int SignExtend(int value, int length) { return value | ~(sign - 1); } - public static InstructionEncoding BuildFrom(ImmutableArray opcodeSpecs) { - ImmutableTree tree = BuildOpcodeTree(opcodeSpecs); + public static InstructionEncoding BuildFrom(ImmutableArray specs) { + ImmutableTree tree = BuildOpcodeTree(specs); Dictionary table = []; - foreach (InstructionSpec spec in opcodeSpecs) { + foreach (InstructionSpec spec in specs) { if (table.ContainsKey(spec.Name)) { throw new Exception($"Duplicate instruction name: {spec.Name}."); } @@ -181,14 +207,16 @@ public static InstructionEncoding BuildFrom(ImmutableArray opco return new(tree, table.ToImmutableDictionary()); } - static ImmutableTree BuildOpcodeTree(ImmutableArray specs) { - Tree tree = new(); + static ImmutableTree BuildOpcodeTree(ImmutableArray specs) { + Tree tree = new(); foreach (InstructionSpec spec in specs) { - ImmutableArray opcode = spec.Opcode; + if (spec is not VmInstructionSpec) continue; + VmInstructionSpec vmInstructionSpec = (VmInstructionSpec)spec; + ImmutableArray opcode = vmInstructionSpec.Opcode; if (opcode.Length == 0) { throw new Exception($"Empty opcode: {spec.Name}."); } - Tree cursor = tree; + Tree cursor = tree; for (int i = 0; i < opcode.Length; i++) { if (cursor.HasValue) { throw new Exception($"Duplicate opcode prefix: {Convert.ToHexString(opcode.AsSpan()[..i])}."); @@ -201,7 +229,7 @@ static ImmutableTree BuildOpcodeTree(ImmutableArray Opcode; public readonly ImmutableArray Operands; - public InstructionSpec(string name, ImmutableArray opcode, ImmutableArray operands) { + public InstructionSpec(string name, ImmutableArray operands) { Name = name; - Opcode = opcode; Operands = operands; } } diff --git a/src/MagesScriptTool/OperandKind.cs b/src/MagesScriptTool/OperandKind.cs index e6941f8..2e979d9 100644 --- a/src/MagesScriptTool/OperandKind.cs +++ b/src/MagesScriptTool/OperandKind.cs @@ -4,6 +4,7 @@ enum OperandKind { Expr, UInt8, Int8, + UInt16, Int16, Int32, Str, diff --git a/src/MagesScriptTool/Program.cs b/src/MagesScriptTool/Program.cs index 9c3434c..1ec70a4 100644 --- a/src/MagesScriptTool/Program.cs +++ b/src/MagesScriptTool/Program.cs @@ -101,7 +101,7 @@ public Tool(ParseResult result) { ImmutableArray instructionSpecs = bank.GetInstructionSpecs(flags); InstructionEncoding = InstructionEncoding.BuildFrom(instructionSpecs); - UncompiledStringSyntax uncompiledStringSyntax = new(); + UncompiledStringSyntax uncompiledStringSyntax = new(); UncompiledStringTableSyntax = new(uncompiledStringSyntax); ImmutableArray glyphSpecs = bank.GetGlyphSpecs(charsetName); @@ -109,6 +109,7 @@ public Tool(ParseResult result) { ImmutableArray stringTagSpecs = bank.GetStringTagSpecs(flags); StringTagsSpec stringTagsSpec = new(stringTagSpecs); + CompiledStringEncoding compiledStringEncoding = new(stringTagsSpec); CompiledScriptPackageEncoding = new(compiledStringEncoding); CompiledStringTableEncoding = new(compiledStringEncoding); diff --git a/src/MagesScriptTool/ScriptCompiler.cs b/src/MagesScriptTool/ScriptCompiler.cs index 7bd193b..1dcd67e 100644 --- a/src/MagesScriptTool/ScriptCompiler.cs +++ b/src/MagesScriptTool/ScriptCompiler.cs @@ -4,7 +4,6 @@ namespace MagesScriptTool; sealed class ScriptCompiler { readonly InstructionEncoding _instructionEncoding; - readonly MemoryStream _stream = new(); readonly SortedDictionary _labelTable = []; readonly SortedDictionary _returnLabelTable = []; @@ -40,7 +39,7 @@ public CompiledScript Compile(ImmutableArray elements) void ProcessElement(UncompiledScriptElement element) { switch (element) { case UncompiledScriptElementInstruction { Value: Instruction instruction }: { - ProcessInstruction(instruction); + _instructionEncoding.Encode(_stream, instruction); break; } case UncompiledScriptElementLabel { Index: int index }: { @@ -69,42 +68,4 @@ void ProcessElement(UncompiledScriptElement element) { } } - void ProcessInstruction(Instruction instruction) { - switch (instruction.Name.ToLowerInvariant()) { - case "dw" or "adr": { - foreach (ExpressionNode operand in instruction.Operands) { - EncodeInt16(operand); - } - break; - } - case "dd" or "stringid": { - foreach (ExpressionNode operand in instruction.Operands) { - EncodeInt32(operand); - } - break; - } - default: { - _instructionEncoding.Encode(_stream, instruction); - break; - } - } - } - - void EncodeInt16(ExpressionNode expression) { - int value = expression.GetInt(); - PutByte((byte)((value >> 00) & 0xFF)); - PutByte((byte)((value >> 08) & 0xFF)); - } - - void EncodeInt32(ExpressionNode expression) { - int value = expression.GetInt(); - PutByte((byte)((value >> 00) & 0xFF)); - PutByte((byte)((value >> 08) & 0xFF)); - PutByte((byte)((value >> 16) & 0xFF)); - PutByte((byte)((value >> 24) & 0xFF)); - } - - void PutByte(byte value) { - _stream.WriteByte(value); - } } diff --git a/src/MagesScriptTool/ScriptDecompiler.cs b/src/MagesScriptTool/ScriptDecompiler.cs index 4919166..9c73a77 100644 --- a/src/MagesScriptTool/ScriptDecompiler.cs +++ b/src/MagesScriptTool/ScriptDecompiler.cs @@ -4,7 +4,6 @@ namespace MagesScriptTool; sealed class ScriptDecompiler { readonly InstructionEncoding _instructionEncoding; - readonly ImmutableArray _code; readonly ImmutableArray _labels; readonly ImmutableArray _returnLabels; @@ -257,39 +256,39 @@ void Decode() { void DecodeInt16Table() { while (Position < Length) { - AddInstruction(new("dw", [DecodeInt16()])); + AddInstruction(_instructionEncoding.Decode(this, "dw")); } } void DecodeInt32Table() { while (Position < Length) { - AddInstruction(new("dd", [DecodeInt32()])); + AddInstruction(_instructionEncoding.Decode(this, "dd")); } } void DecodeAdrTable() { while (Position < Length) { - AddInstruction(new("Adr", [DecodeInt16()])); + AddInstruction(_instructionEncoding.Decode(this, "Adr")); } } void DecodeTextTable() { while (Position < Length) { - AddInstruction(new("StringID", [DecodeInt32()])); + AddInstruction(_instructionEncoding.Decode(this, "StringID")); } } void DecodeNameIdTable() { SetIncomplete(); while (true) { - ExpressionNode id = DecodeInt16(); - AddInstruction(new("dw", [id])); - if (id.GetInt() == 0xFFFF) { + Instruction id = _instructionEncoding.Decode(this, "dw"); + AddInstruction(id); + if ((id.Operands[0].GetInt() & 0xFFFF) == 0xFFFF) { break; } - AddInstruction(new("StringID", [DecodeInt32()])); - AddInstruction(new("StringID", [DecodeInt32()])); + AddInstruction(_instructionEncoding.Decode(this, "StringID")); + AddInstruction(_instructionEncoding.Decode(this, "StringID")); } SetComplete(); } @@ -298,9 +297,9 @@ void DecodeEncycDataTable() { SetIncomplete(); int index = 0; while (true) { - ExpressionNode value0 = DecodeInt16(); - AddInstruction(new("dw", [value0])); - if (value0.GetInt() == 0xFF) { + Instruction pageCount = _instructionEncoding.Decode(this, "dw"); + AddInstruction(pageCount); + if ((pageCount.Operands[0].GetInt() & 0xFFFF) == 0xFF) { break; } @@ -308,19 +307,21 @@ void DecodeEncycDataTable() { index++; // Category - AddInstruction(new("StringID", [DecodeInt32()])); + AddInstruction(_instructionEncoding.Decode(this, "StringID")); // Name - AddInstruction(new("StringID", [DecodeInt32()])); + AddInstruction(_instructionEncoding.Decode(this, "StringID")); // Pronounciation - AddInstruction(new("StringID", [DecodeInt32()])); + AddInstruction(_instructionEncoding.Decode(this, "StringID")); // Sorting key - AddInstruction(new("StringID", [DecodeInt32()])); + AddInstruction(_instructionEncoding.Decode(this, "StringID")); // Content - AddInstruction(new("StringID", [DecodeInt32()])); + for (int i = 0; i < pageCount.Operands[0].GetInt(); i++) { + AddInstruction(_instructionEncoding.Decode(this, "StringID")); + } } SetComplete(); } @@ -328,22 +329,16 @@ void DecodeEncycDataTable() { void DecodeEncycSortTable() { SetIncomplete(); - AddInstruction(new("StringID", [DecodeInt32()])); - AddInstruction(new("StringID", [DecodeInt32()])); + AddInstruction(_instructionEncoding.Decode(this, "StringID")); + AddInstruction(_instructionEncoding.Decode(this, "StringID")); - while (true) { - ExpressionNode value0 = DecodeInt16(); - AddInstruction(new("dw", [value0])); - if (value0.GetInt() == 0xFFFF) { - break; - } - } - - while (true) { - ExpressionNode value0 = DecodeInt16(); - AddInstruction(new("dw", [value0])); - if (value0.GetInt() == 0xFFFF) { - break; + for (int i = 0; i < 2; i++) { + while (true) { + Instruction value0 = _instructionEncoding.Decode(this, "dw"); + AddInstruction(value0); + if ((value0.Operands[0].GetInt() & 0xFFFF) == 0xFFFF) { + break; + } } } @@ -353,7 +348,7 @@ void DecodeEncycSortTable() { void DecodeMesModeFormatTable() { int index = 0; while (Position < Length) { - ExpressionNode value0 = DecodeInt16(); + Instruction value0 = _instructionEncoding.Decode(this, "dw"); string? comment = index switch { 0 => "display mode", 1 => "message window ID", @@ -380,35 +375,11 @@ void DecodeMesModeFormatTable() { if (comment is not null) { AddComment(comment); } - AddInstruction(new("dw", [value0])); + AddInstruction(value0); index++; } } - ExpressionNodeNumber DecodeInt16() { - int value = 0; - value |= GetByte() << 0; - value |= GetByte() << 8; - return new(value); - } - - ExpressionNodeNumber DecodeInt32() { - int value = 0; - value |= GetByte() << 0; - value |= GetByte() << 8; - value |= GetByte() << 16; - value |= GetByte() << 24; - return new(value); - } - - byte GetByte() { - int value = ReadByte(); - if (value < 0) { - throw new EndOfStreamException(); - } - return (byte)value; - } - void Reset() { Error = null; Body.Clear(); diff --git a/src/MagesScriptTool/SpecBank.cs b/src/MagesScriptTool/SpecBank.cs index 327d5c9..05baf04 100644 --- a/src/MagesScriptTool/SpecBank.cs +++ b/src/MagesScriptTool/SpecBank.cs @@ -23,9 +23,20 @@ public ImmutableArray GetInstructionSpecs(ImmutableDictionary(text); } } + + sealed class SerializedDataDirectiveSpec { + [YamlMember(Alias = "name", ApplyNamingConventions = false)] + public string Name { get; set; } = default!; + + [YamlMember(Alias = "operands", ApplyNamingConventions = false)] + public string[] Operands { get; set; } = default!; + + [YamlMember(Alias = "flags", ApplyNamingConventions = false)] + public string[] Flags { get; set; } = default!; + + public ImmutableArray ParseOperands() { + List operands = []; + for (int i = 0; i < Operands.Length; i++) { + operands.Add(Operands[i] switch { + "expr" => OperandKind.Expr, + "uint8" => OperandKind.UInt8, + "int8" => OperandKind.Int8, + "uint16" => OperandKind.UInt16, + "int16" => OperandKind.Int16, + "int32" => OperandKind.Int32, + "str" => OperandKind.Str, + _ => throw new Exception($"Unrecognized operand kind name: {Operands[i]}."), + }); + } + return [..operands]; + } + public bool CheckFlags(ImmutableDictionary flags) { + foreach (string flag in Flags) { + string name; + bool value; + if (flag.StartsWith('~')) { + (name, value) = (flag[1..], false); + } else { + (name, value) = (flag, true); + } + if (!flags.ContainsKey(name) || flags[name] != value) { + return false; + } + } + return true; + } + public static SerializedDataDirectiveSpec[] LoadList(string path) { + string text = File.ReadAllText(path, new UTF8Encoding(false, true)); + IDeserializer deserializer = new DeserializerBuilder().Build(); + return deserializer.Deserialize(text); + } + } } diff --git a/src/MagesScriptTool/UncompiledScriptSyntax.cs b/src/MagesScriptTool/UncompiledScriptSyntax.cs index c8a2ef4..2c6a509 100644 --- a/src/MagesScriptTool/UncompiledScriptSyntax.cs +++ b/src/MagesScriptTool/UncompiledScriptSyntax.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Data.Common; using System.Diagnostics; using System.Text; @@ -140,7 +141,7 @@ public ImmutableArray Parse() { UncompiledScriptElement ParseElement() { char ch = _reader.Peek(0); - if (IsInstructionNameStart(ch)) { + if (IsIdentifierStart(ch)) { string name = ParseInstructionName(); switch (name) { case "hex": { @@ -231,9 +232,9 @@ UncompiledScriptElementInstruction ParseEvalInstruction() { } string ParseInstructionName() { - Debug.Assert(IsInstructionNameStart(_reader.Peek(0))); + Debug.Assert(IsIdentifierStart(_reader.Peek(0))); string s = ""; - while (IsInstructionNamePart(_reader.Peek(0))) { + while (IsIdentifierPart(_reader.Peek(0))) { s += _reader.Next(); } return s; @@ -264,12 +265,12 @@ int ParseNibble() { }; } - static bool IsInstructionNameStart(char c) { + static bool IsIdentifierStart(char c) { return c is '_' or (>= 'A' and <= 'Z') or (>= 'a' and <= 'z'); } - static bool IsInstructionNamePart(char c) { - return IsInstructionNameStart(c) || IsDigit(c); + static bool IsIdentifierPart(char c) { + return IsIdentifierStart(c) || IsDigit(c); } static bool IsDigit(char c) { diff --git a/src/MagesScriptTool/VmInstructionSpec.cs b/src/MagesScriptTool/VmInstructionSpec.cs new file mode 100644 index 0000000..3ef50f5 --- /dev/null +++ b/src/MagesScriptTool/VmInstructionSpec.cs @@ -0,0 +1,11 @@ +using System.Collections.Immutable; + +namespace MagesScriptTool; + +class VmInstructionSpec : InstructionSpec { + public readonly ImmutableArray Opcode; + + public VmInstructionSpec(string name, ImmutableArray opcode, ImmutableArray operands) : base(name, operands) { + Opcode = opcode; + } +} \ No newline at end of file