private void ScriptList_SelectionChanged(object sender, SelectionChangedEventArgs e) { // Change what script to show strings from // This will update the StringList contents with a list of IDs for the selected script // Consider asking the user if they want to save the current input data if they've changed the text but didn't insert it // Load RMD script var path = e.AddedItems[0].ToString(); currentRmd = new RmdFile(path, 0x391); currentSelectedScript = System.IO.Path.GetFileName(path); if (currentRmd.Strings.Count > 1) { StatusBar.Text = String.Format("Loaded {0}... found {1} strings", e.AddedItems[0], currentRmd.Strings.Count); } else { StatusBar.Text = String.Format("Loaded {0}... found {1} string", e.AddedItems[0], currentRmd.Strings.Count); } // Remove anything from the string list from the old script StringList.Items.Clear(); foreach (var str in currentRmd.Strings) { StringList.Items.Add(str.Key); } if (StringList.Items.Count > 0) { StringList.SelectedIndex = 0; } UpdateToggleInsertionContent(); }
private List <Tuple <Bitmap, RectangleF> > DrawGlyphs(uint cmd, RmdFile targetFont, int x, int y) { var tiles = new List <Tuple <Bitmap, RectangleF> >(); if (targetFont != null) { var glyphMetrics = targetFont.FontMapping[cmd]; Bitmap tile = new Bitmap(glyphMetrics.Width, glyphMetrics.Height); using (Graphics g = Graphics.FromImage(tile)) g.DrawImage(targetFont.Font, new RectangleF(0, 0, glyphMetrics.Width, glyphMetrics.Height), glyphMetrics, GraphicsUnit.Pixel); tiles.Add(new Tuple <Bitmap, RectangleF>(tile, new RectangleF(x, y, glyphMetrics.Width, glyphMetrics.Height))); } else { Console.WriteLine("Could not find {0:x2} in font mapping", cmd); } return(tiles); }
public MainWindow() { InitializeComponent(); translationDatabase = LoadTranslationDatabase(translationDatbaseFilename); translationDLCDatabase = LoadTranslationDatabase(translationDLCDatbaseFilename, true); glyphDatabase = LoadGlyphDatabase(glyphDatabaseFilename); reverseGlyphDatabase = BuildReverseGlyphDatabase(glyphDatabase); var scriptsFolder = "scripts"; if (!Directory.Exists(scriptsFolder)) { MessageBox.Show(String.Format("Please place all *.rmd files into a folder named \"{0}\" and load the program again", scriptsFolder)); } else { var scripts = Directory.EnumerateFiles(scriptsFolder, "*.rmd", SearchOption.AllDirectories); var basicCharSetPath = System.IO.Path.Combine(scriptsFolder, "BasicCharSet.rmd"); if (File.Exists(basicCharSetPath)) { basicCharSetRmd = new RmdFile(basicCharSetPath, 0x81); } var basicRubySetPath = System.IO.Path.Combine(scriptsFolder, "BasicRubySet.rmd"); if (File.Exists(basicRubySetPath)) { basicRubySetRmd = new RmdFile(basicRubySetPath, 0x881); } foreach (var script in scripts) { ScriptList.Items.Add(script); } } }
private Tuple <Bitmap, string> DrawString(byte[][] text, double frameWidth, RmdFile currentRmd) { int glyphWidth = currentRmd.GlyphWidth; int glyphHeight = currentRmd.GlyphHeight; int requiredWidth = 0; int x = 0, y = 0; string outputText = ""; // Calculate required image width and height int lines = 0; var tiles = new List <Tuple <Bitmap, RectangleF> >(); for (int i = 0; i < text.Length; i++) { var c = text[i]; var cmd = BitConverter.ToUInt16(c, 0); if (cmd >= 0x8080) { string opcodeText = null; // Control codes if (cmd == 0x8080) { opcodeText = "n"; } else if (cmd == 0x8081) { opcodeText = "a"; } else if (cmd == 0x8082) { opcodeText = "b"; } else if (cmd == 0x8090) { opcodeText = "ruby"; } else if (cmd == 0x8091) { opcodeText = "/ruby"; } else if (cmd == 0x8094) { opcodeText = "e"; } else if (cmd == 0x8099) { opcodeText = "f"; } opcodeText = "[" + opcodeText + " "; if (cmd == 0x8090) { for (int j = 2; j < c.Length; j++) { opcodeText += String.Format("{0}", GetTextByGlypyId("BasicRubySet", (uint)basicRubySetRmd.CharsetOffset + c[j] - 1)); } } else { for (int j = 2; j < c.Length; j++) { opcodeText += String.Format("{0:x2} ", c[j]); } } opcodeText = opcodeText.Trim() + "]"; if (opcodeText != null) { // Write text to be displayed var tile = DrawTextToBitmap(opcodeText, glyphWidth * 0.75f, System.Drawing.Color.Yellow); if (frameWidth != -1 && x + tile.Width >= frameWidth) { if (x > requiredWidth) { requiredWidth = x; } y += glyphHeight; x = 0; } tiles.Add(new Tuple <Bitmap, RectangleF>(tile, new RectangleF(x, y, tile.Width, tile.Height))); x += tile.Width; outputText += opcodeText; } if (cmd == 0x8080) { if (x > requiredWidth) { requiredWidth = x; } // New line lines++; x = 0; y += glyphHeight; } } else { if (frameWidth != -1 && x + glyphWidth >= frameWidth) { y += glyphHeight; x = 0; } RmdFile targetFont = null; if (basicCharSetRmd != null && basicCharSetRmd.FontMapping.ContainsKey(cmd)) { targetFont = basicCharSetRmd; } else if (basicRubySetRmd != null && basicRubySetRmd.FontMapping.ContainsKey(cmd)) { targetFont = basicRubySetRmd; } else if (currentRmd != null && currentRmd.FontMapping.ContainsKey(cmd)) { targetFont = currentRmd; } else { continue; } var tileGlyphs = DrawGlyphs(cmd, targetFont, x, y); var tile = tileGlyphs.Count > 0 ? tileGlyphs[0].Item1 : null; if (tile != null) { tiles.AddRange(tileGlyphs); using (MemoryStream s = new MemoryStream()) { tile.Save(s, System.Drawing.Imaging.ImageFormat.Bmp); using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) { var hash = sha1.ComputeHash(s.GetBuffer()); var hashStr = BitConverter.ToString(hash).ToLower().Replace("-", ""); // Preferred format if (hashStr == "d919fb1eb06492a666fbec418813f723e97a6e4f") // No image { outputText += " "; } else if (glyphDatabase.ContainsKey(hashStr)) { outputText += glyphDatabase[hashStr].Text; } } } } if (targetFont.GlyphSizes.ContainsKey(cmd)) { var w = targetFont.GlyphSizes[cmd].Item1; var h = targetFont.GlyphSizes[cmd].Item2; x += w; } } } if (x > requiredWidth) { requiredWidth = x; } if (requiredWidth == 0) { requiredWidth = x; } var output = new Bitmap(requiredWidth + 1, (lines + 1) * glyphHeight); using (Graphics g = Graphics.FromImage(output)) { foreach (var tile in tiles) { g.DrawImage(tile.Item1, tile.Item2, new RectangleF(0, 0, tile.Item1.Width, tile.Item1.Height), GraphicsUnit.Pixel); } } outputText = outputText.Replace("[n]", "\n"); if (String.IsNullOrWhiteSpace(outputText)) { outputText = null; } return(new Tuple <Bitmap, string>(output, outputText)); }
private void DumpText_Click(object sender, RoutedEventArgs e) { const string outputFoldername = "output_text"; if (!Directory.Exists(outputFoldername)) { Directory.CreateDirectory(outputFoldername); } // Generate an image for every string in a file, and then generate an image based on all of those images var scripts = ScriptList.Items; int dumpedStrings = 0, dumpedScripts = 0; foreach (string file in scripts) { var baseFilename = System.IO.Path.GetFileNameWithoutExtension(file); if (String.Compare(baseFilename, "BasicCharSet", true) == 0 || String.Compare(baseFilename, "BasicRubySet", true) == 0 || String.Compare(baseFilename, "msg_0", true) == 0) { continue; } RmdFile rmd = new RmdFile(file, 0x391); if (rmd.Strings != null) { foreach (var str in rmd.Strings) { var d = DrawString(str.Value, -1, rmd); var key = System.IO.Path.GetFileName(file); if (String.Compare(key, String.Format("msg_{0}", str.Key)) == 0) { MessageBox.Show("Found msg that broke expected format of no double keys"); } if (!translationDatabase.ContainsKey(str.Key)) { translationDatabase[str.Key] = new TranslationEntry(); } if (d.Item2 != null) { translationDatabase[str.Key].OriginalText = d.Item2; dumpedStrings++; } else { translationDatabase[str.Key].OriginalText = ""; } } } dumpedScripts++; } SaveTranslationDatabase(System.IO.Path.Combine(outputFoldername, translationDatbaseFilename)); LoadTranslationDatabase(translationDatbaseFilename); // Get rid of all the extra entries we created for dumping Console.WriteLine("Finished dumping {0} strings from {1} scripts!", dumpedStrings, dumpedScripts); MessageBox.Show(String.Format("Finished dumping {0} strings from {1} scripts!", dumpedStrings, dumpedScripts)); }
private void DumpGlyphs_Click(object sender, RoutedEventArgs e) { // Dump all unique glyphs used in the scripts const string outputFoldername = "output_glyphs"; if (!Directory.Exists(outputFoldername)) { Directory.CreateDirectory(outputFoldername); } int dumped = 0; using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) { var scripts = ScriptList.Items; foreach (string file in scripts) { var baseFilename = System.IO.Path.GetFileNameWithoutExtension(file); string outputFilename = System.IO.Path.Combine(outputFoldername, baseFilename + ".png"); RmdFile rmd = new RmdFile(file, 0x391); foreach (var gm in rmd.FontMapping) { Rectangle glyphMetrics = gm.Value; Bitmap glyphOrig = new Bitmap(glyphMetrics.Width, glyphMetrics.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); Bitmap glyphBlack = new Bitmap(glyphMetrics.Width, glyphMetrics.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); using (Graphics g1 = Graphics.FromImage(glyphOrig)) using (Graphics g2 = Graphics.FromImage(glyphBlack)) { g1.DrawImage(rmd.Font, new RectangleF(0, 0, glyphMetrics.Width, glyphMetrics.Height), glyphMetrics, GraphicsUnit.Pixel); g2.Clear(Color.Black); g2.DrawImage(rmd.Font, new RectangleF(0, 0, glyphMetrics.Width, glyphMetrics.Height), glyphMetrics, GraphicsUnit.Pixel); } using (MemoryStream s = new MemoryStream()) { glyphOrig.Save(s, System.Drawing.Imaging.ImageFormat.Bmp); var hash = sha1.ComputeHash(s.GetBuffer()); var hashStr = BitConverter.ToString(hash).ToLower().Replace("-", ""); // Preferred format if (hashStr != "d919fb1eb06492a666fbec418813f723e97a6e4f") // No glyph { if (!glyphDatabase.ContainsKey(hashStr)) { var baseGlyphFilename = String.Format("{0:d6}.png", dumped); var outputGlyphFilename = Path.Combine(outputFoldername, baseGlyphFilename); Console.WriteLine("Saving {0}...", outputGlyphFilename); if (Directory.Exists(outputGlyphFilename)) { Directory.CreateDirectory(outputGlyphFilename); } glyphBlack.Save(outputGlyphFilename); glyphDatabase[hashStr] = new GlyphEntry(); glyphDatabase[hashStr].Filename = baseGlyphFilename; glyphDatabase[hashStr].Text = ""; glyphDatabase[hashStr].References = new List <Tuple <string, uint> >(); dumped++; } glyphDatabase[hashStr].References.Add(new Tuple <string, uint>(baseFilename, gm.Key)); } } } } } var outputDatabaseFilename = Path.Combine(outputFoldername, glyphDatabaseFilename); SaveGlyphDatabase(outputDatabaseFilename); Console.WriteLine("Finished dumping {0} glyphs!", dumped); MessageBox.Show(String.Format("Finished dumping {0} glyphs!", dumped)); }
private void DumpScripts_Click(object sender, RoutedEventArgs e) { const string outputFoldername = "output"; if (!Directory.Exists(outputFoldername)) { Directory.CreateDirectory(outputFoldername); } // Generate an image for every string in a file, and then generate an image based on all of those images var scripts = ScriptList.Items; int dumped = 0; foreach (string file in scripts) { var baseFilename = System.IO.Path.GetFileNameWithoutExtension(file); if (String.Compare(baseFilename, "BasicCharSet", true) == 0 || String.Compare(baseFilename, "BasicRubySet", true) == 0 || String.Compare(baseFilename, "msg_0", true) == 0) { continue; } string outputFilename = System.IO.Path.Combine(outputFoldername, baseFilename + ".png"); Console.WriteLine("Saving {0}...", outputFilename); RmdFile rmd = new RmdFile(file, 0x391); if (rmd.Strings != null) { var scriptHeader = DrawTextToBitmap(System.IO.Path.GetFileName(file), 30, System.Drawing.Color.LightBlue); List <Tuple <ulong, Bitmap, Bitmap> > images = new List <Tuple <ulong, Bitmap, Bitmap> >(); foreach (var str in rmd.Strings) { var header = DrawTextToBitmap(String.Format("{0}:", str.Key), 20, System.Drawing.Color.Red); var d = DrawString(str.Value, -1, rmd); images.Add(new Tuple <ulong, Bitmap, Bitmap>(str.Key, header, d.Item1)); var key = System.IO.Path.GetFileName(file); if (String.Compare(key, String.Format("msg_{0}", str.Key)) == 0) { MessageBox.Show("Found msg that broke expected format of no double keys"); } if (!translationDatabase.ContainsKey(str.Key)) { translationDatabase[str.Key] = new TranslationEntry(); if (d.Item2 != null) { translationDatabase[str.Key].Text = d.Item2; } else { translationDatabase[str.Key].Text = ""; } } } int xpadding = 10, ypadding = 10; int w = scriptHeader.Width + xpadding, h = scriptHeader.Height + 20 + ypadding; foreach (var image in images) { if (image.Item2.Width > w) { w = image.Item2.Width; } if (image.Item3.Width > w) { w = image.Item3.Width; } h += image.Item2.Height + 10; h += image.Item3.Height + 20; } Bitmap output = new Bitmap(w + xpadding * 2, h + ypadding * 2); int x = xpadding, y = ypadding; using (Graphics g = Graphics.FromImage(output)) { g.Clear(System.Drawing.Color.Black); g.DrawImage(scriptHeader, x, y); y += scriptHeader.Height + 20; foreach (var image in images) { g.DrawImage(image.Item2, x, y); y += image.Item2.Height + 10; g.DrawImage(image.Item3, x, y); y += image.Item3.Height + 20; } } output.Save(outputFilename); dumped++; } } SaveTranslationDatabase(System.IO.Path.Combine(outputFoldername, translationDatbaseFilename)); LoadTranslationDatabase(translationDatbaseFilename); // Get rid of all the extra entries we created for dumping Console.WriteLine("Finished dumping {0} scripts!", dumped); MessageBox.Show(String.Format("Finished dumping {0} scripts!", dumped)); }
private void ToggleScriptMode_Click(object sender, RoutedEventArgs e) { translationDatabase = LoadTranslationDatabase(translationDatbaseFilename); translationDLCDatabase = LoadTranslationDatabase(translationDLCDatbaseFilename, true); var scriptsFolder = "scripts"; var DLCFolder = "scripts_dlc"; ScriptList.SelectedIndex = -1; if (ToggleScriptMode.Content.ToString().Contains("DLC")) { if (!Directory.Exists(DLCFolder)) { MessageBox.Show(String.Format("Please place all *.rmd files into a folder named \"{0}\" and load the program again.", DLCFolder)); } else { var dlc = Directory.EnumerateFiles(DLCFolder, "*.rmd", SearchOption.AllDirectories); var basicCharSetPath = System.IO.Path.Combine(DLCFolder, "BasicCharSet.rmd"); if (File.Exists(basicCharSetPath)) { basicCharSetRmd = new RmdFile(basicCharSetPath, 0x81); } var basicRubySetPath = System.IO.Path.Combine(DLCFolder, "BasicRubySet.rmd"); if (File.Exists(basicRubySetPath)) { basicRubySetRmd = new RmdFile(basicRubySetPath, 0x881); } ScriptList.Items.Clear(); foreach (var dlc_script in dlc) { ScriptList.Items.Add(dlc_script); } ToggleScriptMode.Content = "Switch to base"; DumpGlyphs.IsEnabled = false; DumpScripts.IsEnabled = false; DumpText.IsEnabled = false; } } else { if (!Directory.Exists(scriptsFolder)) { MessageBox.Show(String.Format("Please place all *.rmd files into a folder named \"{0}\" and load the program again.", scriptsFolder)); } else { var scripts = Directory.EnumerateFiles(scriptsFolder, "*.rmd", SearchOption.AllDirectories); var basicCharSetPath = System.IO.Path.Combine(scriptsFolder, "BasicCharSet.rmd"); if (File.Exists(basicCharSetPath)) { basicCharSetRmd = new RmdFile(basicCharSetPath, 0x81); } var basicRubySetPath = System.IO.Path.Combine(scriptsFolder, "BasicRubySet.rmd"); if (File.Exists(basicRubySetPath)) { basicRubySetRmd = new RmdFile(basicRubySetPath, 0x881); } ScriptList.Items.Clear(); foreach (var script in scripts) { ScriptList.Items.Add(script); } ToggleScriptMode.Content = "Switch to DLC"; DumpGlyphs.IsEnabled = true; DumpScripts.IsEnabled = true; DumpText.IsEnabled = true; } } }