public void ScanRange(byte[] rom, int startAddress, int endAddress) { if (rom == null) { throw new ArgumentNullException(); } int address = startAddress; while (address < endAddress) { if (ControlCodePredicate(rom, address)) { IControlCode code = ControlCodes.FirstOrDefault(c => c.IsMatch(rom, address)); if (code == null) { throw new Exception("Control code not found"); } IList <int> references = code.GetReferences(rom, address); if (references != null) { LabelMap.AddRange(references); } address += code.ComputeLength(rom, address); } else { address++; } } }
public void ScanString(string str, ref int referenceAddress, IDictionary <byte, string> charLookup, bool scanCodesOnly, out IList <string> references, out ISet <IControlCode> controlCodes) { references = new List <string>(); controlCodes = new HashSet <IControlCode>(); for (int i = 0; i < str.Length;) { if (str[i] == '[') { if (str.IndexOf(']', i + 1) == -1) { throw new Exception("Opening bracket has no matching closing bracket: position " + i); } string[] codeStrings = str.Substring(i + 1, str.IndexOf(']', i + 1) - i - 1) .Split(' '); IControlCode code = ControlCodes.FirstOrDefault(c => c.IsMatch(codeStrings)); if (!controlCodes.Contains(code)) { controlCodes.Add(code); } foreach (var codeString in codeStrings) { if (codeString[0] == '_') { if (codeString[codeString.Length - 1] != '_') { throw new Exception("Reference has no closing underscore: position " + i); } if (codeString.Length <= 2) { throw new Exception("Reference is empty: position " + i); } if (!scanCodesOnly) { referenceAddress += 4; } references.Add(codeString.Substring(1, codeString.Length - 2)); } else if (IsHexByte(codeString)) { if (!scanCodesOnly) { referenceAddress++; } } else { throw new Exception(String.Format( "Encountered invalid code string at position {0}: {1}", i, codeString)); } } i = str.IndexOf(']', i + 1) + 1; } else if (str[i] == ']') { throw new Exception("Closing bracket has no matching opening bracket: position " + i); } else if (str[i] == '^') { if (str.IndexOf('^', i + 1) == -1) { throw new Exception("Label has no matching closing caret: position " + i); } string label = str.Substring(i + 1, str.IndexOf('^', i + 1) - i - 1); if (AddressMap.ContainsKey(label)) { throw new Exception("Label already defined: position " + i); } if (!scanCodesOnly) { AddressMap.Add(label, referenceAddress); } i = str.IndexOf('^', i + 1) + 1; } else { if (!(str[i] == '\r') && !(str[i] == '\n')) { if (!scanCodesOnly) { GetByte(str[i], charLookup); // just check if it's valid referenceAddress++; } } i++; } } }
public void CompileString(string str, IList <byte> buffer, ref int referenceAddress, IDictionary <byte, string> charLookup, int padLength) { int previousBufferSize = buffer.Count; for (int i = 0; i < str.Length;) { if (str[i] == '[') { if (str.IndexOf(']', i + 1) == -1) { throw new Exception("Opening bracket has no matching closing bracket: position " + i); } string[] codeStrings = str.Substring(i + 1, str.IndexOf(']', i + 1) - i - 1) .Split(' '); // Match the code IControlCode code = ControlCodes.FirstOrDefault(c => c.IsMatch(codeStrings)); if (code == null) { // Direct copy for (int j = 0; j < codeStrings.Length; j++) { if (!IsHexByte(codeStrings[j])) { throw new Exception("Code string for unrecognized control code block must be a byte literal: position " + i); } byte value = byte.Parse(codeStrings[j], System.Globalization.NumberStyles.HexNumber); if (buffer != null) { buffer.Add(value); } referenceAddress++; } } else { // Validate if (!code.IsValid(codeStrings)) { throw new Exception("Invalid control code: position " + i); } // Parse code.Compile(codeStrings, buffer, ref referenceAddress, AddressMap); } i = str.IndexOf(']', i + 1) + 1; } else if (str[i] == ']') { throw new Exception("Closing bracket has no matching opening bracket: position " + i); } else if (str[i] == '^') { if (str.IndexOf('^', i + 1) == -1) { throw new Exception("Label has no matching closing caret: position " + i); } i = str.IndexOf('^', i + 1) + 1; } else { if (!(str[i] == '\r') && !(str[i] == '\n')) { byte value = GetByte(str[i], charLookup); if (buffer != null) { buffer.Add(value); } referenceAddress++; } i++; } } // Pad the remaining bytes if (padLength != -1) { int bytesWritten = buffer.Count - previousBufferSize; if (bytesWritten > padLength) { throw new Exception("Exceeded pad length: wrote " + bytesWritten + " bytes, but the pad length is " + padLength + " bytes"); } for (int i = bytesWritten; i < padLength; i++) { if (buffer != null) { buffer.Add(0); } referenceAddress++; } } }
public string DecompileRange(byte[] rom, int startAddress, int endAddress, bool newLines) { if (rom == null) { throw new ArgumentNullException(); } var builder = new StringBuilder(); bool readUntilEnd = (endAddress == -1); bool ended = false; bool suppressNextEnd = false; int address = startAddress; while (!ended) { if (LabelMap.Labels.ContainsKey(address)) { builder.Append('^'); builder.Append(LabelMap.Labels[address]); builder.Append('^'); } if (ControlCodePredicate(rom, address)) { IControlCode code = ControlCodes.FirstOrDefault(c => c.IsMatch(rom, address)); if (code == null) { throw new Exception("Control code not found"); } // Check if it's compressed text if (code.IsCompressedString) { builder.Append(code.GetCompressedString(rom, address)); } else { IList <CodeString> codeStrings = code.GetCodeStrings(rom, address); var filtered = codeStrings.Select(cs => FilterCodeString(cs)).ToArray(); builder.Append(String.Format("[{0}]", String.Join(" ", filtered))); if (newLines && code.IsEnd && !suppressNextEnd) { builder.AppendLine(); } } address += code.ComputeLength(rom, address); /*if (newLines && code.IsEnd && !suppressNextEnd) * { * builder.Append("(" + address.ToString("X") + ")"); * }*/ if (readUntilEnd && code.IsEnd) { ended = true; } if (code.IsEnd) { suppressNextEnd = false; } else if (code.SuppressNextEnd == true) { suppressNextEnd = true; } } else { string str = GetChar(rom, address++); builder.Append(str); } if (!readUntilEnd && address >= endAddress) { ended = true; } } return(builder.ToString()); }