public static void DumpComparison(string filename, RomHandler romPrimary, RomHandler romSecondary) { TextWriter writer = File.CreateText(filename); using (HtmlTextWriter html = new HtmlTextWriter(writer)) { html.WriteLine("<!DOCTYPE html>"); html.RenderBeginTag(HtmlTextWriterTag.Html); { WriteHeader(html, string.Format("{0} Message Comparison", System.Windows.Forms.Application.ProductName)); html.RenderBeginTag(HtmlTextWriterTag.Body); { html.RenderBeginTag(HtmlTextWriterTag.H2); { if (romSecondary != null) { html.WriteEncodedText(string.Format("Comparison between {0} ({1}) and {2} ({3})", Path.GetFileName(romPrimary.FileName), romPrimary.Language, Path.GetFileName(romSecondary.FileName), romSecondary.Language)); } else { html.WriteEncodedText(string.Format("Dump of {0} ({1})", Path.GetFileName(romPrimary.FileName), romPrimary.Language)); } } html.RenderEndTag(); html.RenderBeginTag(HtmlTextWriterTag.H4); { Version ver = new Version(System.Windows.Forms.Application.ProductVersion); html.WriteEncodedText(string.Format("{0} v{1}.{2}", System.Windows.Forms.Application.ProductName, ver.Major, ver.Minor)); html.WriteEncodedText(" - "); html.WriteEncodedText(string.Format("{0}", (Assembly.GetExecutingAssembly().GetCustomAttribute(typeof(AssemblyCopyrightAttribute)) as AssemblyCopyrightAttribute).Copyright)); } html.RenderEndTag(); int numBanks = 0; if (romSecondary != null) { numBanks = (romPrimary.MessageBanks.Length == romSecondary.MessageBanks.Length ? romPrimary.MessageBanks.Length : Math.Max(romPrimary.MessageBanks.Length, romSecondary.MessageBanks.Length)); } else { numBanks = romPrimary.MessageBanks.Length; } for (int i = 0; i < numBanks; i++) { MessageBank[] langBanks = new MessageBank[] { (romPrimary != null && i < romPrimary.MessageBanks.Length ? romPrimary.MessageBanks[i] : null), (romSecondary != null && i < romSecondary.MessageBanks.Length ? romSecondary.MessageBanks[i] : null) }; string bankId = string.Format("bank-{0:D4}", i); html.AddAttribute(HtmlTextWriterAttribute.Class, "header"); html.RenderBeginTag(HtmlTextWriterTag.Div); { html.AddAttribute(HtmlTextWriterAttribute.Class, "header-text"); html.RenderBeginTag(HtmlTextWriterTag.Span); { if (romPrimary.MessageBanks[i].Number == -1) { html.Write("General"); } else { html.Write("Bank {0}", romPrimary.MessageBanks[i].Number); } } html.RenderEndTag(); html.AddAttribute(HtmlTextWriterAttribute.Class, "header-toggle"); html.RenderBeginTag(HtmlTextWriterTag.Span); { html.AddAttribute(HtmlTextWriterAttribute.Href, string.Format("javascript:toggle('{0}');", bankId), false); html.RenderBeginTag(HtmlTextWriterTag.A); { html.Write("+/-"); } html.RenderEndTag(); } html.RenderEndTag(); } html.RenderEndTag(); html.AddAttribute(HtmlTextWriterAttribute.Id, bankId); html.AddStyleAttribute(HtmlTextWriterStyle.Display, "table"); html.RenderBeginTag(HtmlTextWriterTag.Table); { html.RenderBeginTag(HtmlTextWriterTag.Tr); { html.AddAttribute(HtmlTextWriterAttribute.Class, "header-id"); html.RenderBeginTag(HtmlTextWriterTag.Th); { html.Write("ID"); } html.RenderEndTag(); html.AddAttribute(HtmlTextWriterAttribute.Class, "header-desc-text"); html.RenderBeginTag(HtmlTextWriterTag.Th); { html.Write("Primary ({0})", romPrimary.Language); } html.RenderEndTag(); if (romSecondary != null) { html.AddAttribute(HtmlTextWriterAttribute.Class, "header-desc-text"); html.RenderBeginTag(HtmlTextWriterTag.Th); { html.Write("Secondary ({0})", romSecondary.Language); } html.RenderEndTag(); } html.AddAttribute(HtmlTextWriterAttribute.Class, "header-desc-sim"); html.RenderBeginTag(HtmlTextWriterTag.Th); { html.Write("Primary ({0}; Sim)", romPrimary.Language); } html.RenderEndTag(); if (romSecondary != null) { html.AddAttribute(HtmlTextWriterAttribute.Class, "header-desc-sim"); html.RenderBeginTag(HtmlTextWriterTag.Th); { html.Write("Secondary ({0}; Sim)", romSecondary.Language); } html.RenderEndTag(); } } html.RenderEndTag(); int numMessages = 0; if (langBanks[1] != null) { numMessages = (langBanks[0].Messages.Count == langBanks[1].Messages.Count ? langBanks[0].Messages.Count : Math.Max(langBanks[0].Messages.Count, langBanks[1].Messages.Count)); } else { numMessages = langBanks[0].Messages.Count; } for (int j = 0; j < numMessages; j++) { html.RenderBeginTag(HtmlTextWriterTag.Tr); { html.AddAttribute(HtmlTextWriterAttribute.Class, "message-id"); html.RenderBeginTag(HtmlTextWriterTag.Th); { html.Write("#{0}", j + 1); } html.RenderEndTag(); string jpnMessage = (j < langBanks[0].Messages.Count ? langBanks[0].Messages[j].Text : string.Empty); for (int k = 0; k < langBanks.Length; k++) { if (langBanks[k] == null) { continue; } string message = (j < langBanks[k].Messages.Count ? langBanks[k].Messages[j].Text : string.Empty); if (k != 0 && jpnMessage.Equals(message) || message.StartsWith("エラー" + Environment.NewLine)) { html.AddAttribute(HtmlTextWriterAttribute.Class, "message-desc-suspicious"); } else { html.AddAttribute(HtmlTextWriterAttribute.Class, "message-desc-text"); } html.RenderBeginTag(HtmlTextWriterTag.Td); { message = message.Replace(" ", " "); message = message.Replace("<", "<"); message = message.Replace(">", ">"); message = message.Replace(Environment.NewLine, "<br />"); message = message.Replace("[Highlight:On]", "<span style=\"color:#ff0000;\">"); message = message.Replace("[Highlight:Off]", "</span>"); int numSpanStart = CountSubstrings(message, "<span "); int numSpanEnd = CountSubstrings(message, "</span>"); if (numSpanStart > numSpanEnd) { message += "</span>"; } else if (numSpanEnd > numSpanStart) { message = "<span>" + message; } html.Write(message); } html.RenderEndTag(); } for (int k = 0; k < langBanks.Length; k++) { if (langBanks[k] == null) { continue; } Message message = langBanks[k].Messages[j]; html.AddAttribute(HtmlTextWriterAttribute.Class, "message-desc-sim"); html.RenderBeginTag(HtmlTextWriterTag.Td); { string imgFile = string.Format("img\\{0}-{1}-{2}.png", i, j, k); string imgPath = Path.Combine(Path.GetDirectoryName(filename), imgFile); if (!Directory.Exists(Path.GetDirectoryName(imgPath))) { Directory.CreateDirectory(Path.GetDirectoryName(imgPath)); } Bitmap image = (k == 0 ? romPrimary.GetMessageImage(message) : romSecondary.GetMessageImage(message)); if (image == null) { continue; } image.Save(imgPath); html.AddAttribute(HtmlTextWriterAttribute.Src, imgFile.Replace('\\', '/')); html.AddAttribute(HtmlTextWriterAttribute.Alt, Path.GetFileNameWithoutExtension(imgFile)); html.RenderBeginTag(HtmlTextWriterTag.Img); html.RenderEndTag(); html.WriteBreak(); } html.RenderEndTag(); } } html.RenderEndTag(); } } html.RenderEndTag(); html.WriteBreak(); } } html.RenderEndTag(); } html.RenderEndTag(); } writer.Close(); }
public RomHandler(string filename) { FileName = filename; using (FileStream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { byte[] romData = new byte[fileStream.Length]; if (romData.Length != fileStream.Read(romData, 0, romData.Length)) { throw new Exception("Data read mismatch"); } string gameId = Encoding.ASCII.GetString(romData, 0xAC, 4); switch (gameId) { case "ARZJ": fontOffset = FollowPointer(romData, 0xBC11C); baseMessageTextOffset = FollowPointer(romData, 0xBC99C); baseMessageIdxOffset = FollowPointer(romData, 0xBC9A0); bankXTextOffset = FollowPointer(romData, 0xF440); bankXIdxOffset = FollowPointer(romData, 0xF438); Language = GameLanguage.Japanese; break; case "AZCE": fontOffset = FollowPointer(romData, 0xBBFF8); baseMessageTextOffset = FollowPointer(romData, 0xBC878); baseMessageIdxOffset = FollowPointer(romData, 0xBC87C); bankXTextOffset = FollowPointer(romData, 0xF44C); bankXIdxOffset = FollowPointer(romData, 0xF444); Language = GameLanguage.English; break; default: throw new Exception(string.Format("Unknown ROM or game version '{0}'", gameId)); } MessageBanks = new MessageBank[((baseMessageTextOffset - baseMessageIdxOffset) / 4) + 1]; MessageBanks[0] = new MessageBank(romData, -1, bankXTextOffset, bankXIdxOffset, Language); for (int i = 1; i < MessageBanks.Length; i++) { MessageBanks[i] = new MessageBank( romData, i, FollowPointer(romData, (uint)(baseMessageTextOffset + ((i - 1) * 4))), FollowPointer(romData, (uint)(baseMessageIdxOffset + ((i - 1) * 4))), Language); } MessageStyles = new MessageStyle[BitConverter.ToUInt32(romData, MessageStyle.BaseOffset) / MessageStyle.SizeOf]; for (int i = 0; i < MessageStyles.Length; i++) { MessageStyles[i] = new MessageStyle(romData, (MessageStyle.BaseOffset + (i * MessageStyle.SizeOf))); } FontImage = GBAGraphics.GetMMZFont(romData, (int)fontOffset, romData, (int)(fontOffset - 0x20), false); FontImageHighlighted = GBAGraphics.GetMMZFont(romData, (int)fontOffset, romData, (int)(fontOffset - 0x20), true); } }