diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..64cc878 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.cs linguist-language=C# \ No newline at end of file diff --git a/Event Assembler/Core/AssemblyInfo.cs b/Event Assembler/Core/AssemblyInfo.cs deleted file mode 100644 index 6768c9e..0000000 --- a/Event Assembler/Core/AssemblyInfo.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -//[assembly: Extension] -[assembly: AssemblyFileVersion("11.1")] -[assembly: AssemblyDescription("Core library of Event Assembler")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Nintenlord, Crazycolorx5")] -[assembly: Guid("74afd097-d67b-4f50-ba8e-f7083eb4439f")] -[assembly: AssemblyTitle("Core")] -[assembly: AssemblyProduct("Core")] -[assembly: AssemblyCopyright("Copyright © Nintenlord 2011, Crazycolorz5 2016")] -[assembly: AssemblyTrademark("")] -[assembly: ComVisible(false)] -[assembly: AssemblyVersion("11.1.00.00")] diff --git a/Event Assembler/Core/Code/Language/EACodeLanguage.cs b/Event Assembler/Core/Code/Language/EACodeLanguage.cs index 6568656..82b94dd 100644 --- a/Event Assembler/Core/Code/Language/EACodeLanguage.cs +++ b/Event Assembler/Core/Code/Language/EACodeLanguage.cs @@ -4,6 +4,7 @@ using Nintenlord.Event_Assembler.Core.IO.Input; using Nintenlord.Event_Assembler.Core.IO.Logs; using Nintenlord.Parser; +using Nintenlord.Utility.Strings; using System; using System.Collections.Generic; using System.IO; @@ -104,7 +105,7 @@ public EACodeLanguage(string name, IPointerMaker pointerMaker, Tuple>) null); + this.assembler = new EAExpressionAssembler(this.codeStorage, new TokenParser (new Func (StringExtensions.GetValue))); this.disassembler = new EACodeLanguageDisassembler(this.codeStorage, pointerMaker, pointerList); } @@ -113,6 +114,16 @@ public void Assemble(IPositionableInputStream input, BinaryWriter output, ILog m this.assembler.Assemble(input, output, messageLog); } + public void Compile(IPositionableInputStream input, TextWriter output, ILog messageLog) + { + this.assembler.Compile(input, output, messageLog); + } + + public IEnumerable> GetGlobalSymbols () + { + return this.assembler.GetGlobalSymbols(); + } + public IEnumerable Disassemble(byte[] code, int offset, int length, Priority priority, bool addEndingLinest, ILog messageLog) { return this.disassembler.Disassemble(code, offset, length, priority, messageLog, addEndingLinest); diff --git a/Event Assembler/Core/Code/Language/EAExpressionAssembler.cs b/Event Assembler/Core/Code/Language/EAExpressionAssembler.cs index d32399b..2ef3aad 100644 --- a/Event Assembler/Core/Code/Language/EAExpressionAssembler.cs +++ b/Event Assembler/Core/Code/Language/EAExpressionAssembler.cs @@ -34,7 +34,13 @@ internal sealed class EAExpressionAssembler private const string offsetPopper = "POP"; private const string assertion = "ASSERT"; private const string protectCode = "PROTECT"; - private readonly IParser> parser; + private const string ThumbAssembly = "T"; + private const string ARMAssembly = "A"; + private const string ExternSymbol = "EXTERN"; + private const string GlobalSymbol = "GLOBAL"; + private const string sectionMaker = "SECTION"; + private const string sectionEnd = "ENDSECTION"; + private readonly IParser> parser; private readonly ICodeTemplateStorer storer; private ILog log; @@ -80,7 +86,7 @@ public void Assemble(IPositionableInputStream input, BinaryWriter output, ILog l if (log.ErrorCount == 0) { this.currentOffset = 0; - ExecuteLayoutPass (expression, null); + ExecuteLayoutPass (expression, null, output); } if (log.ErrorCount == 0) { @@ -88,8 +94,46 @@ public void Assemble(IPositionableInputStream input, BinaryWriter output, ILog l ExecuteWritePass (output, expression, null); } } + + public void Compile(IPositionableInputStream input, TextWriter output, ILog log) { + this.log = log; - private void ExecuteLayoutPass(IExpression expression, ScopeStructure scope) { + this.offsetHistory = new Stack (); + this.protectedRegions = new List> (); + + this.scopeStructures = new Dictionary, ScopeStructure> (); + + TokenScanner tokenScanner = new TokenScanner (input); + + if (!tokenScanner.MoveNext ()) + return; + + Match match; + IExpression expression = parser.Parse (tokenScanner, out match); + + if (!match.Success) { + log.AddError (match.Error); + return; + } + + if (!tokenScanner.IsAtEnd && tokenScanner.Current.Type != TokenType.EndOfStream) { + AddNotReachedEnd (tokenScanner.Current); + return; + } + + if (log.ErrorCount == 0) { + this.currentOffset = 0; + // DeclareExternASMCLabels(ExecuteLayoutPass (expression, null,output), output); + ExecuteLayoutPass(expression, null, output); + } + + if (log.ErrorCount == 0) { + this.currentOffset = 0; + ExecuteWritePass (output, expression, null); + } + } + + private ScopeStructure ExecuteLayoutPass(IExpression expression, ScopeStructure scope, T output) { switch (expression.Type) { case EAExpressionType.Scope: @@ -98,7 +142,7 @@ private void ExecuteLayoutPass(IExpression expression, ScopeStructure scopeStructures [(Scope)expression] = newScope; foreach (IExpression child in expression.GetChildren()) - ExecuteLayoutPass (child, newScope); + ExecuteLayoutPass (child, newScope, output); break; } @@ -110,6 +154,9 @@ private void ExecuteLayoutPass(IExpression expression, ScopeStructure if (code.IsEmpty || HandleBuiltInCodeLayout (code, scope)) break; + if (code.CodeName.Name == "ASMC" && code.Parameters[0].ToString() != "" && !System.Text.RegularExpressions.Regex.IsMatch(code.Parameters[0].ToString(), @"\A\b(0[xX])?[0-9a-fA-F]+\b\Z")) + scope.RegisterASMCLabel(code.Parameters[0].ToString()); + Types.Type[] sig = ((IEnumerable>)code.Parameters).Select (new Func, Types.Type> (Types.Type.GetType)).ToArray (); CanCauseError templateError = this.storer.FindTemplate (code.CodeName.Name, sig); @@ -134,6 +181,9 @@ private void ExecuteLayoutPass(IExpression expression, ScopeStructure case EAExpressionType.Labeled: { + // record label names + scope.SetLocalLabelAddress(((LabelExpression)expression).LabelName, currentOffset); + CanCauseError err = scope.AddNewSymbol (((LabelExpression)expression).LabelName, new ValueExpression (this.currentOffset, new FilePosition ())); if (err.CausedError) @@ -172,9 +222,27 @@ private void ExecuteLayoutPass(IExpression expression, ScopeStructure throw new ArgumentException ("Badly formed tree."); } - } - private void ExecuteWritePass(BinaryWriter output, IExpression expression, ScopeStructure scope) { + // DeclareExternASMCLabels(scope, output); + return scope; + } + + // private void DeclareExternASMCLabels(ScopeStructure scope, T output) + private void DeclareExternASMCLabels(ScopeStructure scope, TextWriter output) + { + //if (output is TextWriter) + if (scope != null) + foreach (var label in scope.GetRegisteredASMCLabels()) + { + if (!scope.IsLocalLabelExisted(label)) + { + //(output as TextWriter).WriteLine("\t.global " + label); + output.WriteLine("\t.global " + label); + } + } + } + + private void ExecuteWritePass(BinaryWriter output, IExpression expression, ScopeStructure scope) { // This is to be executed *after* the layout pass switch (expression.Type) { @@ -212,7 +280,7 @@ private void ExecuteWritePass(BinaryWriter output, IExpression expression, ICodeTemplate template = templateError.Result; - CanCauseError data = template.GetData (code.Parameters, x => this.GetSymbolValue (scope, x)); + CanCauseError data = template.GetData (code.Parameters, x => this.GetSymbolValue (scope, x), scope); if (data.CausedError) // Can't compute code data, so we err @@ -245,7 +313,165 @@ private void ExecuteWritePass(BinaryWriter output, IExpression expression, } } + + private void ExecuteWritePass(TextWriter output, IExpression expression, ScopeStructure scope) { + // This is to be executed *after* the layout pass + + switch (expression.Type) { + + case EAExpressionType.Scope: + { + ScopeStructure newScope = scopeStructures [(Scope)expression]; + + foreach (IExpression child in expression.GetChildren()) + ExecuteWritePass (output, child, newScope); + + break; + } + + case EAExpressionType.Code: + { + Code code = expression as Code; + + // alignment. ALIGN 2^n => .align n + if(!code.IsEmpty && code.CodeName.Name == offsetAligner && code.ParameterCount.IsInRange(1, 1) && !(code.Parameters[0] is ExpressionList)) + output.WriteLine("\t.align {0}", Math.Ceiling(Math.Log(Folding.Fold (code.Parameters[0], (x => this.GetSymbolValue (scope, x))).Result, 2))); + + if (code.IsEmpty || HandleBuiltInCodeWrite (code, scope, output)) + break; + + bool TFlag = false; + // bool ExtFlag = false; + + if (code.CodeName.Name == "ASMC") + { + if (code.Parameters.Length > 0 && code.Parameters[0].ToString() != "" && !scope.IsLocalLabelExisted(code.Parameters[0].ToString()) && !System.Text.RegularExpressions.Regex.IsMatch(code.Parameters[0].ToString(), @"\A\b(0[xX])?[0-9a-fA-F]+\b\Z")) + { + // ExtFlag = true; + } + else + { + TFlag = true; + } + } + + // Maybe all of this template lookup up can be made faster by + // storing the found template from the layout pass? + + Types.Type[] sig = ((IEnumerable>)code.Parameters).Select (new Func, Types.Type> (Types.Type.GetType)).ToArray (); + + CanCauseError templateError = this.storer.FindTemplate (code.CodeName.Name, sig); + + if (templateError.CausedError) { + AddError ((IExpression)code, templateError); + break; + } + + // We won't check for alignment as it should already have been done in the layout pass + ICodeTemplate template = templateError.Result; + + /*if (template is CodeTemplate && code.Parameters.Length > 0) + { + for (int i = 0; i < code.Parameters.Length; i++) + { + if(scope.GetRegisteredASMCLabels().Exists(o => o == code.Parameters[i].ToString())) + { + (template as CodeTemplate).AddExternLabel(i, code.Parameters[i].ToString()); + } + } + }*/ + + CanCauseError data = template.GetData (code.Parameters, x => this.GetSymbolValue (scope, x), scope); + + Dictionary localLabels = template.GetLocalLabels (); + Dictionary externLabels = template.GetExternLabels(); + var labels = localLabels.Union(externLabels).ToList(); + + if (data.CausedError) + // Can't compute code data, so we err + this.AddError (expression, data); + else { + // Write data + if(labels.Count == 0) + TryWrite(output, expression, currentOffset, data.Result); + else { + int startIndex = 0; + foreach (KeyValuePair k in labels) + { + // Console.WriteLine("pos:" + k.Key + " label:" + k.Value); + if (k.Key - startIndex > 0) + TryWrite(output, expression, currentOffset, data.Result.Skip(startIndex).Take(k.Key - startIndex).ToArray()); + startIndex = k.Key + 4; + + if(TFlag == true && scope.IsLocalLabelExisted(k.Value)) + { + output.WriteLine("\t.word {0}+1", k.Value); + TFlag = false; + } + else + output.WriteLine("\t.word {0}", k.Value); + } + if (data.Result.Length - startIndex > 4) + TryWrite(output, expression, currentOffset, data.Result.Skip(startIndex).Take(data.Result.Length - startIndex).ToArray()); + } + } + + this.currentOffset += data.Result.Length; + + /*for (int i = 0; i < code.Parameters.Length; i++) + { + // Console.WriteLine(code.Parameters[i]); + if (scope.IsLabelExisted(code.Parameters[i].ToString())) + { + output.WriteLine("\t.word {0}", code.Parameters[i]); + this.currentOffset += 4; + } + else + { + IExpression[] parameter = new IExpression[] { code.Parameters[i] }; + CanCauseError data = template.GetDataUnit(parameter, x => this.GetSymbolValue(scope, x)); + if (data.CausedError) + // Can't compute code data, so we err + this.AddError(expression, data); + else + { + // Write data + TryWrite(output, expression, currentOffset, data.Result); + this.currentOffset += data.Result.Length; + } + } + }*/ + + break; + } + + case EAExpressionType.RawData: + { + RawData rawData = (RawData)expression; + + TryWrite (output, expression, this.currentOffset, rawData.Data); + this.currentOffset += rawData.Data.Length; + + break; + } + + case EAExpressionType.Labeled: + + //TODO Add label attribute: ".global LabelName" + output.WriteLine(((LabelExpression)expression).LabelName + ":"); + + break; + case EAExpressionType.Assignment: + //TODO .set/.equ, but it doesn't matter + break; + + default: + throw new ArgumentException ("Badly formed tree."); + + } + } + private bool SyncOutputCursorWithOffset(BinaryWriter output, long offset) { if (output.BaseStream.Position != offset) { if (!output.BaseStream.CanSeek) @@ -256,7 +482,7 @@ private bool SyncOutputCursorWithOffset(BinaryWriter output, long offset) { return true; } - + private bool TryWrite(BinaryWriter output, IExpression expression, long offset, byte[] data) { if (!SyncOutputCursorWithOffset (output, (long)this.currentOffset)) { this.AddError (expression, "Stream cannot be seeked."); @@ -272,6 +498,16 @@ private bool TryWrite(BinaryWriter output, IExpression expression, long off return true; } + private bool TryWrite(TextWriter output, IExpression expression, long offset, byte[] data) { + if (IsProtected (this.currentOffset, data.Length)) { + this.AddError (expression, "Attempting to modify protected memory at " + this.currentOffset.ToHexString ("$") + " with code of length " + data.Length); + return false; + } + + output.WriteLine ("\t.byte 0x" + BitConverter.ToString(data).Replace("-", ", 0x")); + return true; + } + private bool HandleBuiltInCodeLayout(Code code, ScopeStructure scope) { switch (code.CodeName.Name) { @@ -304,13 +540,92 @@ private bool HandleBuiltInCodeLayout(Code code, ScopeStructure scope) HandleBuiltInProtect (code, scope); return true; + case ThumbAssembly: + case ARMAssembly: + return true; + + case ExternSymbol: + CanCauseError err = scope.AddNewSymbol(code.Parameters[0].ToString(), new ValueExpression(-1, new FilePosition())); + + if (err.CausedError) + AddWarning((IExpression)code, err.ErrorMessage); + return true; + + case GlobalSymbol: + case sectionMaker: + case sectionEnd: + return true; + default: return false; } } - private bool HandleBuiltInCodeWrite(Code code, ScopeStructure scope) { + private void PrintAssemblyCode(Code code, ScopeStructure scope, TextWriter output) + { + output.Write("\t"); + for (int i = 0; i < code.Parameters.Length; i++) + { + // support EA macro in inline assembly + if (!scope.IsLocalLabelExisted(code.Parameters[i].ToString()) && !scope.GetSymbolValue(code.Parameters[i].ToString()).CausedError) + { + output.Write(" #0x{0:X}", Folding.Fold(code.Parameters[i], (x => this.GetSymbolValue(scope, x))).Result); + } + else + { + output.Write(" {0}", code.Parameters[i].ToString()); + } + + if (i == 0) + { + output.Write("\t"); + if (code.Parameters[0].ToString() == "push" || code.Parameters[0].ToString() == "pop") + output.Write("{"); + } + if (i != code.Parameters.Length - 1) + { + if (i != 0) + output.Write(","); + + if (code.Parameters[0].ToString().StartsWith("ldr") || code.Parameters[0].ToString().StartsWith("str")) + { + if(i == 1) + output.Write("["); + } + + // Console.WriteLine(code.Parameters[i + 1].ToString()); + if (System.Text.RegularExpressions.Regex.IsMatch(code.Parameters[i + 1].ToString(), @"^\d+$")) + output.Write("#"); + } + else + { + if (code.Parameters[0].ToString() == "push" || code.Parameters[0].ToString() == "pop") + output.Write(" }"); + else + if (code.Parameters[0].ToString().StartsWith("ldr") || code.Parameters[0].ToString().StartsWith("str")) + output.Write(" ]"); + output.Write("\n"); + } + + + } + } + + private void HandleThumbAssembly(Code code, ScopeStructure scope, TextWriter output) + { + // output.WriteLine("\t .thumb"); + // output.WriteLine("\t .thumb_func"); + PrintAssemblyCode(code, scope, output); + } + + private void HandleARMAssembly(Code code, ScopeStructure scope, TextWriter output) + { + // output.WriteLine("\t .arm"); + PrintAssemblyCode(code, scope, output); + } + + private bool HandleBuiltInCodeWrite(Code code, ScopeStructure scope, TextWriter output) { switch (code.CodeName.Name) { case messagePrinterCode: @@ -332,15 +647,19 @@ private bool HandleBuiltInCodeWrite(Code code, ScopeStructure scope) { case offsetChanger: HandleBuiltInOffsetChange (code, scope); - return true; + if(Program.RunConfig.org) + output.WriteLine(".previous\n@section org_{0:X} 0x{0:X}+0x8000000", Convert.ToInt32(code.Parameters[0].ToString())); + return true; case offsetPusher: HandleBuiltInOffsetPush (code, scope); - return true; + output.WriteLine(".pushsection"); + return true; case offsetPopper: HandleBuiltInOffsetPop (code, scope); - return true; + output.WriteLine(".popsection"); + return true; case assertion: HandleBuiltInAssert (code, scope); @@ -349,13 +668,92 @@ private bool HandleBuiltInCodeWrite(Code code, ScopeStructure scope) { case protectCode: return true; - default: - return false; + case ThumbAssembly: + HandleThumbAssembly (code, scope, output); + return true; + + case ARMAssembly: + HandleARMAssembly (code, scope, output); + return true; + + case ExternSymbol: + output.WriteLine("\t.extern {0}", code.Parameters[0]); + return true; + + case GlobalSymbol: + output.WriteLine("\t.global {0}", code.Parameters[0]); + return true; + + case sectionMaker: + output.WriteLine("@section {0} 0x{1:X}", code.Parameters[0], Convert.ToInt32(code.Parameters[1].ToString())); + return true; + + case sectionEnd: + output.WriteLine(".previous"); + return true; + + default: + return false; } } - private void HandleBuiltInOffsetChange(Code code, ScopeStructure scope) { + private bool HandleBuiltInCodeWrite(Code code, ScopeStructure scope) + { + switch (code.CodeName.Name) + { + + case messagePrinterCode: + this.log.AddMessage(this.ExpressionToString((IExpression)code, scope).Substring(code.CodeName.Name.Length + 1)); + return true; + + case errorPrinterCode: + this.log.AddError(this.ExpressionToString((IExpression)code, scope).Substring(code.CodeName.Name.Length + 1)); + return true; + + case warningPrinterCode: + this.log.AddWarning(this.ExpressionToString((IExpression)code, scope).Substring(code.CodeName.Name.Length + 1)); + return true; + + case currentOffsetCode: + case offsetAligner: + HandleBuiltInOffsetAlign(code, scope); + return true; + + case offsetChanger: + HandleBuiltInOffsetChange(code, scope); + return true; + + case offsetPusher: + HandleBuiltInOffsetPush(code, scope); + return true; + + case offsetPopper: + HandleBuiltInOffsetPop(code, scope); + return true; + + case assertion: + HandleBuiltInAssert(code, scope); + return true; + + case protectCode: + return true; + + case ThumbAssembly: + case ARMAssembly: + case ExternSymbol: + case GlobalSymbol: + case sectionMaker: + case sectionEnd: + return true; + + default: + return false; + + } + } + + private void HandleBuiltInOffsetChange(Code code, ScopeStructure scope) { if (code.ParameterCount.IsInRange (1, 1) && !(code [0] is ExpressionList)) { CanCauseError canCauseError = Folding.Fold (code [0], (x => this.GetSymbolValue (scope, x))); if (!canCauseError.CausedError) diff --git a/Event Assembler/Core/Code/LanguageProcessor.cs b/Event Assembler/Core/Code/LanguageProcessor.cs index 5da63e8..a750940 100644 --- a/Event Assembler/Core/Code/LanguageProcessor.cs +++ b/Event Assembler/Core/Code/LanguageProcessor.cs @@ -50,7 +50,7 @@ public LanguageProcessor (bool collectDocComments, IComparer equa this.languages = new Dictionary (); } - public void ProcessCode (string folder, string extension) + public void ProcessCode (string folder, bool recursive, string extension) { if (!Directory.Exists (folder)) throw new DirectoryNotFoundException ("Folder " + folder + " not found."); @@ -59,7 +59,7 @@ public void ProcessCode (string folder, string extension) folder = Path.GetFullPath (folder); - FileInfo[] files = directoryInfo.GetFiles ("*" + extension, SearchOption.AllDirectories); + FileInfo[] files = directoryInfo.GetFiles ("*" + extension, recursive ? SearchOption.AllDirectories: SearchOption.TopDirectoryOnly); this.elements = (IDictionary>)new Dictionary> (); diff --git a/Event Assembler/Core/Code/ScopeStructure`1.cs b/Event Assembler/Core/Code/ScopeStructure`1.cs index 31695e6..669b8fa 100644 --- a/Event Assembler/Core/Code/ScopeStructure`1.cs +++ b/Event Assembler/Core/Code/ScopeStructure`1.cs @@ -8,6 +8,7 @@ using Nintenlord.Event_Assembler.Core.Code.Language.Expression; using Nintenlord.Utility; using System.Collections.Generic; +using System.Linq; namespace Nintenlord.Event_Assembler.Core.Code { @@ -16,12 +17,16 @@ public sealed class ScopeStructure : ITree> private readonly ScopeStructure ParentScope; private List> childScopes; private Dictionary> definedSymbols; + private Dictionary localLabels; // local labels + private List ASMCLabels; // extern labels public ScopeStructure(ScopeStructure parentScope) { this.ParentScope = parentScope; this.childScopes = new List>(); this.definedSymbols = new Dictionary>(); + this.localLabels = new Dictionary(); + this.ASMCLabels = new List(); } public void AddChildScope(ScopeStructure newChildScope) @@ -49,7 +54,39 @@ public CanCauseError AddNewSymbol(string symbol, IExpression value) definedSymbols[symbol] = value; return CanCauseError.NoError; } + + public int GetLocalLabelAddress(string labelName) + { + if(localLabels.ContainsKey(labelName)) + return localLabels[labelName]; + return 0; + } + + public void SetLocalLabelAddress(string labelName, int labelAddress) + { + if(localLabels.ContainsKey(labelName)) + localLabels[labelName] = labelAddress; + else + localLabels.Add(labelName, labelAddress); + } + public bool IsLocalLabelExisted(string labelName) + { + if (localLabels.ContainsKey(labelName)) + return true; + return false; + } + + public void RegisterASMCLabel(string labelName) + { + ASMCLabels.Add(labelName); + } + + public List GetRegisteredASMCLabels() + { + return ASMCLabels.Distinct().ToList(); + } + public bool IsGlobalScope() { return (ParentScope == null); diff --git a/Event Assembler/Core/Code/Templates/CodeTemplate.cs b/Event Assembler/Core/Code/Templates/CodeTemplate.cs index 38c307e..696124d 100644 --- a/Event Assembler/Core/Code/Templates/CodeTemplate.cs +++ b/Event Assembler/Core/Code/Templates/CodeTemplate.cs @@ -37,6 +37,23 @@ internal sealed class CodeTemplate : ICodeTemplate, INamed, IParameteriz private readonly List fixedParameters; private IPointerMaker pointerMaker; private readonly StringComparer comparer; + private Dictionary localLabels; + private Dictionary externLabels; + + public Dictionary GetLocalLabels() + { + return localLabels.OrderBy(o => o.Key).ToDictionary(o => o.Key, p => p.Value); + } + + public Dictionary GetExternLabels() + { + return externLabels.OrderBy(o => o.Key).ToDictionary(o => o.Key, p => p.Value); + } + + public void AddExternLabel(int pos, string labelName) + { + externLabels.Add(pos, labelName); + } public IPointerMaker PointerMaker { @@ -190,6 +207,8 @@ public CodeTemplate(string name, int id, int lenght, IEnumerable(parameters.Count()); this.fixedParameters = new List(parameters.Count()); this.baseData = new byte[this.LengthInBytes]; + localLabels = new Dictionary { }; + externLabels = new Dictionary { }; if (id != 0) { this.baseData[0] = (byte) (id & (int) byte.MaxValue); @@ -266,18 +285,32 @@ private byte[] GetDataUnit(string[] text, ILog messageLog) return code; } - private CanCauseError GetDataUnit(IExpression[] parameters, Func getSymbolValue) + public CanCauseError GetDataUnit(IExpression[] parameters, Func getSymbolValue, ScopeStructure scope) { byte[] code = this.baseData.Clone() as byte[]; + localLabels.Clear(); + externLabels.Clear(); for (int index = 0; index < parameters.Length; ++index) { TemplateParameter paramTemp = this[index]; if (paramTemp.lenght > 0) { - CanCauseError values = CodeTemplate.GetValues(parameters[index], paramTemp, getSymbolValue, this.pointerMaker); - if (values.CausedError) - return values.ConvertError(); - paramTemp.InsertValues(values.Result, code); + if (scope.GetRegisteredASMCLabels().Exists(o => o == parameters[index].ToString()) && !scope.IsLocalLabelExisted(parameters[index].ToString())) + { + paramTemp.InsertValues(new int [1], code); + AddExternLabel(paramTemp.position / 8, parameters[index].ToString()); + } + else + { + CanCauseError values = CodeTemplate.GetValues(parameters[index], paramTemp, getSymbolValue, this.pointerMaker); + if (values.CausedError) + return values.ConvertError(); + paramTemp.InsertValues(values.Result, code); + if (scope.IsLocalLabelExisted(parameters[index].ToString())) + { + localLabels.Add(paramTemp.position / 8, parameters[index].ToString()); + } + } } } return (CanCauseError) code; @@ -300,7 +333,7 @@ internal static CanCauseError GetValues(IExpression parameter, Templ } else { - CanCauseError canCauseError = Folding.Fold(parameter, getSymbolValue); + CanCauseError canCauseError = Folding.Fold(parameter, getSymbolValue); if (canCauseError.CausedError) return canCauseError.ConvertError(); if (paramTemp.pointer && pointerMaker != null) @@ -411,10 +444,10 @@ public int GetLengthBytes(IExpression[] code) return this.LengthInBytes; } - public CanCauseError GetData(IExpression[] code, Func getSymbolValue) + public CanCauseError GetData(IExpression[] code, Func getSymbolValue, ScopeStructure scope) { if (!canBeRepeated) - return GetDataUnit(code, getSymbolValue); + return GetDataUnit(code, getSymbolValue, scope); if (code.Length == 0) return CanCauseError.Error("Encountered {0} code with no parameters", Name); @@ -424,7 +457,7 @@ public CanCauseError GetData(IExpression[] code, Func for (int index = 0; index < num; ++index) { - CanCauseError dataUnit = GetDataUnit(new IExpression[1]{ code[index] }, getSymbolValue); + CanCauseError dataUnit = GetDataUnit(new IExpression[1]{ code[index] }, getSymbolValue, scope); if (dataUnit.CausedError) return dataUnit.ConvertError(); diff --git a/Event Assembler/Core/Code/Templates/ICodeTemplate.cs b/Event Assembler/Core/Code/Templates/ICodeTemplate.cs index 688b765..1883394 100644 --- a/Event Assembler/Core/Code/Templates/ICodeTemplate.cs +++ b/Event Assembler/Core/Code/Templates/ICodeTemplate.cs @@ -7,6 +7,7 @@ using Nintenlord.Event_Assembler.Core.Code.Language.Expression; using Nintenlord.Utility; using System; +using System.Collections.Generic; namespace Nintenlord.Event_Assembler.Core.Code.Templates { @@ -30,7 +31,11 @@ public interface ICodeTemplate : INamed, IParameterized int GetLengthBytes(IExpression[] parameters); - CanCauseError GetData(IExpression[] parameters, Func getSymbolValue); + CanCauseError GetData(IExpression[] parameters, Func getSymbolValue, ScopeStructure scope); + + Dictionary GetLocalLabels(); + + Dictionary GetExternLabels(); bool Matches(byte[] data, int offset); diff --git a/Event Assembler/Core/Code/Templates/TerminatingStringTemplate.cs b/Event Assembler/Core/Code/Templates/TerminatingStringTemplate.cs index 5022346..ddd7cc9 100644 --- a/Event Assembler/Core/Code/Templates/TerminatingStringTemplate.cs +++ b/Event Assembler/Core/Code/Templates/TerminatingStringTemplate.cs @@ -146,12 +146,22 @@ public bool Matches(Language.Types.Type[] code) return true; } + public Dictionary GetLocalLabels() + { + return new Dictionary { }; + } + + public Dictionary GetExternLabels() + { + return new Dictionary { }; + } + public int GetLengthBytes(IExpression[] code) { return (code.Length + 1) * this.parameter.LenghtInBytes; } - public CanCauseError GetData(IExpression[] code, Func getSymbolValue) + public CanCauseError GetData(IExpression[] code, Func getSymbolValue, ScopeStructure scope) { List byteList = new List(32); for (int index = 0; index < code.Length; ++index) diff --git a/Event Assembler/Core/Core.csproj b/Event Assembler/Core/Core.csproj index f1a3e6b..39e0b4e 100644 --- a/Event Assembler/Core/Core.csproj +++ b/Event Assembler/Core/Core.csproj @@ -1,216 +1,18 @@ - - - + - Debug - AnyCPU - {224C71E2-5E52-4910-910A-6FA9C2F937BE} - Exe - Core - v4.0 - 512 - Nintenlord.Event_Assembler.Core - - false - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 1 - 11.0.0.%2a - false - true + net6.0 + Library + enable - - true - full - false - bin\Debug - DEBUG;TRACE - prompt - 4 - true - false - - - AnyCPU - pdbonly - true - bin\Release - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - - - - - False - Microsoft .NET Framework 4 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 4.5 - true - + - - {8FA48EF8-3E11-494A-B587-592D7C22EFDF} - Nintenlord - + + + + + + - \ No newline at end of file diff --git a/Event Assembler/Core/Program.cs b/Event Assembler/Core/Program.cs index d312bbc..3d2aa4c 100644 --- a/Event Assembler/Core/Program.cs +++ b/Event Assembler/Core/Program.cs @@ -37,15 +37,18 @@ public enum RunExecType GenPNHighlight, Assemble, Disassemble, + Compile, } public RunExecType execType; public bool quiet = false; + public bool org = true; - public string language = null; + public string language = null; public string rawsFolder = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "Language Raws"); - public string rawsExtension = ".txt"; + public bool isRawsFolderRecursive = true; + public string rawsExtension = ".txt"; public bool isDirectory = true; public bool addEndGuards = false; public string inputFile = null; @@ -107,6 +110,11 @@ public static bool CodesLoaded { private static int Main (string[] args) { + if (args.Length == 0) { + Console.WriteLine("No parameter. Please read doc."); + return -1; + } + TextWriterMessageLog writerMessageLog = new TextWriterMessageLog (Console.Error); StreamWriter logWriter = null; @@ -126,9 +134,10 @@ private static int Main (string[] args) Program.MakeDoc ( Program.RunConfig.outputFile, Program.RunConfig.rawsFolder, - Program.RunConfig.rawsExtension, + Program.RunConfig.isRawsFolderRecursive, + Program.RunConfig.rawsExtension, Program.RunConfig.isDirectory, - Program.RunConfig.docHeader, + Program.RunConfig.docHeader, Program.RunConfig.docFooter ); @@ -156,7 +165,10 @@ private static int Main (string[] args) case ProgramRunConfig.RunExecType.Assemble: Program.Assemble ((ILog)writerMessageLog); break; - + + case ProgramRunConfig.RunExecType.Compile: + Program.Compile ((ILog)writerMessageLog); + break; } } @@ -187,11 +199,12 @@ public static void Assemble (string inputFile, string outputFile, string languag } // EA GUI Entry point - public static void LoadCodes (string rawsFolder, string extension, bool isDirectory, bool collectDocCodes) + public static void LoadCodes (string rawsFolder, string extension, bool isDirectory, bool isDirectoryRecursive, bool collectDocCodes) { Program.RunConfig.rawsFolder = rawsFolder; Program.RunConfig.rawsExtension = extension; Program.RunConfig.isDirectory = isDirectory; + Program.RunConfig.isRawsFolderRecursive = isDirectoryRecursive; LoadCodes (collectDocCodes); } @@ -252,6 +265,11 @@ private static ProgramRunConfig ReadProgramArguments (string[] args, ILog log) case "disassemble": result.execType = ProgramRunConfig.RunExecType.Disassemble; break; + + case "C": + case "compile": + result.execType = ProgramRunConfig.RunExecType.Compile; + break; default: log.AddError ("Unknown run mode `{0}`", it.Current); @@ -264,6 +282,7 @@ private static ProgramRunConfig ReadProgramArguments (string[] args, ILog log) switch (result.execType) { case ProgramRunConfig.RunExecType.Assemble: + case ProgramRunConfig.RunExecType.Compile: case ProgramRunConfig.RunExecType.Disassemble: if (!it.MoveNext ()) { log.AddError ("You need to specify a game for which to (dis)assemble!"); @@ -284,8 +303,15 @@ private static ProgramRunConfig ReadProgramArguments (string[] args, ILog log) continue; } - // -raws - if (it.Current.Equals ("-raws")) { + // ignore ORG + if (it.Current.Equals("-ignoreORG")) + { + result.org = false; + continue; + } + + // -raws + if (it.Current.Equals ("-raws")) { if (!it.MoveNext ()) { log.AddError ("`-raws` passed without specifying a path."); return null; @@ -716,8 +742,7 @@ private static void Assemble (ILog log) EACodeLanguage language = Program.languages [Program.RunConfig.language]; - EAExpressionAssembler assembler = new EAExpressionAssembler (language.CodeStorage, new TokenParser (new Func (StringExtensions.GetValue))); - assembler.Assemble (inputStream, output, log); + language.Assemble (inputStream, output, log); if (Program.RunConfig.symbolOutputFile != null) { // Outputting global symbols to another file @@ -728,7 +753,7 @@ private static void Assemble (ILog log) using (FileStream fileStream = File.OpenWrite (Program.RunConfig.symbolOutputFile)) using (StreamWriter symOut = new StreamWriter (fileStream)) - foreach (KeyValuePair symbol in assembler.GetGlobalSymbols()) + foreach (KeyValuePair symbol in language.GetGlobalSymbols()) symOut.WriteLine ("{0}={1}", symbol.Key, symbol.Value.ToHexString ("$")); } catch (Exception e) { log.AddError (e.ToString ()); @@ -754,6 +779,98 @@ private static void Assemble (ILog log) if (inputIsFile) input.Close (); } + + private static void Compile (ILog log) + { + TextReader input; + bool inputIsFile; + + if (Program.RunConfig.inputFile != null) { + input = File.OpenText (Program.RunConfig.inputFile); + inputIsFile = false; + } else { + input = Console.In; + inputIsFile = true; + } + + using (IDirectivePreprocessor preprocessor = new Preprocessor (log)) { + // preprocessor.AddReserved (eaCodeLanguage.GetCodeNames ()); + preprocessor.AddDefined (new string[] { "_" + Program.RunConfig.language + "_", "_EA_" }); + + DependencyMakingIncludeListener depMaker = null; + + if (Program.RunConfig.ppDepEnable) { + depMaker = new DependencyMakingIncludeListener (); + preprocessor.IncludeListener = depMaker; + } + + using (IInputStream inputStream = new PreprocessingInputStream (input, preprocessor)) { + if (Program.RunConfig.ppSimulation) { + // preprocess to null output + while (inputStream.ReadLine () != null) + ; + } else { + if (Program.RunConfig.outputFile == null) { + log.AddError ("No output file specified for assembly."); + return; + } + + string outFile = Program.RunConfig.outputFile; + + if (File.Exists (outFile) && File.GetAttributes (outFile).HasFlag ((Enum)FileAttributes.ReadOnly)) { + log.AddError ("File `{0}` exists and cannot be written to.", outFile); + return; + } + + using (StreamWriter output = new StreamWriter(outFile, false, Encoding.Default)) { + // Make entry point label global to call in C source file + //TODO support ARM? + output.WriteLine("\t.section .rodata"); + output.WriteLine("\t.align 2"); + output.WriteLine("\t.global " + Path.GetFileNameWithoutExtension(outFile).Replace(".", "_")); + output.WriteLine(Path.GetFileNameWithoutExtension(outFile).Replace(".", "_") + ":"); + + if (!Program.CodesLoaded) + LoadCodes (false); + + // Console.WriteLine("language: {0}", Program.RunConfig.language); + EACodeLanguage language = Program.languages [Program.RunConfig.language]; + + language.Compile (inputStream, output, log); + + if (Program.RunConfig.symbolOutputFile != null) { + // Outputting global symbols to another file + + try { + if (File.Exists (Program.RunConfig.symbolOutputFile)) + File.Delete (Program.RunConfig.symbolOutputFile); + + using (FileStream fileStream = File.OpenWrite (Program.RunConfig.symbolOutputFile)) + using (StreamWriter symOut = new StreamWriter (fileStream)) + foreach (KeyValuePair symbol in language.GetGlobalSymbols()) + symOut.WriteLine ("{0}={1}", symbol.Key, symbol.Value.ToHexString ("$")); + } catch (Exception e) { + log.AddError (e.ToString ()); + } + } + + output.Close(); + } + } + } + + if (depMaker != null) { + try { + depMaker.GenerateMakeDependencies (log); + } catch (Exception e) { + log.AddError (e.ToString ()); + } + } + } + + if (inputIsFile) + input.Close (); + } private static void Disassemble (ILog log) { if (!File.Exists (Program.RunConfig.inputFile)) { @@ -866,7 +983,7 @@ private static void LoadCodes(bool collectDoc) { IPointerMaker pointerMaker = (IPointerMaker)new GBAPointerMaker (); if (Program.RunConfig.isDirectory) - languageProcessor.ProcessCode (Program.RunConfig.rawsFolder, Program.RunConfig.rawsExtension); + languageProcessor.ProcessCode (Program.RunConfig.rawsFolder, Program.RunConfig.isRawsFolderRecursive, Program.RunConfig.rawsExtension); else languageProcessor.ProcessCode (Program.RunConfig.rawsFolder); @@ -880,11 +997,12 @@ private static void LoadCodes(bool collectDoc) { break; case "FE7": + case "FE7J": pointerList = FE7CodeLanguage.PointerList; break; case "FE8": - // pointerList = DummyCodeLanguage.PointerList; + case "FE8J": pointerList = FE8CodeLanguage.PointerList; break; @@ -906,12 +1024,12 @@ private static void LoadCodes(bool collectDoc) { } } - public static void MakeDoc (string output, string rawsFolder, string extension, bool isDirectory, string header, string footer) + public static void MakeDoc (string output, string rawsFolder, bool isRawsFolderRecursive, string extension, bool isDirectory, string header, string footer) { LanguageProcessor languageProcessor = new LanguageProcessor (true, (IComparer)new TemplateComparer (), Program.stringComparer); if (isDirectory) - languageProcessor.ProcessCode (rawsFolder, extension); + languageProcessor.ProcessCode (rawsFolder, isRawsFolderRecursive, extension); else languageProcessor.ProcessCode (rawsFolder); diff --git a/Event Assembler/Core/Properties/Resources.Designer.cs b/Event Assembler/Core/Properties/Resources.Designer.cs index c4b3f39..c5774b8 100644 --- a/Event Assembler/Core/Properties/Resources.Designer.cs +++ b/Event Assembler/Core/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ @@ -13,13 +13,13 @@ namespace Nintenlord.Event_Assembler.Core.Properties { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// 一个强类型的资源类,用于查找本地化的字符串等。 /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -33,7 +33,7 @@ internal Resources() { } /// - /// Returns the cached ResourceManager instance used by this class. + /// 返回此类使用的缓存的 ResourceManager 实例。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ internal Resources() { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { diff --git a/Event Assembler/Core/app.config b/Event Assembler/Core/app.config deleted file mode 100644 index fcd0c93..0000000 --- a/Event Assembler/Core/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/Event Assembler/Event Assembler/Event Assembler.csproj b/Event Assembler/Event Assembler/Event Assembler.csproj index 449cce5..2398dd7 100644 --- a/Event Assembler/Event Assembler/Event Assembler.csproj +++ b/Event Assembler/Event Assembler/Event Assembler.csproj @@ -325,9 +325,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest diff --git a/Event Assembler/Event Assembler/NppEASyntax.xml b/Event Assembler/Event Assembler/NppEASyntax.xml new file mode 100644 index 0000000..d36d1af --- /dev/null +++ b/Event Assembler/Event Assembler/NppEASyntax.xml @@ -0,0 +1,64 @@ + + + + + + + + 00// 01 02 03/* 04*/ + + 0x $ + a b c d e f A B C D E F + + + b + + ( ) [ ] , : " ; + - * / % << >> < > + + + + + + + + + + + #include #define #undef #ifndef #ifdef #endif #else #incbin #incext #runext #inctext + ORG CURRENTOFFSET MESSAGE ERROR WARNING PUSH POP ASSERT + _0x + ASMC ASMC2 CAM1 CAM2 CMON CMOF GOTO_IFAT GOTO_IFAF GOTO LABEL CHECK_MODE CHECK_HARD CHECK_TURNS CHECK_ENEMIES CHECK_OTHERS CHECK_SKIRMISH CHECK_TUTORIAL CHECK_MONEY CHECK_EVENTID CHECK_POSTGAME CHECK_CHAPTER_NUMBER BEQ BNE BGE BGT BLE BLT GOTO_IFEF GOTO_IFET GOTO_IFNHM GOTO_IFNEM GOTO_IFNO GOTO_IFYES GOTO_IFNTUTORIAL GOTO_IFTU CHECK_EVENTID CHECK_EVBIT GOTO_IFNUF GOTO_IFCA GOTO_IFCNA GOTO_IFCL CHECK_ACTIVE CHECK_EXISTS CHECK_STATUS CHECK_ALIVE CHECK_DEPLOYED CHECK_ACTIVEID CHECK_ALLEGIANCE CHECK_COORDS CHECK_CLASS CHECK_LUCK FADI FADU FAWI FAWU FADICG FADUCG HIDEMAP SHOWMAP REMA RETB REBU BACG REMOVEPORTRAITS FROMCGTOBG FROMBGTOCG FROMCGTOMAP LCKB LCKS ULCK NEVENTS NSSP NCONVOS NCSP TEX1 TEXT MORETEXT TEX2 TEXTIFEM MORETEXTIFEM TEXTCG MORETEXTCG TEX6 TEX8 TEXTIFTACTF MORETEXTIFTACTF TEXTIFEVENTID MORETEXTIFEVENTID TEXTIFASM MORETEXTIFASM NOTIFY BROWNBOXTEXT TEXTSTART TUTORIALTEXTBOXSTART SOLOTEXTBOXSTART TEXTSHOW TEXTSHOW2 TEXTCONT TEXTEND CURF CUMO CURE ENDA ENDB THE_END LYN_END ENUT ENUF ENUT_SLOT2 ENUF_SLOT2 EVBIT_T EVBIT_F EVBIT_MODIFY CALL JUMP ITGC ITGM ITGV SHLI GIVEITEMTO GIVEITEMTOMAIN MONE MAC1 MACC MAC2 MAC3 MACE TILECHANGE TILEREVERSE LOMA SVAL SETVAL SMOV SADD SSUB SMUL SDIV SAND SORR SXOR SLSL SLOTS_LEFTSHIFT SLSR SLOTS_RIGHTSHIFT SLOTS_SETFROMQUEUE SAVETOQUEUE STQFROMSLOT COUNTER_CHECK COUNTER_SET COUNTER_ADD COUNTER_SUBTRACT RANDOMNUMBER STARTFADE ENDFADE FADECOLORS EARTHQUAKE_START EARTHQUAKE_END GLOWING_CROSS END_GLOWING_CROSS BREAKING_SACRED_STONE MNCH MNC2 MNC3 MNC4 MNTS MOVE MOVENEXTTO MOVEMAINC REPOS MOVEONTO MOVE_1STEP MOMA MUSC MUSS MUSM SOUN MURE MUSCFAST MUSCMID MUSCSLOW SUDDENMUS MUSI MUNO MUEN OOBB STAL STAL2 STAL3 CGSTAL CHAI CHAI2 CUSI CUSA CUSE CUSN UNCM UNCR SET_HP SET_ENDTURN SET_STATE SET_SOMETHING DISA_IF DISA REMU CLEA CLEN CLEE ENUN FIGH BLDT FIG1 FIG2 GIVETO GIVETOMAIN GIVETOSLOT3 KILL LOU1 LOU2 LOUMODE1 LOUMODE2 LOEV LOADSINGLEUNIT LOUFILTERED LOUFILTERED2 LOAD1 LOAD_SLOT1 LOAD2 LOAD3 LOAD4 MOVEFORCED PROM REPA REVEAL RESUMM WARP WARP_OUT VCBF VCWF WEA1 WEA2 ASMWORLDMAP WM_FADEOUT WM_SHOWDRAWNMAP SKIPWN WM_SETCAM WM_CENTERCAMONLORD WM_MOVECAM WM_MOVECAMTO WM_MOVECAM2 LOADWM HIGHLIGHT FADETOWM PLACEDOT RIPPLE WM_DRAWPATH WM_DRAWPATH2 WM_REMOVEPATH WM_LOADLOCATION2 WM_REMOVELOCATION WM_LOADLOCATION3 DRAWPATH3 WM_CREATENEXTDESTINATION WM_SETDESTINATION WM_HIGHLIGHT WM_HIGHLIGHTCLEAR1 WM_HIGHLIGHTCLEAR2 WM_FXCLEAR1 WM_FXCLEAR2 ZOOMTO ZOOMOUT SHOWARROW REMOVE2 REMOVE1 PLACEFLAG REMOVE4 REMOVE3 PUTSPRITE WM_MAKELORDVISIBLE WM_MAKELORDDISAPPEAR WM_FADEINSPRITE WM_FADEOUTSPRITE WM_WAITFORSPRITELOAD WM_PUTSPRITE WM_PUTMOVINGSPRITE WM_MOVESPRITETO WM_SPAWNLORD REMSPRITE SHOWPORTRAIT REMOVEPORTRAIT WM_SHOWPORTRAIT WM_CLEARPORTRAIT WM_WAITFORCAM WM_WAITFORFX WM_WAITFORSPRITES WM_WAITFORTEXT WM_WAITFORFXCLEAR1 WM_WAITFORFXCLEAR2 TEXTWM TEXTBOXTOTOP TEXTBOXTOBOTTOM SCRO REMOVETEXTBOX WM_SHOWTEXTWINDOW WM_TEXTDECORATE WM_TEXT WM_TEXTSTART WM_REMOVETEXT SHOWMAPTEXT CLEAN PREP + POIN WORD SHORT BYTE + TURN LOCA AFEV END_MAIN ENDTRAP CHESRANDOM VILL SHOP CHES DOOR AREA CHAR CHARASM SHOP ASME UNKWON UNKWON2 COORDS END TURN_HM BLST FIRE GAST ARROW EGG UNIT REDA + _SATURATE_COLORS MOVIMM MOV _ASM2 _IF0x21 _MOVE0x2C _ASM0x3F _ASM0x42 _IF0x4A _IF0x4B _IFTT2 _ASM0x59 _ASM0x5A _FADI2 _FADU2 _LIGHTNING TUTORIAL_CALL _MUSICSOMETHING _WARP SLOTS_UNKNOWN STORETOSOMETHING + SECTION GLOBAL EXTERN T A ALIGN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Nintenlord/Collections/CollectionExtensions.cs b/Nintenlord/Collections/CollectionExtensions.cs index 92c4ab9..573f677 100644 --- a/Nintenlord/Collections/CollectionExtensions.cs +++ b/Nintenlord/Collections/CollectionExtensions.cs @@ -21,82 +21,6 @@ public static bool And(this IEnumerable collection) return collection.All(x => x); } - public static T Max(this IEnumerable collection) where T : IComparable - { - var enumerator = collection.GetEnumerator(); - if (!enumerator.MoveNext()) - { - throw new ArgumentException("Empty IEnumerable", "collection"); - } - T max = enumerator.Current; - while (enumerator.MoveNext()) - { - T current = enumerator.Current; - if (current.CompareTo(max) > 0) - { - max = current; - } - } - return max; - } - - public static T Max(this IEnumerable collection, IComparer comp) - { - var enumerator = collection.GetEnumerator(); - if (!enumerator.MoveNext()) - { - throw new ArgumentException("Empty IEnumerable", "collection"); - } - T max = enumerator.Current; - while (enumerator.MoveNext()) - { - T current = enumerator.Current; - if (comp.Compare(current, max) > 0) - { - max = current; - } - } - return max; - } - - public static T Min(this IEnumerable collection) where T : IComparable - { - var enumerator = collection.GetEnumerator(); - if (!enumerator.MoveNext()) - { - throw new ArgumentException("Empty IEnumerable", "collection"); - } - T min = enumerator.Current; - while (enumerator.MoveNext()) - { - T current = enumerator.Current; - if (current.CompareTo(min) < 0) - { - min = current; - } - } - return min; - } - - public static T Min(this IEnumerable collection, IComparer comp) - { - var enumerator = collection.GetEnumerator(); - if (!enumerator.MoveNext()) - { - throw new ArgumentException("Empty IEnumerable", "collection"); - } - T min = enumerator.Current; - while (enumerator.MoveNext()) - { - T current = enumerator.Current; - if (comp.Compare(current, min) < 0) - { - min = current; - } - } - return min; - } - public static string ToElementWiseString(this IEnumerable collection) { StringBuilder text = new StringBuilder("{"); diff --git a/Nintenlord/Collections/Lists/LinkedArrayList.cs b/Nintenlord/Collections/Lists/LinkedArrayList.cs index 7d7a869..d14053c 100644 --- a/Nintenlord/Collections/Lists/LinkedArrayList.cs +++ b/Nintenlord/Collections/Lists/LinkedArrayList.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using Nintenlord.Utility.Primitives; -using System.Diagnostics.Contracts; namespace Nintenlord.Collections.Lists { @@ -22,8 +21,8 @@ public T First { get { - Contract.Requires - (count > 0, "Can't take the first of empty collection."); + if (count <= 0) + throw new Exception("Can't take the first of empty collection."); return items[firstReservedIndex]; } @@ -32,8 +31,9 @@ public T Last { get { - Contract.Requires - (count > 0, "Can't take the last of empty collection."); + + if (count <= 0) + throw new Exception("Can't take the last of empty collection."); return firstFreeIndex > 0 ? items[firstFreeIndex - 1] : items[items.Length - 1]; } @@ -191,7 +191,8 @@ private int Find(T item) private void InsertAtInternalIndex(int internalIndex, T item) { - Contract.Requires(count < items.Length); + if (count >= items.Length) + throw new Exception("No enough room to insert."); //There is always room on the array at this point if (firstReservedIndex < firstFreeIndex) @@ -447,7 +448,8 @@ public int IndexOf(T item) public void Insert(int index, T item) { - Contract.Requires(index >= 0 && index <= count); + if (index < 0 || index > count) + throw new IndexOutOfRangeException(); if (index == count) { @@ -465,7 +467,8 @@ public void Insert(int index, T item) public void RemoveAt(int index) { - Contract.Requires(index >= 0 && index < count); + if (index < 0 || index >= count) + throw new IndexOutOfRangeException(); RemoveAtInternal(ToInternalIndex(index)); } diff --git a/Nintenlord/Grammars/ContextFreeGrammar.cs b/Nintenlord/Grammars/ContextFreeGrammar.cs index 18341d5..ba4628f 100644 --- a/Nintenlord/Grammars/ContextFreeGrammar.cs +++ b/Nintenlord/Grammars/ContextFreeGrammar.cs @@ -16,11 +16,15 @@ namespace Nintenlord.Grammars /// public sealed class ContextFreeGrammar { + #pragma warning disable 0649 + IDictionary productions; T startingSymbol; T[] variables; T[] terminals; + #pragma warning restore 0649 + public T[][] this[T variable] { get diff --git a/Nintenlord/Grammars/PushdownAutomata.cs b/Nintenlord/Grammars/PushdownAutomata.cs index 327ab02..0ebdb49 100644 --- a/Nintenlord/Grammars/PushdownAutomata.cs +++ b/Nintenlord/Grammars/PushdownAutomata.cs @@ -19,9 +19,14 @@ public class DeterministicPushdownAutomata Stack stack; Dictionary, Tuple> transitions; Dictionary, Tuple> epsilonTransitions; + + #pragma warning disable 0649 + TStackSymbol stackStartSymbol; TState startingState; + #pragma warning restore 0649 + public DeterministicPushdownAutomata() { epsilonTransitions = new Dictionary, Tuple>(); diff --git a/Nintenlord/Graph/GraphHelpers.cs b/Nintenlord/Graph/GraphHelpers.cs index 7d51a85..1eade90 100644 --- a/Nintenlord/Graph/GraphHelpers.cs +++ b/Nintenlord/Graph/GraphHelpers.cs @@ -22,12 +22,6 @@ public static class GraphHelpers public static bool HasCycle(this IGraph graph, out List cycle) { throw new NotImplementedException(); - - var DFS = graph.DepthFirstTraversalAllNodes( - GraphTraversal.DepthFirstTraversalOrdering.PostOrdering); - - //var tree = graph.DepthFirstSearch(); - } /// diff --git a/Nintenlord/Nintenlord.csproj b/Nintenlord/Nintenlord.csproj index 1e1903c..365fc6a 100644 --- a/Nintenlord/Nintenlord.csproj +++ b/Nintenlord/Nintenlord.csproj @@ -1,260 +1,27 @@ - - + - Debug - AnyCPU - 8.0.30703 - 2.0 - {8FA48EF8-3E11-494A-B587-592D7C22EFDF} + net6.0 Library - Properties - Nintenlord - Nintenlord - v4.0 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + false + x86;AnyCPU - true bin\x86\Debug\ - DEBUG;TRACE - full - x86 - prompt false false bin\x86\Release\ - TRACE - true - pdbonly - x86 - prompt false false false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - \ No newline at end of file + diff --git a/Nintenlord/Utility/SharedDirtyBuffer.cs b/Nintenlord/Utility/SharedDirtyBuffer.cs index fa86c41..0d43ae7 100644 --- a/Nintenlord/Utility/SharedDirtyBuffer.cs +++ b/Nintenlord/Utility/SharedDirtyBuffer.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Diagnostics.Contracts; namespace Nintenlord.Utility { @@ -41,7 +40,8 @@ public int Length public DirtyBufferUser(SharedDirtyBuffer listToUse) { - Contract.Requires(!listToUse.InUse, "Argument listToUse is already in use."); + if (listToUse.InUse) + throw new ArgumentException("Argument listToUse is already in use."); this.listToUse = listToUse; this.listToUse.InUse = true; diff --git a/README3.md b/README3.md new file mode 100644 index 0000000..f79407e --- /dev/null +++ b/README3.md @@ -0,0 +1,24 @@ +To respect Nintenlord and Crazycolorz5, I put what I need to say here. + +# Convert event scripts to assembly source files (C mode): +``` +Core.exe C game_version -input:xxx.event -output:xxx.s +``` +Supported *game_version* list: +- FE6 +- FE7 +- FE7J +- FE8 +- FE8J + +# Syntax differences in C mode: +* Extended syntax: + + GLOABL + + EXTERN + + SECTION + + ENDSECTION +* ORG can be skipped by -ignoreORG option + +# Inline assembly: +Begin with "T". +Experimental. Not supposed to use. diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..b58445a --- /dev/null +++ b/TODO.md @@ -0,0 +1,35 @@ +# TODO List: ++ Bugfix: to set end of a section ++ Feature: to handle PUSH & ORG & POP + +# Note: +``` +Stan 昨天晚上7点29分 +How hard do you think it would be for you to make those work by outputting those .ARM.__at_address sections (that may not work with gnu ld?) (or some other formatted section name, whatever works)? +Like PUSH; ORG $1234; WORD $DEADBEEF; POP would output .pushsection .ARM.__at_08001234, "ax"; .word 0xDEADBEEF; .popsection or something? +Stan 昨天晚上8点26分 +so you do +.pushsection .ARM.__at_0808388E, "ax" + nop +.popsection +so you do +.section .ARM.__at_0808388E, "ax" + nop +.previous +Stan 昨天晚上8点50分 +PUSH; ORG Somewhere + POIN MyHackThing +POP +// Free Space +ALIGN 4 +MyHackThing: + // Data +if you ignore the POP you are not writing in free space anymore +and that's a pretty big problem +Stan 昨天晚上9点12分 +.section .ARM.__at_0808388E, "ax" + nop +.previous +Stan 昨天晚上9点17分 +(using .pushsection/.popsection may be better than .previous tho but yes) +``` \ No newline at end of file