public void SetTokens(GR.Collections.MultiMap <string, SymbolInfo> TokenInfo) { if (InvokeRequired) { Invoke(new SetTokensCallback(SetTokens), new object[] { TokenInfo }); return; } comboSymbols.Items.Clear(); GR.Collections.Set <string> keys = TokenInfo.GetUniqueKeys(); foreach (var token in keys) { comboSymbols.Items.Add(token); } m_TokenInfos = TokenInfo; }
public GR.Collections.Set <FileDependency.DependencyInfo> GetDependencies(ProjectElement Element) { var dependencies = new GR.Collections.Set <FileDependency.DependencyInfo>(); foreach (var dependency in Element.ForcedDependency.DependentOnFile) { if (!dependencies.ContainsValue(dependency)) { dependencies.Add(dependency); ProjectElement otherElement = GetElementByFilename(dependency.Filename); if (otherElement != null) { dependencies.Merge(GetDependencies(otherElement)); } } } return(dependencies); }
public SymbolInfo(SymbolInfo RHS) { Type = RHS.Type; Name = RHS.Name; LineIndex = RHS.LineIndex; // global LineCount = RHS.LineCount; // global (-1 is for complete file) DocumentFilename = RHS.DocumentFilename; LocalLineIndex = RHS.LocalLineIndex; AddressOrValue = RHS.AddressOrValue; String = RHS.String; RealValue = RHS.RealValue; Zone = RHS.Zone; FromDependency = RHS.FromDependency; Info = RHS.Info; CharIndex = RHS.CharIndex; Length = RHS.Length; SourceInfo = RHS.SourceInfo; References = RHS.References; }
public string LabelsAsFile(LabelFileFormat Format) { StringBuilder sb = new StringBuilder(); var sentLabels = new GR.Collections.Set <int>(); foreach (var token in Labels) { if (token.Value.Type == SymbolInfo.Types.LABEL) { switch (Format) { case LabelFileFormat.VICE: // VICE now bails on values outside 16bit if ((token.Value.AddressOrValue >= 0) && (token.Value.AddressOrValue <= 65535) && (!sentLabels.ContainsValue(token.Value.AddressOrValue))) { sentLabels.Add(token.Value.AddressOrValue); sb.Append("add_label $"); sb.Append(token.Value.AddressOrValue.ToString("X4")); sb.Append(" ."); sb.AppendLine(token.Key.Replace('.', '_').Replace('-', '_').Replace("+", "plus")); } break; case LabelFileFormat.C64DEBUGGER: sb.Append("al C:"); sb.Append(token.Value.AddressOrValue.ToString("X4")); sb.Append(" ."); sb.AppendLine(token.Key.Replace('.', '_').Replace('-', '_').Replace("+", "plus")); break; } } } return(sb.ToString()); }
public override void Validate() { var files = Files(); GR.Collections.Set <GR.Generic.Tupel <int, int> > usedTracksAndSectors = new GR.Collections.Set <GR.Generic.Tupel <int, int> >(); usedTracksAndSectors.Add(new GR.Generic.Tupel <int, int>(TRACK_HEADER, SECTOR_HEADER)); usedTracksAndSectors.Add(new GR.Generic.Tupel <int, int>(TRACK_BAM, SECTOR_BAM)); int curTrack = TRACK_DIRECTORY; int curSector = SECTOR_DIRECTORY; usedTracksAndSectors.Add(new GR.Generic.Tupel <int, int>(curTrack, curSector)); while (true) { Sector sec = Tracks[curTrack - 1].Sectors[curSector]; curTrack = sec.Data.ByteAt(0); curSector = sec.Data.ByteAt(1); if (curTrack == 0) { // track = 0 marks last directory entry break; } usedTracksAndSectors.Add(new GR.Generic.Tupel <int, int>(curTrack, curSector)); } foreach (var file in files) { curTrack = file.StartTrack; curSector = file.StartSector; while (true) { Sector sec = Tracks[curTrack - 1].Sectors[curSector]; usedTracksAndSectors.Add(new GR.Generic.Tupel <int, int>(curTrack, curSector)); curTrack = sec.Data.ByteAt(0); curSector = sec.Data.ByteAt(1); if (curTrack == 0) { // track = 0 marks last directory entry break; } } } foreach (var track in Tracks) { foreach (var sector in track.Sectors) { if ((!sector.Free) && (!usedTracksAndSectors.ContainsValue(new GR.Generic.Tupel <int, int>(track.TrackNo, sector.SectorNo)))) { sector.Free = true; } } } }
private string MnemonicToString(Tiny64.Opcode opcode, GR.Memory.ByteBuffer Data, int DataStartAddress, int CodePos, GR.Collections.Set <ushort> AccessedAddresses, GR.Collections.Map <int, string> NamedLabels) { string output = opcode.Mnemonic.ToLower(); ushort targetAddress = 0; bool twoBytes = true; switch (opcode.Addressing) { case Tiny64.Opcode.AddressingType.IMPLICIT: break; case Tiny64.Opcode.AddressingType.ABSOLUTE: targetAddress = Data.UInt16At(CodePos + 1 - DataStartAddress); break; case Tiny64.Opcode.AddressingType.ABSOLUTE_X: targetAddress = Data.UInt16At(CodePos + 1 - DataStartAddress); break; case Tiny64.Opcode.AddressingType.ABSOLUTE_Y: targetAddress = Data.UInt16At(CodePos + 1 - DataStartAddress); break; case Tiny64.Opcode.AddressingType.IMMEDIATE: targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress); twoBytes = false; break; case Tiny64.Opcode.AddressingType.INDIRECT: targetAddress = Data.UInt16At(CodePos + 1 - DataStartAddress); break; case Tiny64.Opcode.AddressingType.ZEROPAGE_INDIRECT_X: targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress); twoBytes = false; break; case Tiny64.Opcode.AddressingType.ZEROPAGE_INDIRECT_Y: targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress); twoBytes = false; break; case Tiny64.Opcode.AddressingType.RELATIVE: { // int delta = value - lineInfo.AddressStart - 2; sbyte relValue = (sbyte)Data.ByteAt(CodePos + 1 - DataStartAddress); targetAddress = (ushort)(relValue + 2 + CodePos); } break; case Tiny64.Opcode.AddressingType.ZEROPAGE: targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress); twoBytes = false; break; case Tiny64.Opcode.AddressingType.ZEROPAGE_X: targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress); twoBytes = false; break; case Tiny64.Opcode.AddressingType.ZEROPAGE_Y: targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress); twoBytes = false; break; } string addressPlacement; if (twoBytes) { addressPlacement = "$" + targetAddress.ToString("x4"); } else { addressPlacement = "$" + targetAddress.ToString("x2"); } if (AccessedAddresses.ContainsValue(targetAddress)) { addressPlacement = "label_" + targetAddress.ToString("x4"); } if (NamedLabels.ContainsKey(targetAddress)) { addressPlacement = NamedLabels[targetAddress]; } switch (opcode.Addressing) { case Tiny64.Opcode.AddressingType.IMPLICIT: break; case Tiny64.Opcode.AddressingType.ABSOLUTE: output += " " + addressPlacement; break; case Tiny64.Opcode.AddressingType.ABSOLUTE_X: output += " " + addressPlacement + ", x"; break; case Tiny64.Opcode.AddressingType.ABSOLUTE_Y: output += " " + addressPlacement + ", y"; break; case Tiny64.Opcode.AddressingType.IMMEDIATE: output += " #" + addressPlacement; break; case Tiny64.Opcode.AddressingType.INDIRECT: output += " ( " + addressPlacement + " )"; break; case Tiny64.Opcode.AddressingType.ZEROPAGE_INDIRECT_X: output += " ( " + addressPlacement + ", x)"; break; case Tiny64.Opcode.AddressingType.ZEROPAGE_INDIRECT_Y: output += " ( " + addressPlacement + " ), y"; break; case Tiny64.Opcode.AddressingType.RELATIVE: { // int delta = value - lineInfo.AddressStart - 2; output += " " + addressPlacement; //output += " (" + delta.ToString( "X2" ) + ")"; } break; case Tiny64.Opcode.AddressingType.ZEROPAGE: output += " " + addressPlacement; break; case Tiny64.Opcode.AddressingType.ZEROPAGE_X: output += " " + addressPlacement + ", x"; break; case Tiny64.Opcode.AddressingType.ZEROPAGE_Y: output += " " + addressPlacement + ", y"; break; } return(output); }
public bool Disassemble(int DataStartAddress, GR.Collections.Set <int> JumpedAtAddresses, GR.Collections.Map <int, string> NamedLabels, DisassemblerSettings Settings, out string Disassembly, out int FirstLineWithOpcode) { StringBuilder sb = new StringBuilder(); Disassembly = ""; FirstLineWithOpcode = 1; if (JumpedAtAddresses.Count == 0) { return(false); } int progStepPos = JumpedAtAddresses.First; GR.Collections.Set <ushort> accessedAddresses = new GR.Collections.Set <ushort>(); GR.Collections.Set <int> addressesToCheck = new GR.Collections.Set <int>(JumpedAtAddresses); GR.Collections.Set <int> addressesChecked = new GR.Collections.Set <int>(); GR.Collections.Set <ushort> probableLabel = new GR.Collections.Set <ushort>(); // check for basic header int sysAddress = -1; if (HasBASICJumpAddress(DataStartAddress, out sysAddress)) { progStepPos = sysAddress; addressesToCheck.Add(progStepPos); } /* * else * { * // automatically check at data start address * addressesToCheck.Add( DataStartAddress ); * }*/ int codeStartPos = progStepPos; GR.Collections.Map <ushort, GR.Generic.Tupel <Tiny64.Opcode, ushort> > disassembly = new GR.Collections.Map <ushort, GR.Generic.Tupel <Tiny64.Opcode, ushort> >(); while (addressesToCheck.Count > 0) { progStepPos = addressesToCheck.First; //Debug.Log( "check address:" + progStepPos ); addressesToCheck.Remove(progStepPos); if (addressesChecked.ContainsValue(progStepPos)) { continue; } while (true) { if (progStepPos < DataStartAddress) { break; } /* * sb.Append( "Jumped to address before data\r\n" ); * Disassembly = sb.ToString(); * return false; * }*/ if (progStepPos >= DataStartAddress + m_SourceData.Length) { // reached the end break; } Tiny64.Opcode opcode = null; bool outsideData = false; if (!DisassembleInstruction(m_SourceData, DataStartAddress, progStepPos, out opcode, out outsideData)) { if (!outsideData) { sb.Append("Failed to disassemble data $" + m_SourceData.ByteAt(progStepPos - DataStartAddress).ToString("X2") + " at location " + progStepPos + "($" + progStepPos.ToString("X4") + ")\r\n"); Disassembly = sb.ToString(); return(false); } } if (outsideData) { break; } addressesChecked.Add(progStepPos); //Debug.Log( "Mnemonic: " + OpcodeToString( opcode, Data, progStepPos + 1 - DataStartAddress ) ); //Debug.Log( progStepPos.ToString( "X4" ) + ": " + MnemonicToString( opcode, Data, DataStartAddress, progStepPos ) ); if ((opcode.ByteValue == 0x4c) || // jmp (opcode.ByteValue == 0x20)) // jsr { // absolute jump accessedAddresses.Add(m_SourceData.UInt16At(progStepPos + 1 - DataStartAddress)); addressesToCheck.Add(m_SourceData.UInt16At(progStepPos + 1 - DataStartAddress)); //Debug.Log( "access address " + Data.UInt16At( progStepPos + 1 ).ToString( "X4" ) ); } else if (opcode.ByteValue == 0x6c) // jmp indirect { probableLabel.Add(m_SourceData.UInt16At(progStepPos + 1 - DataStartAddress)); } else if (opcode.Addressing == Tiny64.Opcode.AddressingType.RELATIVE) { int targetAddress = (sbyte)m_SourceData.ByteAt(progStepPos + 1 - DataStartAddress) + 2 + progStepPos; probableLabel.Add((ushort)targetAddress); addressesToCheck.Add(targetAddress); accessedAddresses.Add((ushort)targetAddress); } disassembly[(ushort)progStepPos] = new GR.Generic.Tupel <Tiny64.Opcode, ushort>(opcode, m_SourceData.UInt16At(progStepPos + 1)); if ((opcode.ByteValue == 0x40) || // rts (opcode.ByteValue == 0x60) || // rti (opcode.ByteValue == 0x4c)) // jmp { // end of code here break; } //string output = MnemonicToString( opcode, Data, DataStartAddress, progStepPos ); //Debug.Log( output ); progStepPos += opcode.NumOperands + 1; } } progStepPos = codeStartPos; //foreach ( KeyValuePair<ushort,GR.Generic.Tupel<Opcode, ushort>> instruction in disassembly ) // remove potential labels that are not in our code GR.Collections.Set <ushort> addressesToRemove = new GR.Collections.Set <ushort>(); foreach (var accessedAddress in accessedAddresses) { if (!disassembly.ContainsKey(accessedAddress)) { addressesToRemove.Add(accessedAddress); } } foreach (var addressToRemove in addressesToRemove) { accessedAddresses.Remove(addressToRemove); } sb.Append("* = $"); sb.AppendLine(DataStartAddress.ToString("x4")); if (!Settings.AddLineAddresses) { foreach (var namedLabel in NamedLabels) { sb.Append(namedLabel.Value); sb.Append(" = $"); sb.AppendLine(namedLabel.Key.ToString("X4")); } if (NamedLabels.Count > 0) { sb.AppendLine(); } } int trueAddress = DataStartAddress; bool hadBytes = false; int hadBytesStart = 0; int localLineIndex = 1; while (trueAddress < DataStartAddress + m_SourceData.Length) { if (disassembly.ContainsKey((ushort)trueAddress)) { if (hadBytes) { sb.Append(DisassembleBinary(m_SourceData, DataStartAddress, hadBytesStart, trueAddress - hadBytesStart, Settings)); hadBytes = false; } GR.Generic.Tupel <Tiny64.Opcode, ushort> instruction = disassembly[(ushort)trueAddress]; if (Settings.AddLineAddresses) { sb.Append("$"); sb.Append(trueAddress.ToString("X4") + ": "); } if (DataStartAddress == trueAddress) { FirstLineWithOpcode = localLineIndex; } ++localLineIndex; if (accessedAddresses.ContainsValue((ushort)trueAddress)) { // line break in front of named label sb.AppendLine(); if (Settings.AddLineAddresses) { sb.Append("$"); sb.Append(trueAddress.ToString("X4") + ": "); } if (NamedLabels.ContainsKey(trueAddress)) { sb.AppendLine(NamedLabels[trueAddress]); } else { sb.Append("label_" + trueAddress.ToString("x4") + "\r\n"); } if (Settings.AddLineAddresses) { sb.Append("$"); sb.Append(trueAddress.ToString("X4") + ": "); } } else if (NamedLabels.ContainsKey(trueAddress)) { // line break in front of named label sb.AppendLine(); if (Settings.AddLineAddresses) { sb.Append("$"); sb.Append(trueAddress.ToString("X4") + ": "); } sb.AppendLine(NamedLabels[trueAddress]); if (Settings.AddLineAddresses) { sb.Append("$"); sb.Append(trueAddress.ToString("X4") + ": "); } } if (Settings.AddAssembledBytes) { sb.Append(" "); sb.Append(instruction.first.ByteValue.ToString("X2")); switch (instruction.first.NumOperands) { case 0: sb.Append(" "); break; case 1: sb.Append(" "); sb.Append(m_SourceData.ByteAt(trueAddress + 1 - DataStartAddress).ToString("X2")); sb.Append(" "); break; case 2: sb.Append(" "); sb.Append(m_SourceData.ByteAt(trueAddress + 1 - DataStartAddress).ToString("X2")); sb.Append(" "); sb.Append(m_SourceData.ByteAt(trueAddress + 1 - DataStartAddress + 1).ToString("X2")); break; } } sb.Append(" " + MnemonicToString(instruction.first, m_SourceData, DataStartAddress, trueAddress, accessedAddresses, NamedLabels)); sb.Append("\r\n"); trueAddress += instruction.first.NumOperands + 1; } else { if (!hadBytes) { hadBytes = true; hadBytesStart = trueAddress; } ++trueAddress; } } if (hadBytes) { sb.Append(DisassembleBinary(m_SourceData, DataStartAddress, hadBytesStart, trueAddress - hadBytesStart, Settings)); hadBytes = false; } Disassembly = sb.ToString(); return(true); }
public int ImageToMCBitmapData(Dictionary <int, List <ColorMappingTarget> > ForceBitPattern, List <Formats.CharData> Chars, bool[,] ErrornousBlocks, int CharX, int CharY, int WidthChars, int HeightChars, out GR.Memory.ByteBuffer bitmapData, out GR.Memory.ByteBuffer screenChar, out GR.Memory.ByteBuffer screenColor) { int numErrors = 0; ColorMappingTarget[] bitPattern = new ColorMappingTarget[3] { ColorMappingTarget.BITS_01, ColorMappingTarget.BITS_10, ColorMappingTarget.BITS_11 }; var usedBitPattern = new GR.Collections.Set <ColorMappingTarget>(); Dictionary <int, GR.Collections.Set <ColorMappingTarget> > usedPatterns = new Dictionary <int, GR.Collections.Set <ColorMappingTarget> >(); screenChar = new GR.Memory.ByteBuffer((uint)(WidthChars * HeightChars)); screenColor = new GR.Memory.ByteBuffer((uint)(WidthChars * HeightChars)); bitmapData = new GR.Memory.ByteBuffer((uint)(8 * WidthChars * HeightChars)); GR.Collections.Map <byte, ColorMappingTarget> usedColors = new GR.Collections.Map <byte, ColorMappingTarget>(); for (int y = 0; y < HeightChars; ++y) { for (int x = 0; x < WidthChars; ++x) { // ein zeichen-block usedColors.Clear(); usedBitPattern.Clear(); if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = false; } for (int charY = 0; charY < 8; ++charY) { for (int charX = 0; charX < 4; ++charX) { byte colorIndex = (byte)Image.GetPixel(x * 8 + charX * 2, y * 8 + charY); if (colorIndex >= 16) { if (Chars != null) { Chars[x + y * BlockWidth].Error = "Color index >= 16 (" + colorIndex + ") at " + (x * 8 + charX * 2).ToString() + ", " + (y * 8 + charY).ToString() + " (" + charX + "," + charY + ")"; } if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = true; } ++numErrors; } if (colorIndex != Colors.BackgroundColor) { // remember used color usedColors.Add(colorIndex, 0); } } } // more than 3 colors? if (usedColors.Count > 3) { if (Chars != null) { Chars[x + y * BlockWidth].Error = "Too many colors used"; } if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = true; } ++numErrors; } else { if (usedColors.Count > 0) { int colorTarget = 0; List <byte> keys = new List <byte>(usedColors.Keys); // check for overlaps - two colors are used that would map to the same target pattern? Dictionary <int, ColorMappingTarget> recommendedPattern = new Dictionary <int, ColorMappingTarget>(); numErrors += DetermineBestMapping(keys, x, y, ForceBitPattern, recommendedPattern, ErrornousBlocks); foreach (byte colorIndex in keys) { if (recommendedPattern.ContainsKey(colorIndex)) { usedColors[colorIndex] = recommendedPattern[colorIndex]; if (!usedPatterns.ContainsKey(colorIndex)) { usedPatterns.Add(colorIndex, new GR.Collections.Set <ColorMappingTarget>()); } usedPatterns[colorIndex].Add(recommendedPattern[colorIndex]); usedBitPattern.Add(recommendedPattern[colorIndex]); switch (recommendedPattern[colorIndex]) { case ColorMappingTarget.BITS_01: { // upper screen char nibble byte value = screenChar.ByteAt(x + y * WidthChars); value &= 0x0f; value |= (byte)(colorIndex << 4); screenChar.SetU8At(x + y * WidthChars, value); } break; case ColorMappingTarget.BITS_10: { // lower nibble in screen char byte value = screenChar.ByteAt(x + y * WidthChars); value &= 0xf0; value |= (byte)(colorIndex); screenChar.SetU8At(x + y * WidthChars, value); } break; case ColorMappingTarget.BITS_11: // color ram screenColor.SetU8At(x + y * WidthChars, colorIndex); break; } continue; } if (!usedPatterns.ContainsKey(colorIndex)) { usedPatterns.Add(colorIndex, new GR.Collections.Set <ColorMappingTarget>()); } usedPatterns[colorIndex].Add(bitPattern[colorTarget]); colorTarget = 0; while ((colorTarget < 3) && (usedBitPattern.ContainsValue(bitPattern[colorTarget]))) { ++colorTarget; } usedBitPattern.Add(bitPattern[colorTarget]); if (colorTarget == 0) { // upper screen char nibble byte value = screenChar.ByteAt(x + y * WidthChars); value &= 0x0f; value |= (byte)(colorIndex << 4); screenChar.SetU8At(x + y * WidthChars, value); usedColors[colorIndex] = ColorMappingTarget.BITS_01; } else if (colorTarget == 1) { // lower nibble in screen char byte value = screenChar.ByteAt(x + y * WidthChars); value &= 0xf0; value |= (byte)(colorIndex); screenChar.SetU8At(x + y * WidthChars, value); usedColors[colorIndex] = ColorMappingTarget.BITS_10; } else if (colorTarget == 2) { // color ram screenColor.SetU8At(x + y * WidthChars, colorIndex); usedColors[colorIndex] = ColorMappingTarget.BITS_11; } ++colorTarget; } } // write out bits /* * Debug.Log( "For Char " + x + "," + y ); * foreach ( var usedColor in usedColors ) * { * Debug.Log( " Color " + usedColor.Key + " = " + usedColor.Value ); * }*/ for (int charY = 0; charY < 8; ++charY) { for (int charX = 0; charX < 4; ++charX) { byte colorIndex = (byte)Image.GetPixel(x * 8 + charX * 2, y * 8 + charY); if (colorIndex != Colors.BackgroundColor) { // other color byte colorValue = 0; switch (usedColors[colorIndex]) { case ColorMappingTarget.BITS_01: colorValue = 0x01; break; case ColorMappingTarget.BITS_10: colorValue = 0x02; break; case ColorMappingTarget.BITS_11: colorValue = 0x03; break; } int bitmapIndex = x * 8 + y * 8 * WidthChars + charY; byte value = bitmapData.ByteAt(bitmapIndex); if (charX == 0) { value &= 0x3f; value |= (byte)(colorValue << 6); } else if (charX == 1) { value &= 0xcf; value |= (byte)(colorValue << 4); } else if (charX == 2) { value &= 0xf3; value |= (byte)(colorValue << 2); } else { value &= 0xfc; value |= colorValue; } bitmapData.SetU8At(bitmapIndex, value); } } } } } } /* * Debug.Log( "Used patterns:" ); * foreach ( var entry in usedPatterns ) * { * Debug.Log( "Index " + entry.Key ); * foreach ( var pattern in entry.Value ) * { * Debug.Log( " used " + pattern ); * } * }*/ return(numErrors); }