private void AddKeymapEntry(Types.KeyboardKey KeyboardKey, uint NeutralLangID, System.Windows.Forms.Keys Key) { KeymapEntry entry = new KeymapEntry(); entry.KeyboardKey = KeyboardKey; entry.Key = Key; if (DefaultKeymaps[NeutralLangID] == null) { DefaultKeymaps[NeutralLangID] = new GR.Collections.Map <System.Windows.Forms.Keys, KeymapEntry>(); } DefaultKeymaps[NeutralLangID][Key] = entry; AllKeyInfos[KeyboardKey] = entry; }
public void SetBreakPoints(GR.Collections.Map <string, List <Types.Breakpoint> > BreakPoints) { m_BreakPoints.Clear(); foreach (var key in BreakPoints.Keys) { foreach (Types.Breakpoint breakPoint in BreakPoints[key]) { if (breakPoint.Address != -1) { m_BreakPoints.Add(breakPoint); } } } }
private void RefreshCategoryCounts() { GR.Collections.Map <int, int> catCounts = new GR.Collections.Map <int, int>(); for (int i = 0; i < 256; ++i) { catCounts[m_Charset.Characters[i].Category]++; } int itemIndex = 0; foreach (ListViewItem item in listCategories.Items) { item.SubItems[1].Text = catCounts[(int)item.Tag].ToString(); item.Tag = itemIndex; ++itemIndex; } }
public List <string> CheckForErrors() { List <string> errors = new List <string>(); GR.Collections.Map <GR.Generic.Tupel <int, int>, GR.Memory.ByteBuffer> usedSectors = new GR.Collections.Map <GR.Generic.Tupel <int, int>, GR.Memory.ByteBuffer>(); int curTrack = TRACK_DIRECTORY; int curSector = SECTOR_DIRECTORY; bool endFound = false; while (!endFound) { Sector sec = Tracks[curTrack - 1].Sectors[curSector]; for (int i = 0; i < 8; ++i) { int fileTrack = sec.Data.ByteAt(0x20 * i + 3); int fileSector = sec.Data.ByteAt(0x20 * i + 4); if (sec.Data.ByteAt(0x20 * i + 2) != (byte)C64Studio.Types.FileType.SCRATCHED) { // valid entry? C64Studio.Types.FileInfo info = new C64Studio.Types.FileInfo(); FollowChain(fileTrack, fileSector, usedSectors, info.Filename, errors); } } curTrack = sec.Data.ByteAt(0); curSector = sec.Data.ByteAt(1); if (curTrack == 0) { // track = 0 marks last directory entry endFound = true; } } return(errors); }
private List <TokenInfo> ExtTan(List <TokenInfo> Arguments, GR.Collections.Map <byte, byte> TextCodeMapping) { var result = new List <TokenInfo>(); if (Arguments.Count != 1) { SetError("Invalid argument count"); return(result); } if (!m_Parser.EvaluateTokens(0, Arguments, TextCodeMapping, out SymbolInfo functionResult)) { SetError("Invalid argument"); return(result); } var resultValue = new TokenInfo() { Type = TokenInfo.TokenType.LITERAL_NUMBER, Content = Math.Tan(functionResult.ToNumber() * Math.PI / 180.0f).ToString("0.00000000000000000000", System.Globalization.CultureInfo.InvariantCulture) }; result.Add(resultValue); return(result); }
private void FollowChain(int Track, int Sector, GR.Collections.Map <GR.Generic.Tupel <int, int>, GR.Memory.ByteBuffer> UsedSectors, GR.Memory.ByteBuffer Filename, List <string> Errors) { int fileTrack = Track; int fileSector = Sector; while (fileTrack != 0) { GR.Generic.Tupel <int, int> location = new GR.Generic.Tupel <int, int>(fileTrack, fileSector); if ((UsedSectors[location].Length > 0) && (UsedSectors[location] != Filename)) { Errors.Add("Sector " + location.first + ", Track " + location.second + " is referenced by more than one file"); } int newTrack = Tracks[fileTrack - 1].Sectors[fileSector].Data.ByteAt(0); int newSector = Tracks[fileTrack - 1].Sectors[fileSector].Data.ByteAt(1); if (newTrack == 0) { return; } if ((newTrack < 1) || (newTrack > Tracks.Count)) { Errors.Add("Reference to invalid track " + newTrack + " encountered in track " + fileTrack + ", Sector " + fileSector); return; } fileTrack = newTrack; fileSector = newSector; } }
public int Handle(string[] args) { if (args.Length == 0) { System.Console.WriteLine("MediaManager V" + System.Windows.Forms.Application.ProductVersion); System.Console.WriteLine(""); System.Console.WriteLine("Call with mediamanager"); System.Console.WriteLine(" [-d64 <disk image>]"); System.Console.WriteLine(" [-t64 <tape file>]"); System.Console.WriteLine(" [-import <file name>[,load address]]"); System.Console.WriteLine(" [-export <file name>]"); System.Console.WriteLine(" [-rename <file name>]"); System.Console.WriteLine(" [-renameto <file name>]"); System.Console.WriteLine(" [-delete <file name>]"); System.Console.WriteLine(" [-listfiles]"); System.Console.WriteLine(""); System.Console.WriteLine("load address can be given as decimal, hexadecimal (prefix $ or 0x). If load address is given it is prepended to the import file data."); System.Console.WriteLine("The filename given to -renameto is used for the actually written file when exporting"); System.Console.WriteLine("The filename given to -renameto is used for the file info entry when importing"); return(1); } bool expectingParameter = false; string expectingParameterName = ""; string methodToUse = ""; GR.Collections.Map <string, string> paramMap = new GR.Collections.Map <string, string>(); for (int i = 0; i < args.Length; ++i) { if (expectingParameter) { paramMap[expectingParameterName] = args[i]; expectingParameter = false; } else if ((args[i].ToUpper() == "-D64") || (args[i].ToUpper() == "-T64") || (args[i].ToUpper() == "-IMPORT") || (args[i].ToUpper() == "-DELETE") || (args[i].ToUpper() == "-RENAME") || (args[i].ToUpper() == "-RENAMETO") || (args[i].ToUpper() == "-EXPORT")) { expectingParameter = true; expectingParameterName = args[i].ToUpper(); if ((expectingParameterName == "-IMPORT") || (expectingParameterName == "-EXPORT") || (expectingParameterName == "-DELETE") || (expectingParameterName == "-RENAME")) { methodToUse = expectingParameterName; } } else if (args[i].ToUpper() == "-LISTFILES") { paramMap[args[i].ToUpper()] = ""; methodToUse = args[i].ToUpper(); } else { System.Console.Error.WriteLine("Unsupported option " + args[i]); return(1); } } if (expectingParameter) { System.Console.Error.WriteLine("Missing value for " + expectingParameterName); return(1); } // do we have a container? if ((!paramMap.ContainsKey("-D64")) && (!paramMap.ContainsKey("-T64"))) { System.Console.Error.WriteLine("Missing medium"); return(1); } // load C64Studio.Formats.MediaFormat medium = null; string mediumFilename = ""; if (paramMap.ContainsKey("-D64")) { medium = new C64Studio.Formats.D64(); mediumFilename = paramMap["-D64"]; } else if (paramMap.ContainsKey("-T64")) { medium = new C64Studio.Formats.T64(); mediumFilename = paramMap["-T64"]; } if (!medium.Load(mediumFilename)) { System.Console.WriteLine("No image found, start empty"); medium.CreateEmptyMedia(); } // handle command if (methodToUse == "-LISTFILES") { List <C64Studio.Types.FileInfo> files = medium.Files(); foreach (C64Studio.Types.FileInfo file in files) { string filename = C64Studio.Util.FilenameToReadableUnicode(file.Filename); filename = filename.PadRight(16); System.Console.WriteLine("\"" + filename + "\" " + file.Blocks + " blocks " + file.Type.ToString() + " " + file.Filename); } System.Console.WriteLine(files.Count + " files"); } else if (methodToUse == "-EXPORT") { C64Studio.Types.FileInfo fileInfo = medium.LoadFile(C64Studio.Util.ToFilename(paramMap["-EXPORT"])); if (fileInfo != null) { string outputFilename = paramMap["-EXPORT"]; if (paramMap.ContainsKey("-RENAMETO")) { outputFilename = paramMap["-RENAMETO"]; } GR.IO.File.WriteAllBytes(outputFilename, fileInfo.Data); System.Console.WriteLine("File " + paramMap["-EXPORT"] + " exported"); } else { System.Console.Error.WriteLine("File " + paramMap["-EXPORT"] + " not found in medium"); } } else if (methodToUse == "-DELETE") { C64Studio.Types.FileInfo fileInfo = medium.LoadFile(C64Studio.Util.ToFilename(paramMap["-DELETE"])); if (fileInfo != null) { if (!medium.DeleteFile(C64Studio.Util.ToFilename(paramMap["-DELETE"]))) { System.Console.Error.WriteLine("File could not be deleted: " + medium.LastError); } else { System.Console.WriteLine("File deleted"); medium.Save(mediumFilename); } } else { System.Console.Error.WriteLine("File " + paramMap["-DELETE"] + " not found in medium"); } } else if (methodToUse == "-IMPORT") { bool addAddress = false; ushort startAddress = 0x0801; string filenameImport = paramMap["-IMPORT"]; string[] paramList = filenameImport.Split(','); if ((paramList.Length == 0) || (paramList.Length > 2)) { System.Console.Error.WriteLine("Invalid parameter value for -IMPORT"); return(1); } filenameImport = paramList[0]; if (paramList.Length >= 2) { addAddress = true; string loadAdressPart = paramList[1]; if (loadAdressPart.StartsWith("0x")) { ushort.TryParse(loadAdressPart.Substring(2), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out startAddress); } else if (loadAdressPart.StartsWith("$")) { ushort.TryParse(loadAdressPart.Substring(1), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out startAddress); } else { ushort.TryParse(loadAdressPart, out startAddress); } } GR.Memory.ByteBuffer data = GR.IO.File.ReadAllBytes(filenameImport); if (data == null) { System.Console.Error.WriteLine("Could not read file " + paramMap["-IMPORT"]); return(1); } // insert load address if (addAddress) { GR.Memory.ByteBuffer newData = new GR.Memory.ByteBuffer(2 + data.Length); newData.SetU16At(0, startAddress); data.CopyTo(newData, 0, (int)data.Length, 2); data = newData; } if (paramMap.ContainsKey("-RENAMETO")) { filenameImport = paramMap["-RENAMETO"]; } if (!medium.WriteFile(C64Studio.Util.ToFilename(filenameImport), data, C64Studio.Types.FileType.PRG)) { System.Console.Error.WriteLine("Could not write file to medium: " + medium.LastError); return(1); } System.Console.WriteLine("File imported"); medium.Save(mediumFilename); } else if (methodToUse == "-RENAME") { if (!paramMap.ContainsKey("-RENAMETO")) { System.Console.Error.WriteLine("Missing -renameto directive"); return(1); } string origFilename = paramMap["-RENAME"]; GR.Memory.ByteBuffer origFilenameBuffer = C64Studio.Util.ToFilename(origFilename); string targetFilename = paramMap["-RENAMETO"]; GR.Memory.ByteBuffer targetFilenameBuffer = C64Studio.Util.ToFilename(targetFilename); if (!medium.RenameFile(origFilenameBuffer, targetFilenameBuffer)) { System.Console.Error.WriteLine("Failed to rename file"); return(1); } System.Console.WriteLine("File renamed"); medium.Save(mediumFilename); } else { System.Console.Error.WriteLine("Unsupported method " + methodToUse); } return(0); }
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); }
bool CheckColors() { // can all colors be matched to the palette? GR.Collections.Map <uint, byte> matchedColors = new GR.Collections.Map <uint, byte>(); for (int i = 0; i < m_OrigSize.Width; ++i) { for (int j = 0; j < m_OrigSize.Height; ++j) { uint pixelValue = picOriginal.DisplayPage.GetPixel(i, j); byte matchedColor = 0; if (matchedColors.ContainsKey(pixelValue)) { matchedColor = matchedColors[pixelValue]; m_ImportImage.SetPixel(i, j, matchedColor); } else { // TODO - match byte red = (byte)((pixelValue & 0xff0000) >> 16); byte green = (byte)((pixelValue & 0x00ff00) >> 8); byte blue = (byte)(pixelValue & 0xff); if ((picOriginal.DisplayPage.PixelFormat == System.Drawing.Imaging.PixelFormat.Format4bppIndexed) || (picOriginal.DisplayPage.PixelFormat == System.Drawing.Imaging.PixelFormat.Format1bppIndexed) || (picOriginal.DisplayPage.PixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)) { red = picOriginal.DisplayPage.PaletteRed((int)pixelValue); green = picOriginal.DisplayPage.PaletteGreen((int)pixelValue); blue = picOriginal.DisplayPage.PaletteBlue((int)pixelValue); } //ColorSystem.RGB rgb = new ColorSystem.RGB( red, green, blue ); // HSV-system (painter!) int bestMatch = MatchColor(red, green, blue, m_CurPalette); /* * int bestMatchDistance = 50000000; * int bestMatch = -1; * for ( int k = 0; k < 16; ++k ) * { * int distR = red - (int)( ( m_CurPalette.ColorValues[k] & 0xff0000 ) >> 16 ); * int distG = green - (int)( ( m_CurPalette.ColorValues[k] & 0x00ff00 ) >> 8 ); * int distB = blue - (int)( m_CurPalette.ColorValues[k] & 0xff ); * //int distance = (int)( distR * distR * 0.3f + distG * distG * 0.6f + distB * distB * 0.1f ); * int distance = (int)( distR * distR + distG * distG + distB * distB ); * * if ( distance < bestMatchDistance ) * { * bestMatchDistance = distance; * bestMatch = k; * } * }*/ if (bestMatch == -1) { m_ImportImage.SetPixel(i, j, 16); } else { matchedColor = (byte)bestMatch; matchedColors[pixelValue] = matchedColor; m_ImportImage.SetPixel(i, j, matchedColor); } } } } picPreview.DisplayPage.DrawFromMemoryImage(m_ImportImage, 0, 0); picPreview.Invalidate(); 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); }
public int ImageToHiresBitmapData(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) { screenChar = null; screenColor = null; bitmapData = null; if ((CharX < 0) || (CharX >= BlockWidth) || (CharY < 0) || (CharY >= BlockHeight) || (WidthChars < 0) || (HeightChars < 0) || (CharX + WidthChars > BlockWidth) || (CharY + HeightChars > BlockHeight)) { return(1); } int numErrors = 0; 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, byte> usedColors = new GR.Collections.Map <byte, byte>(); for (int y = CharY; y < HeightChars; ++y) { for (int x = CharX; x < WidthChars; ++x) { // ein zeichen-block usedColors.Clear(); if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = false; } for (int charY = 0; charY < 8; ++charY) { for (int charX = 0; charX < 8; ++charX) { byte colorIndex = (byte)Image.GetPixel(x * 8 + charX, y * 8 + charY); if (colorIndex >= 16) { if (Chars != null) { Chars[x + y * BlockWidth].Error = "Color index >= 16 (" + colorIndex + ") at " + (x * 8 + charX).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 2 colors? if (usedColors.Count > 2) { if (Chars != null) { Chars[x + y * BlockWidth].Error = "Too many colors used"; } if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = true; } ++numErrors; } else { int firstColorIndex = -1; if (usedColors.Count > 0) { int colorTarget = 0; List <byte> keys = new List <byte>(usedColors.Keys); /* * // only one color, that means, the other was background -> force the same bit pattern * if ( ( usedColors.Count == 1 ) * && ( usedColors[0] != Colors.BackgroundColor ) ) * { * colorTarget = 1; * firstColorIndex = Colors.BackgroundColor; * }*/ // 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)) { if (recommendedPattern[colorIndex] == ColorMappingTarget.COLOR_1) { colorTarget = 0; } else if (recommendedPattern[colorIndex] == ColorMappingTarget.COLOR_2) { colorTarget = 1; } } 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] = 1; firstColorIndex = colorIndex; } 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] = 2; } if (recommendedPattern.ContainsKey(colorIndex)) { if (recommendedPattern[colorIndex] == ColorMappingTarget.COLOR_2) { firstColorIndex = colorIndex; } } ++colorTarget; } } // write out bits for (int charY = 0; charY < 8; ++charY) { for (int charX = 0; charX < 8; ++charX) { byte colorIndex = (byte)Image.GetPixel(x * 8 + charX, y * 8 + charY); if (colorIndex == firstColorIndex) { // other color byte colorValue = usedColors[colorIndex]; int bitmapIndex = x * 8 + y * WidthChars * 8 + charY; byte value = bitmapData.ByteAt(bitmapIndex); int mask = (1 << (7 - charX)); value &= (byte)(0xff ^ mask); value |= (byte)mask; bitmapData.SetU8At(bitmapIndex, value); } } } } } } return(numErrors); }
public int ImageToHiresBitmapData(List <Formats.CharData> Chars, bool[,] ErrornousBlocks, out GR.Memory.ByteBuffer bitmapData, out GR.Memory.ByteBuffer screenChar, out GR.Memory.ByteBuffer screenColor) { int numErrors = 0; screenChar = new GR.Memory.ByteBuffer((uint)(BlockWidth * BlockHeight)); screenColor = new GR.Memory.ByteBuffer((uint)(BlockWidth * BlockHeight)); bitmapData = new GR.Memory.ByteBuffer((uint)(8 * BlockWidth * BlockHeight)); GR.Collections.Map <byte, byte> usedColors = new GR.Collections.Map <byte, byte>(); for (int y = 0; y < BlockHeight; ++y) { for (int x = 0; x < BlockWidth; ++x) { // ein zeichen-block usedColors.Clear(); if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = false; } for (int charY = 0; charY < 8; ++charY) { for (int charX = 0; charX < 8; ++charX) { byte colorIndex = (byte)Image.GetPixel(x * 8 + charX, y * 8 + charY); if (colorIndex >= 16) { if (Chars != null) { Chars[x + y * BlockWidth].Error = "Color index >= 16 (" + colorIndex + ") at " + (x * 8 + charX).ToString() + ", " + (y * 8 + charY).ToString() + " (" + charX + "," + charY + ")"; } if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = true; } ++numErrors; } if (colorIndex != BackgroundColor) { // remember used color usedColors.Add(colorIndex, 0); } } } // more than 2 colors? if (usedColors.Count > 2) { if (Chars != null) { Chars[x + y * BlockWidth].Error = "Too many colors used"; } if (ErrornousBlocks != null) { ErrornousBlocks[x, y] = true; } ++numErrors; } else { int firstColorIndex = -1; if (usedColors.Count > 0) { int colorTarget = 0; List <byte> keys = new List <byte>(usedColors.Keys); foreach (byte colorIndex in keys) { if (colorTarget == 0) { // upper screen char nibble byte value = screenChar.ByteAt(x + y * BlockWidth); value &= 0x0f; value |= (byte)(colorIndex << 4); screenChar.SetU8At(x + y * BlockWidth, value); usedColors[colorIndex] = 1; firstColorIndex = colorIndex; } else if (colorTarget == 1) { // lower nibble in screen char byte value = screenChar.ByteAt(x + y * BlockWidth); value &= 0xf0; value |= (byte)(colorIndex); screenChar.SetU8At(x + y * BlockWidth, value); usedColors[colorIndex] = 2; } ++colorTarget; } } // write out bits for (int charY = 0; charY < 8; ++charY) { for (int charX = 0; charX < 8; ++charX) { byte colorIndex = (byte)Image.GetPixel(x * 8 + charX, y * 8 + charY); if (colorIndex == firstColorIndex) { // other color byte colorValue = usedColors[colorIndex]; int bitmapIndex = x * 8 + y * BlockWidth * 8 + charY; byte value = bitmapData.ByteAt(bitmapIndex); int mask = (1 << (7 - charX)); value &= (byte)(0xff ^ mask); value |= (byte)mask; bitmapData.SetU8At(bitmapIndex, value); } } } } } } return(numErrors); }