public override void Inject(bool encrypt, string outputPath, string shortName, string longName, Bitmap menuIconImg, Bitmap bootTvImg, Bitmap bootDrcImg) { string outPath = GetValidOutputPath(outputPath, shortName); if (Directory.Exists(outPath) && (Directory.GetDirectories(outPath).Length != 0 || Directory.GetFiles(outPath).Length != 0)) { throw new Exception("The output path \"" + outPath + "\"exists and is not empty."); } Base = GetLoadedBase(); if (!BaseIsLoaded) { throw new Exception("The base is not ready."); } InjectImages(menuIconImg, bootTvImg, bootDrcImg); if (RomIsValid) { InjectMeta(shortName, longName); } InjectRom(); if (encrypt) { NusContent.Encrypt(BasePath, outPath); } else if (!Useful.DirectoryCopy(BasePath, outPath, true)) { throw new Exception("\"" + BasePath + "\" copy failed."); } }
public void LoadBase(string path) { NusContent.Format format = NusContent.GetFormat(path); if (format == NusContent.Format.Decrypted) { ValidateBase(path); if (Directory.Exists(BasePath)) { Directory.Delete(BasePath, true); Base = null; } if (Useful.DirectoryCopy(path, BasePath, true)) { Base = GetLoadedBase(); } else { throw new Exception("Could not load base \"" + path + "\"."); } } else if (format == NusContent.Format.Encrypted) { ValidateEncryptedBase(path); if (Directory.Exists(BasePath)) { Directory.Delete(BasePath, true); Base = null; } Directory.CreateDirectory(BasePath); NusContent.Decrypt(path, BasePath); Base = GetLoadedBase(); } else { StringBuilder strBuilder = new StringBuilder(); strBuilder.AppendLine("The folder not contains a valid NUS content."); strBuilder.AppendLine("If it is an unpackaged (decrypted) NUS content, then:"); strBuilder.AppendLine("The \"" + path + "\\code\" folder not exist."); strBuilder.AppendLine("Or \"" + path + "\\content\" folder not exist."); strBuilder.AppendLine("Or \"" + path + "\\meta\" folder not exist."); strBuilder.AppendLine("If it is an packaged (encrypted) NUS content, then:"); strBuilder.AppendLine("The \"" + path + "\\title.tmd\" file not exist."); strBuilder.AppendLine("Or \"" + path + "\\title.tik\" file not exist."); strBuilder.AppendLine("Or \"" + path + "\\title.cert\" file not exist."); throw new Exception(strBuilder.ToString()); } }
//The UTF8 validator is not 100% reliable. public static bool UTF8Validator(string filename) { if (File.Exists(filename)) { FileStream fs = File.Open(filename, FileMode.Open); byte[] file = new byte[fs.Length]; fs.Read(file, 0, file.Length); fs.Close(); return(Useful.IsUTF8(file)); } else { throw new Exception("N64 config file \"" + filename + "\" not exists."); } }
protected string GetValidOutputPath(string outputPath, string shortName) { if (!Directory.Exists(outputPath)) { throw new Exception("The output path \"" + outputPath + "\" not exist."); } if (shortName.Length == 0) { throw new Exception("The short name is empty."); } char[] array = Useful.Windows1252ToASCII(shortName, '_').ToCharArray(); char[] invalid = Path.GetInvalidFileNameChars(); for (int i = 0; i < array.Length; i++) { foreach (char c in invalid) { if (array[i] == c) { array[i] = '_'; } } } string folderName = new string(array); StringBuilder strBuilder = new StringBuilder(outputPath.Length + folderName.Length + 20); strBuilder.Append(outputPath); strBuilder.Append("\\"); strBuilder.Append(folderName); strBuilder.Append(" ["); if (RomIsValid) { strBuilder.Append(TitleId); strBuilder.Append("]"); } else { strBuilder.Append(NusContent.GetTitleID(BasePath)); strBuilder.Append("] (Edited)"); } return(strBuilder.ToString()); }
public override string ToString() { return("Hash: " + Hash.ToString("X8") + ", Release date: " + Release.ToString("yyyy/MM/dd") + ", Type: " + Type.ToString() + ", ROM size: " + Useful.ToFileSize(ROMSize) + ", FDS ROM: " + FDSROM.ToString() + "\r\nTitle: " + Title); }
public RomGBA(string filename) : base() { byte[] header = new byte[0xC0]; FileStream fs = File.OpenRead(filename); fs.Read(header, 0, 0xC0); fs.Close(); if (Validate(header)) { byte uniqueCode; byte[] shortTitle = new byte[2]; byte region; uniqueCode = header[0xAC]; shortTitle[0] = header[0xAD]; shortTitle[1] = header[0xAE]; region = header[0xAF]; if (Useful.IsUpperLetterOrDigit(uniqueCode)) { FormatCode = (char)uniqueCode; } if (Useful.IsUpperLetterOrDigit(shortTitle[0]) && Useful.IsUpperLetterOrDigit(shortTitle[1])) { ShortId = Encoding.ASCII.GetString(shortTitle); } if (Useful.IsUpperLetterOrDigit(region)) { RegionCode = (char)region; } if (Useful.IsUpperLetterOrDigit(header[0xBC])) { Version = header[0xBC]; } byte[] titleBytes = new byte[0x0C]; Array.Copy(header, 0xA0, titleBytes, 0, 0x0C); int count = 0x0C; while (--count >= 0 && titleBytes[count] == 0) { ; } Title = Encoding.ASCII.GetString(titleBytes, 0, count + 1); fs = File.Open(filename, FileMode.Open); Size = (int)fs.Length; HashCRC16 = Cll.Security.ComputeCRC16(fs); fs.Close(); if (Size > 33554432) { throw new FormatException("The GBA ROM has more than 32 MiB."); } IsValid = true; Console = Format.GBA; } else { throw new FormatException("Check bytes in the GBA ROM header are invalid."); } }
public RomSNES(string filename) : base() { IsSMC = false; Mode = Subformat.Indeterminate; FileStream fs = File.OpenRead(filename); int smcHeaderSize = SMCHeaderSize((int)fs.Length); byte[] data = GetData(fs, smcHeaderSize); fs.Close(); if (smcHeaderSize == 0x200) { IsSMC = true; } int headerOffset = -1; Mode = GetFormat(data, ref headerOffset); if (Mode != Subformat.Indeterminate) { if (data[headerOffset + 0x2A] == 0x33) { byte uniqueCode; byte[] shortTitle = new byte[2]; byte region; uniqueCode = data[headerOffset + 0x02]; shortTitle[0] = data[headerOffset + 0x03]; shortTitle[1] = data[headerOffset + 0x04]; region = data[headerOffset + 0x05]; if (Useful.IsUpperLetterOrDigit(uniqueCode)) { FormatCode = (char)uniqueCode; } if (Useful.IsUpperLetterOrDigit(shortTitle[0]) && Useful.IsUpperLetterOrDigit(shortTitle[1])) { ShortId = Encoding.ASCII.GetString(shortTitle); } if (Useful.IsUpperLetterOrDigit(region)) { RegionCode = (char)region; } } Version = data[headerOffset + 0x2B]; byte[] titleBytes = new byte[21]; Array.Copy(data, headerOffset + 0x10, titleBytes, 0, 21); int count = 21; while (--count >= 0 && titleBytes[count] == 0x20) { ; } Title = Encoding.ASCII.GetString(titleBytes, 0, count + 1); Size = data.Length; HashCRC16 = Cll.Security.ComputeCRC16_ARC(data, 0, data.Length); IsValid = true; Console = Format.SNES_USA; } else { Size = 0; throw new FormatException("It was not possible to determine the SNES ROM format."); } }
public override string ToString() { return("Hash: " + Hash.ToString("X8") + ", Release date: " + Release.ToString("yyyy/MM/dd") + ", Type: " + Type.ToString() + ", ROM size: " + Useful.ToFileSize(ROMSize) + ", Extended footer: " + ExtendedFooter.ToString() + ", PCM data: " + PCMData.ToString() + "\r\nTitle: " + Title); }
public RomN64(string filename) : base() { Endianness = Subformat.Indeterminate; byte[] header = new byte[0x40]; FileStream fs = File.Open(filename, FileMode.Open); Size = (int)fs.Length; fs.Read(header, 0, 0x40); fs.Close(); Endianness = GetFormat(header); if (Endianness == Subformat.BigEndian || (Endianness != Subformat.Indeterminate && Size % 4 == 0)) { byte uniqueCode; byte[] shortTitle = new byte[2]; byte region; header = ToBigEndian(header, Endianness); uniqueCode = header[0x3B]; shortTitle[0] = header[0x3C]; shortTitle[1] = header[0x3D]; region = header[0x3E]; if (Useful.IsUpperLetterOrDigit(uniqueCode)) { FormatCode = (char)uniqueCode; } if (Useful.IsUpperLetterOrDigit(shortTitle[0]) && Useful.IsUpperLetterOrDigit(shortTitle[1])) { ShortId = Encoding.ASCII.GetString(shortTitle); } if (Useful.IsUpperLetterOrDigit(region)) { RegionCode = (char)region; } if (Useful.IsUpperLetterOrDigit(header[0x3F])) { Version = header[0x3F]; } byte[] titleBytes = new byte[20]; Array.Copy(header, 0x20, titleBytes, 0, 20); int count = 20; while (--count >= 0 && titleBytes[count] == 0x20) { ; } Title = Encoding.ASCII.GetString(titleBytes, 0, count + 1); fs = File.Open(filename, FileMode.Open); HashCRC16 = Cll.Security.ComputeCRC16(fs); fs.Close(); IsValid = true; Console = Format.N64; } else { Size = 0; throw new FormatException("It was not possible to determine the N64 ROM format."); } }
public RomNDS(string filename) : base() { TitleLine1 = ""; TitleLine2 = ""; Icon = null; byte[] header = new byte[0x200]; FileStream fs = File.OpenRead(filename); fs.Read(header, 0, 0x200); fs.Close(); if (Validate(header)) { byte uniqueCode; byte[] shortTitle = new byte[2]; byte region; uniqueCode = header[0x0C]; shortTitle[0] = header[0x0D]; shortTitle[1] = header[0x0E]; region = header[0x0F]; if (Useful.IsUpperLetterOrDigit(uniqueCode)) { FormatCode = (char)uniqueCode; } if (Useful.IsUpperLetterOrDigit(shortTitle[0]) && Useful.IsUpperLetterOrDigit(shortTitle[1])) { ShortId = Encoding.ASCII.GetString(shortTitle); } if (Useful.IsUpperLetterOrDigit(region)) { RegionCode = (char)region; } if (Useful.IsUpperLetterOrDigit(header[0x1E])) { Version = header[0x1E]; } byte[] offsetBytes = new byte[4]; byte[] bitmapBytes = new byte[0x200]; byte[] paletteBytes = new byte[0x20]; byte[] titleBytes = new byte[0x100]; fs = File.OpenRead(filename); Size = (int)fs.Length; fs.Seek(0x68, SeekOrigin.Begin); fs.Read(offsetBytes, 0, 4); int offset = (offsetBytes[3] << 24) + (offsetBytes[2] << 16) + (offsetBytes[1] << 8) + offsetBytes[0]; fs.Seek(offset + 0x20, SeekOrigin.Begin); fs.Read(bitmapBytes, 0, 0x200); fs.Read(paletteBytes, 0, 0x20); fs.Read(titleBytes, 0, 0x100); fs.Position = 0; HashCRC16 = Cll.Security.ComputeCRC16(fs); fs.Close(); string title = Encoding.Unicode.GetString(titleBytes); string[] lines = title.Split(new char[] { '\n' }); if (lines.Length == 2) { Title = lines[0]; TitleLine1 = lines[0]; } else if (lines.Length >= 3) { Title = lines[0] + " " + lines[1]; TitleLine1 = lines[0]; TitleLine2 = lines[1]; } Color[] palette = new Color[16]; int j = -1; for (int i = 0; i < 16; i++) { palette[i] = Color.FromArgb( (paletteBytes[++j] & 0x1F) << 3, //0000 0000 0001 1111 ((paletteBytes[j] & 0xE0) >> 2) + //0000 0000 1110 0000 ((paletteBytes[++j] & 0x03) << 6), //0000 0011 0000 0000 (paletteBytes[j] & 0x7C) << 1); //0111 1100 0000 0000 } palette[0] = Color.FromArgb(0, palette[0].R, palette[0].G, palette[0].B); byte[] pix = new byte[1024]; int pixIndex; int bytesIndex; for (int tileY = 0; tileY < 4; tileY++) { for (int tileX = 0; tileX < 4; tileX++) { for (int i = 0; i < 8; i++) { pixIndex = i * 32 + tileX * 8 + tileY * 256; bytesIndex = i * 4 + tileX * 32 + tileY * 128; pix[pixIndex] = (byte)(bitmapBytes[bytesIndex] & 0x0F); pix[pixIndex + 1] = (byte)((bitmapBytes[bytesIndex] & 0xF0) >> 4); pix[pixIndex + 2] = (byte)(bitmapBytes[bytesIndex + 1] & 0x0F); pix[pixIndex + 3] = (byte)((bitmapBytes[bytesIndex + 1] & 0xF0) >> 4); pix[pixIndex + 4] = (byte)(bitmapBytes[bytesIndex + 2] & 0x0F); pix[pixIndex + 5] = (byte)((bitmapBytes[bytesIndex + 2] & 0xF0) >> 4); pix[pixIndex + 6] = (byte)(bitmapBytes[bytesIndex + 3] & 0x0F); pix[pixIndex + 7] = (byte)((bitmapBytes[bytesIndex + 3] & 0xF0) >> 4); } } } Bitmap icon = new Bitmap(32, 32); Rectangle rect = new Rectangle(0, 0, icon.Width, icon.Height); System.Drawing.Imaging.BitmapData data = icon.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, icon.PixelFormat); int length = data.Width * data.Height * 4; byte[] iconBytes = new byte[length]; IntPtr ptr = data.Scan0; System.Runtime.InteropServices.Marshal.Copy(ptr, iconBytes, 0, length); Color color; for (int i = 0; i < 1024; i++) { color = palette[pix[i]]; iconBytes[i * 4] = color.B; iconBytes[i * 4 + 1] = color.G; iconBytes[i * 4 + 2] = color.R; iconBytes[i * 4 + 3] = color.A; } System.Runtime.InteropServices.Marshal.Copy(iconBytes, 0, ptr, length); icon.UnlockBits(data); Icon = icon; IsValid = true; Console = Format.NDS; } else { throw new FormatException("Checksums in the NDS ROM header are invalid."); } }
protected void InjectMeta(string shortName, string longName) { string titleId = TitleId; byte[] id = Useful.StrHexToByteArray(titleId, ""); XmlWriterSettings xmlSettings = new XmlWriterSettings { Encoding = new UTF8Encoding(false), Indent = true, IndentChars = " ", NewLineChars = "\n", NewLineHandling = NewLineHandling.Replace }; XmlDocument xmlApp = new XmlDocument(); XmlDocument xmlMeta = new XmlDocument(); xmlApp.Load(BasePath + "\\code\\app.xml"); xmlMeta.Load(BasePath + "\\meta\\meta.xml"); XmlNode app_title_id = xmlApp.SelectSingleNode("app/title_id"); XmlNode app_group_id = xmlApp.SelectSingleNode("app/group_id"); XmlNode meta_product_code = xmlMeta.SelectSingleNode("menu/product_code"); XmlNode meta_title_id = xmlMeta.SelectSingleNode("menu/title_id"); XmlNode meta_group_id = xmlMeta.SelectSingleNode("menu/group_id"); XmlNode meta_longname_ja = xmlMeta.SelectSingleNode("menu/longname_ja"); XmlNode meta_longname_en = xmlMeta.SelectSingleNode("menu/longname_en"); XmlNode meta_longname_fr = xmlMeta.SelectSingleNode("menu/longname_fr"); XmlNode meta_longname_de = xmlMeta.SelectSingleNode("menu/longname_de"); XmlNode meta_longname_it = xmlMeta.SelectSingleNode("menu/longname_it"); XmlNode meta_longname_es = xmlMeta.SelectSingleNode("menu/longname_es"); XmlNode meta_longname_zhs = xmlMeta.SelectSingleNode("menu/longname_zhs"); XmlNode meta_longname_ko = xmlMeta.SelectSingleNode("menu/longname_ko"); XmlNode meta_longname_nl = xmlMeta.SelectSingleNode("menu/longname_nl"); XmlNode meta_longname_pt = xmlMeta.SelectSingleNode("menu/longname_pt"); XmlNode meta_longname_ru = xmlMeta.SelectSingleNode("menu/longname_ru"); XmlNode meta_longname_zht = xmlMeta.SelectSingleNode("menu/longname_zht"); XmlNode meta_shortname_ja = xmlMeta.SelectSingleNode("menu/shortname_ja"); XmlNode meta_shortname_en = xmlMeta.SelectSingleNode("menu/shortname_en"); XmlNode meta_shortname_fr = xmlMeta.SelectSingleNode("menu/shortname_fr"); XmlNode meta_shortname_de = xmlMeta.SelectSingleNode("menu/shortname_de"); XmlNode meta_shortname_it = xmlMeta.SelectSingleNode("menu/shortname_it"); XmlNode meta_shortname_es = xmlMeta.SelectSingleNode("menu/shortname_es"); XmlNode meta_shortname_zhs = xmlMeta.SelectSingleNode("menu/shortname_zhs"); XmlNode meta_shortname_ko = xmlMeta.SelectSingleNode("menu/shortname_ko"); XmlNode meta_shortname_nl = xmlMeta.SelectSingleNode("menu/shortname_nl"); XmlNode meta_shortname_pt = xmlMeta.SelectSingleNode("menu/shortname_pt"); XmlNode meta_shortname_ru = xmlMeta.SelectSingleNode("menu/shortname_ru"); XmlNode meta_shortname_zht = xmlMeta.SelectSingleNode("menu/shortname_zht"); app_title_id.InnerText = titleId; app_group_id.InnerText = "0000" + id[5].ToString("X2") + id[6].ToString("X2"); if (!Rom.ProductCode.Contains("?")) { meta_product_code.InnerText = "WUP-N-" + Rom.ProductCode; } meta_title_id.InnerText = titleId; meta_group_id.InnerText = "0000" + id[5].ToString("X2") + id[6].ToString("X2"); meta_longname_ja.InnerText = longName; meta_longname_en.InnerText = longName; meta_longname_fr.InnerText = longName; meta_longname_de.InnerText = longName; meta_longname_it.InnerText = longName; meta_longname_es.InnerText = longName; meta_longname_zhs.InnerText = longName; meta_longname_ko.InnerText = longName; meta_longname_nl.InnerText = longName; meta_longname_pt.InnerText = longName; meta_longname_ru.InnerText = longName; meta_longname_zht.InnerText = longName; meta_shortname_ja.InnerText = shortName; meta_shortname_en.InnerText = shortName; meta_shortname_fr.InnerText = shortName; meta_shortname_de.InnerText = shortName; meta_shortname_it.InnerText = shortName; meta_shortname_es.InnerText = shortName; meta_shortname_zhs.InnerText = shortName; meta_shortname_ko.InnerText = shortName; meta_shortname_nl.InnerText = shortName; meta_shortname_pt.InnerText = shortName; meta_shortname_ru.InnerText = shortName; meta_shortname_zht.InnerText = shortName; XmlWriter app = XmlWriter.Create(BasePath + "\\code\\app.xml", xmlSettings); XmlWriter meta = XmlWriter.Create(BasePath + "\\meta\\meta.xml", xmlSettings); xmlApp.Save(app); xmlMeta.Save(meta); app.Close(); meta.Close(); }