public void modelOpen() { string path = textBox1.Text; EndianBinaryReader readModel = new EndianBinaryReader(File.OpenRead(path), Endianness.LittleEndian); nsbmd = new NSBMD_File(); if (readModel.ReadString(Encoding.ASCII, 4) != "BMD0") { readModel.Close(); return; } else { nsbmd.Header.ID = "BMD0"; nsbmd.Header.Magic = readModel.ReadBytes(4); nsbmd.Header.file_size = readModel.ReadInt32(); nsbmd.Header.header_size = readModel.ReadInt16(); nsbmd.Header.nSection = readModel.ReadInt16(); nsbmd.Header.Section_Offset = new Int32[nsbmd.Header.nSection]; for (int i = 0; i < nsbmd.Header.nSection; i++) { nsbmd.Header.Section_Offset[i] = readModel.ReadInt32(); } nsbmd.MDL0.ID = readModel.ReadString(Encoding.ASCII, 4); if (nsbmd.MDL0.ID != "MDL0") { readModel.Close(); return; } nsbmd.MDL0.Section_size = readModel.ReadInt32(); nsbmd.MDL0.Padding1 = readModel.ReadByte(); nsbmd.MDL0.Model_count = readModel.ReadByte(); nsbmd.MDL0.Section_size = readModel.ReadInt16(); nsbmd.MDL0.Constant = readModel.ReadInt16(); nsbmd.MDL0.Subsection_size = readModel.ReadInt16(); nsbmd.MDL0.Constant2 = readModel.ReadInt32(); nsbmd.MDL0.Unknown = new int[nsbmd.MDL0.Model_count]; for (int i = 0; i < nsbmd.MDL0.Model_count; i++) { nsbmd.MDL0.Unknown[i] = readModel.ReadInt32(); } nsbmd.MDL0.Constant3 = readModel.ReadInt16(); nsbmd.MDL0.Section2_size = readModel.ReadInt16(); nsbmd.MDL0.Model_offset = new int[nsbmd.MDL0.Model_count]; for (int i = 0; i < nsbmd.MDL0.Model_count; i++) { nsbmd.MDL0.Model_offset[i] = readModel.ReadInt32(); } nsbmd.MDL0.Model_name = new string[nsbmd.MDL0.Model_count]; for (int i = 0; i < nsbmd.MDL0.Model_count; i++) { nsbmd.MDL0.Model_name[i] = readModel.ReadString(Encoding.ASCII, 16); } readModel.Close(); } }
// Public Methods (2) /// <summary> /// Load NSBTX from stream. /// </summary> /// <param name="stream">Stream to use.</param> /// <returns>Material definitions.</returns> public static IEnumerable<NsbmdAnimation> LoadNsbca(Stream stream) { List<NsbmdAnimation> animation = new List<NsbmdAnimation>(); var reader = new EndianBinaryReader(stream, Endianness.LittleEndian); byte[] id = reader.ReadBytes(4); if (id == new byte[] { 0x42, 0x43, 0x41, 0x30 }) { throw new Exception(); } int i = reader.ReadInt32(); if (i == Nsbmd.NDS_TYPE_MAGIC1) { i = reader.ReadInt32(); if (i == stream.Length) { int numblock = reader.ReadInt32(); numblock >>= 16; int r = reader.ReadInt32(); id = reader.ReadBytes(4); if (numblock == 1 && r == 0x14) { animation.AddRange(ReadJnt0(stream, 0x14)); } } } reader.Close(); return animation; }
public override void ToXml(XmlDocument yaml, XmlNode node, List<string> nodes, List<string> values, List<byte[]> data) { XmlAttribute attr = yaml.CreateAttribute("type"); attr.Value = "path"; node.Attributes.Append(attr); using (EndianBinaryReader rd = new EndianBinaryReader(new MemoryStream(data[Value]))) { while (rd.BaseStream.Position != rd.BaseStream.Length) { XmlElement point = yaml.CreateElement("point"); point.SetAttribute("x", rd.ReadSingle().ToString(CultureInfo.InvariantCulture) + "f"); point.SetAttribute("y", rd.ReadSingle().ToString(CultureInfo.InvariantCulture) + "f"); point.SetAttribute("z", rd.ReadSingle().ToString(CultureInfo.InvariantCulture) + "f"); point.SetAttribute("nx", rd.ReadSingle().ToString(CultureInfo.InvariantCulture) + "f"); point.SetAttribute("ny", rd.ReadSingle().ToString(CultureInfo.InvariantCulture) + "f"); point.SetAttribute("nz", rd.ReadSingle().ToString(CultureInfo.InvariantCulture) + "f"); point.SetAttribute("val", rd.ReadInt32().ToString(CultureInfo.InvariantCulture)); node.AppendChild(point); } rd.Close(); } }
private static void ConvertPath(string path) { using (var reader = new EndianBinaryReader(new FileStream(path, FileMode.Open))) { string outpath; bool toyaml; if (reader.ReadString(Encoding.ASCII, 2) == "BY") { toyaml = true; outpath = Path.ChangeExtension(path, "xml"); if (outpath == path) outpath = path + ".xml"; } else { toyaml = false; outpath = Path.ChangeExtension(path, "byaml"); if (outpath == path) outpath = path + ".byaml"; } reader.BaseStream.Seek(0, SeekOrigin.Begin); if (toyaml) { ConvertFromByaml(reader, outpath); } else { ConvertToByaml(reader, outpath); } reader.Close(); } }
/// <summary> /// genAIS command. Always use section-by-section CRC checks /// </summary> /// <param name="coffFileName"></param> /// <param name="bootMode"></param> /// <returns>Bytes of the binary or text AIS command</returns> public static Byte[] GenAIS(String coffFileName, AISGen devAISGen, INISection[] iniSecs) { UInt32 busWidth = 8; UInt32 addrWidth = 16; UInt32 numTargetSections = 0; UInt32 numWords; UInt32 entryPoint = 0x00000000; Boolean seqReadEn = false; // Not supported on all devices String finalFxnName = null; // Not supported in all devices Hashtable UARTSendDONE_DataSection=null, UARTSendDONE_TextSection=null; // Lists to keep track of the input object and binary files List<ObjectFile> objectFiles = new List<ObjectFile>(); List<BinaryFile> binaryFiles = new List<BinaryFile>(); // COFF file objects for the main application and the AIS extras executable COFFFile AISExtrasCF=null; // Set defaults devAISGen.finalFxnName = null; // List to keep track of loadable sections and their occupied memory ranges devAISGen.sectionMemory = new List<MemoryRange>(); // Setup the binary writer to generate the temp AIS file devAISGen.devAISStream = new MemoryStream(); EndianBinaryWriter tempAIS_bw = new EndianBinaryWriter( devAISGen.devAISStream, devAISGen.devEndian); #region INI Data parsing // Get data from the GENERAL INI Section for (UInt32 i = 0; i < iniSecs.Length; i++) { INISection sec = iniSecs[i]; if (sec.iniSectionName.Equals("GENERAL", StringComparison.OrdinalIgnoreCase)) { foreach (DictionaryEntry de in sec.sectionValues) { // Read buswidth if (((String)de.Key).Equals("BUSWIDTH", StringComparison.OrdinalIgnoreCase)) busWidth = (UInt32)sec.sectionValues["BUSWIDTH"]; // Read BootMode (unless already set) if ((((String)de.Key).Equals("BOOTMODE", StringComparison.OrdinalIgnoreCase)) && (devAISGen.bootMode == BootModes.NONE)) devAISGen.bootMode = (BootModes) Enum.Parse(typeof(BootModes), (String)sec.sectionValues["BOOTMODE"], true); // Read Addr width (for I2C/SPI) if (((String)de.Key).Equals("ADDRWIDTH", StringComparison.OrdinalIgnoreCase)) addrWidth = (UInt32)sec.sectionValues["ADDRWIDTH"]; // Sequential Read ENABLE if (((String)de.Key).Equals("SEQREADEN", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["SEQREADEN"]).Equals("ON", StringComparison.OrdinalIgnoreCase)) seqReadEn = true; if (((String)sec.sectionValues["SEQREADEN"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) seqReadEn = true; } // CRC Type override if (((String)de.Key).Equals("CRCCHECKTYPE", StringComparison.OrdinalIgnoreCase)) { devAISGen.CRCType = (CRCCheckType) Enum.Parse(typeof(CRCCheckType), (String)sec.sectionValues["CRCCHECKTYPE"], true); } // Finalize fxn symbol name if (((String)de.Key).Equals("FINALFXNSYMBOLNAME", StringComparison.OrdinalIgnoreCase)) { finalFxnName = (String)sec.sectionValues["FINALFXNSYMBOLNAME"]; } // Read entrypoint value if (((String)de.Key).Equals("ENTRYPOINT", StringComparison.OrdinalIgnoreCase)) entryPoint = (UInt32)sec.sectionValues["ENTRYPOINT"]; } } if (sec.iniSectionName.Equals("BINARYINPUTFILE", StringComparison.OrdinalIgnoreCase)) { BinaryFile currFile = new BinaryFile(); currFile.fileName = null; currFile.useEntryPoint = false; currFile.loadAddr = 0x00000000; currFile.entryPointAddr = 0x00000000; foreach (DictionaryEntry de in sec.sectionValues) { // File name for binary section data if (((String)de.Key).Equals("FILENAME", StringComparison.OrdinalIgnoreCase)) { currFile.fileName = (String) sec.sectionValues["FILENAME"]; } // Binary section's load address in the memory map if (((String)de.Key).Equals("LOADADDRESS", StringComparison.OrdinalIgnoreCase)) { currFile.loadAddr = (UInt32) sec.sectionValues["LOADADDRESS"]; } // Binary section's entry point address in the memory map if (((String)de.Key).Equals("ENTRYPOINTADDRESS", StringComparison.OrdinalIgnoreCase)) { currFile.entryPointAddr = (UInt32) sec.sectionValues["ENTRYPOINTADDRESS"]; } // Option to specify that this entry point should be used for AIS if (((String)de.Key).Equals("USEENTRYPOINT", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["USEENTRYPOINT"]).Equals("YES", StringComparison.OrdinalIgnoreCase)) currFile.useEntryPoint = true; if (((String)sec.sectionValues["USEENTRYPOINT"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) currFile.useEntryPoint = true; } } if (currFile.fileName == null) { Console.WriteLine("ERROR: File name must be provided for binary input file."); return null; } if (currFile.loadAddr == 0x00000000) { Console.WriteLine("ERROR: Valid load address must be provided for binary input file."); return null; } binaryFiles.Add(currFile); } if (sec.iniSectionName.Equals("OBJECTINPUTFILE", StringComparison.OrdinalIgnoreCase)) { ObjectFile currFile = new ObjectFile(); currFile.useEntryPoint = false; currFile.fileName = null; foreach (DictionaryEntry de in sec.sectionValues) { // File name for binary section data if (((String)de.Key).Equals("FILENAME", StringComparison.OrdinalIgnoreCase)) { currFile.fileName = (String) sec.sectionValues["FILENAME"]; } // Option to specify that this entry point should be used for AIS if (((String)de.Key).Equals("USEENTRYPOINT", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["USEENTRYPOINT"]).Equals("YES", StringComparison.OrdinalIgnoreCase)) currFile.useEntryPoint = true; if (((String)sec.sectionValues["USEENTRYPOINT"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) currFile.useEntryPoint = true; } } if (currFile.fileName == null) { Console.WriteLine("ERROR: File name must be provided for input object file."); return null; } objectFiles.Add(currFile); } } #endregion #region AIS Generation // --------------------------------------------------------- // ****************** BEGIN AIS GENERATION ***************** // --------------------------------------------------------- Console.WriteLine("Begining the AIS file generation."); // Diaplay currently selected boot mode Console.WriteLine("AIS file being generated for bootmode: {0}.",Enum.GetName(typeof(BootModes),devAISGen.bootMode)); #region AIS Extras and UARTSendDONE Setup //Create the COFF file object for the AISExtras file (if it exists/is defined) if (devAISGen.AISExtraFileName != null) { EmbeddedFileIO.ExtractFile(Assembly.GetExecutingAssembly(), devAISGen.AISExtraFileName, false); if (File.Exists(devAISGen.AISExtraFileName)) { // The file exists, so use it AISExtrasCF = new COFFFile(devAISGen.AISExtraFileName); } else { throw new FileNotFoundException("The AISExtra file, " + devAISGen.AISExtraFileName + ", was not found."); } } // If we have the AISExtras COFF file object, use it to setup the addresses // for the AISExtra functions. These will utilize the L1P and L1D spaces that // are usually cache. if ( (AISExtrasCF != null) && (devAISGen.AISExtraFunc != null)) { // Use symbols to get address for AISExtra functions and parameters for (Int32 i = 0; i < devAISGen.AISExtraFunc.Length; i++) { Hashtable sym = AISExtrasCF.symFind("_" + devAISGen.AISExtraFunc[i].funcName); devAISGen.AISExtraFunc[i].funcAddr = (UInt32)sym["value"]; sym = AISExtrasCF.symFind(".params"); devAISGen.AISExtraFunc[i].paramAddr = (UInt32)sym["value"]; } // If the bootMode is UART we need the UARTSendDONE function if (devAISGen.bootMode == BootModes.UART) { // Set address for the UARTSendDone Function in the .text:uart section UARTSendDONE_TextSection = AISExtrasCF.secFind(".text:uart"); UARTSendDONE_DataSection = AISExtrasCF.secFind(".data:uart"); // Eliminate these as loadable since they will be loaded first, separate // from the main COFF file UARTSendDONE_TextSection["copyToTarget"] = false; UARTSendDONE_DataSection["copyToTarget"] = false; AISExtrasCF.Header["numTargetSections"] = ((UInt32)AISExtrasCF.Header["numTargetSections"] - (UInt32)2); // Set the actual run address for the UARTSendDONE function if ((UARTSendDONE_TextSection != null) && (UARTSendDONE_DataSection != null)) { Debug.DebugMSG("UART section found"); devAISGen.UARTSendDONEAddr = (UInt32)UARTSendDONE_TextSection["phyAddr"]; Hashtable sym = AISExtrasCF.symFind("_UARTSendDONE"); if (sym != null) { devAISGen.UARTSendDONEAddr = (UInt32)sym["value"]; Debug.DebugMSG("UARTSendDONE at 0x{0:X8}",devAISGen.UARTSendDONEAddr); } } else { Console.WriteLine("UARTSendDONE function not found in AISExtra COFF file!!!"); return null; } } } // Setup boolean indicating whether to include UARTSendDONE jump commands if ((devAISGen.bootMode == BootModes.UART) && (devAISGen.UARTSendDONEAddr != 0x0)) devAISGen.SendUARTSendDONE = true; else devAISGen.SendUARTSendDONE = false; #endregion #region Write AIS MAGIC Number and initial data // Write the premilinary header and fields (everything before first AIS command) switch (devAISGen.bootMode) { case BootModes.EMIFA: { if (busWidth == 16) tempAIS_bw.Write((UInt32)(0x1 << 0)|(0x2 << 4)); else tempAIS_bw.Write((UInt32)(0x0 << 0)|(0x2 << 4)); tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } case BootModes.NAND: { tempAIS_bw.Write((UInt32)AIS.MagicNumber); tempAIS_bw.Write((UInt32)0); tempAIS_bw.Write((UInt32)0); tempAIS_bw.Write((UInt32)0); break; } case BootModes.UART: { tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } case BootModes.I2CMASTER: { if (addrWidth == 16) tempAIS_bw.Write((UInt32)2); else tempAIS_bw.Write((UInt32)1); tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } case BootModes.SPIMASTER: { if (addrWidth == 24) tempAIS_bw.Write((UInt32)3); else if (addrWidth == 16) tempAIS_bw.Write((UInt32)2); else tempAIS_bw.Write((UInt32)1); tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } default: { tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } }; #endregion #region Send UARTSendDONE sections //Send UART code if it exists if (devAISGen.SendUARTSendDONE) { CRCCheckType tempCRCType = devAISGen.crcType; devAISGen.crcType = CRCCheckType.NO_CRC; devAISGen.SendUARTSendDONE = false; AISSectionLoad(AISExtrasCF, UARTSendDONE_TextSection, devAISGen); AISSectionLoad(AISExtrasCF, UARTSendDONE_DataSection, devAISGen); devAISGen.SendUARTSendDONE = true; devAISGen.crcType = tempCRCType; } #endregion #region ROM Function insertion // Insert words for ROM function execution for (UInt32 i = 0; i < devAISGen.ROMFunc.Length; i++) { for (UInt32 j = 0; j < iniSecs.Length; j++) { if (iniSecs[j].iniSectionName.Equals(devAISGen.ROMFunc[i].iniSectionName)) { UInt32 funcIndex = i; tempAIS_bw.Write((UInt32)AIS.FunctionExec); tempAIS_bw.Write((((UInt32)devAISGen.ROMFunc[i].numParams) << 16) + ((UInt32)funcIndex)); // Write Paramter values read from INI file for (Int32 k = 0; k < devAISGen.ROMFunc[i].numParams; k++) { //FIXME Debug.DebugMSG("\tParam name: {0}, Param num: {1}, Value: {2}\n", devAISGen.ROMFunc[i].paramNames[k], k, iniSecs[j].sectionValues[devAISGen.ROMFunc[i].paramNames[k].ToUpper()]); tempAIS_bw.Write((UInt32)iniSecs[j].sectionValues[devAISGen.ROMFunc[i].paramNames[k].ToUpper()]); } // Call UARTSendDONE from AIS Extras if this is for UART boot if (devAISGen.SendUARTSendDONE) { tempAIS_bw.Write((UInt32)AIS.Jump); tempAIS_bw.Write(devAISGen.UARTSendDONEAddr); } } } } #endregion #region Insert seqread command if (seqReadEn == true) tempAIS_bw.Write((UInt32)AIS.SeqReadEnable); #endregion #region AIS executable data download if (AISExtrasCF != null) { // Load the AISExtras COFF file AISCOFFLoad(AISExtrasCF, devAISGen); } #endregion #region AIS Extras init function execution //Insert calls for any AISExtra Init functions (like power domains) if (AISExtrasCF != null) { for (UInt32 i = 0; i < devAISGen.AISExtraFunc.Length; i++) { if (devAISGen.AISExtraFunc[i].isInitFunc) { for (UInt32 j = 0; j < iniSecs.Length; j++) { if (iniSecs[j].iniSectionName.Equals(devAISGen.AISExtraFunc[i].iniSectionName)) { for (UInt32 k = 0; k < devAISGen.AISExtraFunc[i].numParams; k++) { // Write SET command tempAIS_bw.Write((UInt32)AIS.Set); //Write type field (32-bit only) tempAIS_bw.Write((UInt32)0x3); // Write appropriate parameter address tempAIS_bw.Write((UInt32) (devAISGen.AISExtraFunc[i].paramAddr + (k * 4))); //Write data to write tempAIS_bw.Write((UInt32)iniSecs[j].sectionValues[devAISGen.AISExtraFunc[i].paramNames[k].ToString()]); //Write Sleep value (should always be zero) //tempAIS_bw.Write((UInt32)0x1000); tempAIS_bw.Write((UInt32)0x0); } // Now that params are set, Jump to function tempAIS_bw.Write((UInt32)AIS.Jump); tempAIS_bw.Write(devAISGen.AISExtraFunc[i].funcAddr); // Call UARTSendDONE from AIS Extras if this is for UART boot if (devAISGen.SendUARTSendDONE) { tempAIS_bw.Write((UInt32)AIS.Jump); tempAIS_bw.Write(devAISGen.UARTSendDONEAddr); } } } } } } #endregion Debug.DebugMSG("Starting binary file section loads."); #region Insert binary data files as SECTION_LOAD commands // Insert binary files for (Int32 i=0; i<binaryFiles.Count; i++) { if (File.Exists(binaryFiles[i].fileName)) { AISBinarySectionLoad(binaryFiles[i].fileName, devAISGen, binaryFiles[i].loadAddr); Debug.DebugMSG("Binary file {0} found.", binaryFiles[i].fileName); numTargetSections++; if (binaryFiles[i].useEntryPoint) { entryPoint = binaryFiles[i].entryPointAddr; } } else { Console.WriteLine("WARNING: Binary input file {0} was not found. Skipping.",binaryFiles[i].fileName); } } #endregion Debug.DebugMSG("Starting object file section loads."); #region COFF file parsing and loading // Create the COFF file object for the main application being loaded (if it exists) if (File.Exists(coffFileName)) { ObjectFile currFile = new ObjectFile(); currFile.useEntryPoint = true; currFile.fileName = coffFileName; // Cycle throught all other object files loaded via INI file and unset their // useEntryPoint boolean, warning us as we do Boolean showWarning = false; for (Int32 i=0; i<objectFiles.Count; i++) { // Insert binary file if (objectFiles[i].useEntryPoint) { objectFiles[i].useEntryPoint = false; showWarning = true; } } if (showWarning) Console.WriteLine("WARNING: Ignoring useEntryPoint flag from all object file sections of INI file"); objectFiles.Add(currFile); } // Insert object files for (Int32 i=0; i<objectFiles.Count; i++) { if (File.Exists(objectFiles[i].fileName)) { // FIXME: Add support to detect ELF or COFF and support ELF parsing // Parse the object file COFFFile cf = new COFFFile(objectFiles[i].fileName); if (cf != null) { // Load the object file contents AISCOFFLoad(cf, devAISGen); } else { Console.WriteLine("ERROR: Parsing the input object file {0} failed!",objectFiles[i].fileName); } // If entry point is still null, use the coff file one if (entryPoint == 0x00000000) { if (objectFiles[i].useEntryPoint) { entryPoint = (UInt32)cf.Header["optEntryPoint"]; } } // Insert final function register function if (devAISGen.finalFxnName != null) { Hashtable symbol; // Look for the symbol in the Coff file symbols table symbol = cf.symFind(devAISGen.finalFxnName); // If found, insert the command if (symbol != null) { tempAIS_bw.Write((UInt32)AIS.FinalFxnReg); tempAIS_bw.Write((UInt32)symbol["value"]); Console.WriteLine("Finalize function symbol, '{0}', found as address 0x{1:X8}.",devAISGen.finalFxnName,(UInt32)symbol["value"]); } else { Console.WriteLine("Finalize function symbol, '{0}', not found.",devAISGen.finalFxnName); } } // Close object file if (cf != null) cf.Close(); } else { Console.WriteLine("WARNING: Input object file {0} was not found. Skipping.",objectFiles[i].fileName); } } #endregion #region Insert Final JUMP_CLOSE command tempAIS_bw.Write((UInt32)AIS.Jump_Close); tempAIS_bw.Write(entryPoint); if (entryPoint == 0x00000000) Console.WriteLine("WARNING: Entry point never set or set to invalid value"); // Flush the data and then return to start devAISGen.devAISStream.Flush(); devAISGen.devAISStream.Seek(0,SeekOrigin.Begin); #endregion // Console output Console.WriteLine("AIS file generation was successful."); // --------------------------------------------------------- // ******************* END AIS GENERATION ****************** // --------------------------------------------------------- #endregion #region Prepare the return byte array // Now create return Byte array based on tempAIS file and the bootmode EndianBinaryReader tempAIS_br; tempAIS_br = new EndianBinaryReader( devAISGen.devAISStream, Endian.LittleEndian); // Setup the binary reader object numWords = ((UInt32)tempAIS_br.BaseStream.Length) >> 2; devAISGen.AISData = new Byte[numWords << 2]; //Each word converts to 4 binary bytes Debug.DebugMSG("Number of words in the stream is {0}", numWords); // Copy the data to the output Byte array for (UInt32 i = 0; i < numWords; i++) { BitConverter.GetBytes(tempAIS_br.ReadUInt32()).CopyTo(devAISGen.AISData, i * 4); } // Close the binary reader tempAIS_br.Close(); // Close the COFF files since we are done with them if (AISExtrasCF != null) { AISExtrasCF.Close(); } // Clean up any embedded file resources that may have been extracted EmbeddedFileIO.CleanUpEmbeddedFiles(); #endregion // Return Byte Array return devAISGen.AISData; }
/// <summary> /// genAIS command. Always use section-by-section CRC checks /// </summary> /// <param name="coffFileName"></param> /// <param name="bootMode"></param> /// <returns>Bytes of the binary or text AIS command</returns> public static Byte[] GenAIS(String coffFileName, AISGen devAISGen) { UInt32 busWidth = 8; UInt32 numTargetSections; //UInt32 totalLoadableSize = 0; UInt32 numWords; Hashtable UARTSendDONE_DataSection=null, UARTSendDONE_TextSection=null; // COFF file objects for the main application and the AIS extras executable COFFFile cf=null, AISExtrasCF=null; // --------------------------------------------------------- // ****************** BEGIN AIS GENERATION ***************** // --------------------------------------------------------- Console.WriteLine("Begining the AIS file generation."); #region AIS Generation // Setup the binary writer to generate the temp AIS file devAISGen.devAISFileStream = new FileStream( devAISGen.devAISFileName, FileMode.Create, FileAccess.Write); EndianBinaryWriter tempAIS_bw = new EndianBinaryWriter( devAISGen.devAISFileStream, devAISGen.devEndian); #region INI File parsing // Parse the INI file (describes details for initializing the device) // using AIS ROM functions and possibly AISExtras functions) INISection[] iniSecs = AISGen.iniParse(devAISGen.devINIFileName); // Get data from the GENERAL INI Section for (UInt32 i = 0; i < iniSecs.Length; i++) { INISection sec = iniSecs[i]; if (sec.iniSectionName.Equals("GENERAL", StringComparison.OrdinalIgnoreCase)) { foreach (DictionaryEntry de in sec.sectionValues) { // Read AEMIF buswidth if (((String)de.Key).Equals("BUSWIDTH")) busWidth = (UInt32)sec.sectionValues["BUSWIDTH"]; // Read BootMode (unless already set) if ((((String)de.Key).Equals("BOOTMODE")) && (devAISGen.bootMode == BootModes.NONE)) devAISGen.bootMode = (BootModes) Enum.Parse(typeof(BootModes), (String)sec.sectionValues["BOOTMODE"], true); } } } // Check to make sure some bootmode has been set, if not make a default if (devAISGen.bootMode == BootModes.NONE) { devAISGen.bootMode = BootModes.EMIFA; } Console.WriteLine("AIS file being generated for the {0} bootmode.",Enum.GetName(typeof(BootModes),devAISGen.bootMode)); #endregion #region AIS Extras and UARTSendDONE Setup //Create the COFF file object for the AISExtras file (if it exists/is defined) if (devAISGen.AISExtraFileName != null) { EmbeddedFileIO.ExtractFile(Assembly.GetExecutingAssembly(), devAISGen.AISExtraFileName, false); if (File.Exists(devAISGen.AISExtraFileName)) { // The file exists, so use it AISExtrasCF = new COFFFile(devAISGen.AISExtraFileName); } else { throw new FileNotFoundException("The AISExtra file, " + devAISGen.AISExtraFileName + ", was not found."); } } // If we have the AISExtras COFF file object, use it to setup the addresses // for the AISExtra functions. These will utilize the L1P and L1D spaces that // are usually cache. if (AISExtrasCF != null) { // Use symbols to get address for AISExtra functions and parameters for (Int32 i = 0; i < devAISGen.AISExtraFunc.Length; i++) { Hashtable sym = AISExtrasCF.symFind("_" + devAISGen.AISExtraFunc[i].funcName); devAISGen.AISExtraFunc[i].funcAddr = (UInt32)sym["value"]; sym = AISExtrasCF.symFind(".params"); devAISGen.AISExtraFunc[i].paramAddr = (UInt32)sym["value"]; } // If the bootMode is UART we need the UARTSendDONE function if (devAISGen.bootMode == BootModes.UART) { // Set address for the UARTSendDone Function in the .text:uart section UARTSendDONE_TextSection = AISExtrasCF.secFind(".text:uart"); UARTSendDONE_DataSection = AISExtrasCF.secFind(".data:uart"); // Eliminate these as loadable since they will be loaded first, separate // from the main COFF file UARTSendDONE_TextSection["copyToTarget"] = false; UARTSendDONE_DataSection["copyToTarget"] = false; AISExtrasCF.Header["numTargetSections"] = ((UInt32)AISExtrasCF.Header["numTargetSections"] - (UInt32)2); // Set the actual run address for the UARTSendDONE function if ((UARTSendDONE_TextSection != null) && (UARTSendDONE_DataSection != null)) { Debug.DebugMSG("UART section found"); devAISGen.UARTSendDONEAddr = (UInt32)UARTSendDONE_TextSection["phyAddr"]; Hashtable sym = AISExtrasCF.symFind("_UARTSendDONE"); if (sym != null) { devAISGen.UARTSendDONEAddr = (UInt32)sym["value"]; Debug.DebugMSG("UARTSendDONE at 0x{0:X8}",devAISGen.UARTSendDONEAddr); } } else { Console.WriteLine("UARTSendDONE function not found in AISExtra COFF file!!!"); return null; } } } // Setup boolean indicating whether to include UARTSendDONE jump commands if ((devAISGen.bootMode == BootModes.UART) && (devAISGen.UARTSendDONEAddr != 0x0)) devAISGen.SendUARTSendDONE = true; else devAISGen.SendUARTSendDONE = false; #endregion #region Write AIS MAGIC Number and initial data // Write the premilinary header and fields (everything before first AIS command) switch (devAISGen.bootMode) { case BootModes.EMIFA: { if (busWidth == 16) tempAIS_bw.Write((UInt32)1); else tempAIS_bw.Write((UInt32)0); tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } case BootModes.NAND: { tempAIS_bw.Write((UInt32)AIS.MagicNumber); tempAIS_bw.Write((UInt32)0); tempAIS_bw.Write((UInt32)0); tempAIS_bw.Write((UInt32)0); break; } case BootModes.UART: { tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } }; #endregion #region Send UARTSendDONE sections //Send UART code if it exists if (devAISGen.SendUARTSendDONE) { CRCCheckType tempCRCType = devAISGen.crcType; devAISGen.crcType = CRCCheckType.NO_CRC; devAISGen.SendUARTSendDONE = false; AISSectionLoad(AISExtrasCF, UARTSendDONE_TextSection, devAISGen); AISSectionLoad(AISExtrasCF, UARTSendDONE_DataSection, devAISGen); devAISGen.SendUARTSendDONE = true; devAISGen.crcType = tempCRCType; } #endregion #region ROM Function insertion // Insert words for ROM function execution for (UInt32 i = 0; i < devAISGen.ROMFunc.Length; i++) { for (UInt32 j = 0; j < iniSecs.Length; j++) { if (iniSecs[j].iniSectionName.Equals(devAISGen.ROMFunc[i].iniSectionName)) { UInt32 funcIndex = i; tempAIS_bw.Write((UInt32)AIS.FunctionExec); tempAIS_bw.Write((((UInt32)devAISGen.ROMFunc[i].numParams) << 16) + ((UInt32)funcIndex)); // Write Paramter values read from INI file for (Int32 k = 0; k < devAISGen.ROMFunc[i].numParams; k++) { tempAIS_bw.Write((UInt32)iniSecs[j].sectionValues[devAISGen.ROMFunc[i].paramNames[k].ToString()]); Debug.DebugMSG(((UInt32)iniSecs[j].sectionValues[devAISGen.ROMFunc[i].paramNames[k].ToString()]).ToString()); } // Call UARTSendDONE from AIS Extras if this is for UART boot if (devAISGen.SendUARTSendDONE) { tempAIS_bw.Write((UInt32)AIS.Jump); tempAIS_bw.Write(devAISGen.UARTSendDONEAddr); } } } } #endregion #region AIS executable data download if (AISExtrasCF != null) { // Load the AISExtras COFF file AISCOFFLoad(AISExtrasCF, devAISGen); } #endregion #region AIS Extras init function execution //Insert calls for any AISExtra Init functions (like power domains) if (AISExtrasCF != null) { for (UInt32 i = 0; i < devAISGen.AISExtraFunc.Length; i++) { if (devAISGen.AISExtraFunc[i].isInitFunc) { for (UInt32 j = 0; j < iniSecs.Length; j++) { if (iniSecs[j].iniSectionName.Equals(devAISGen.AISExtraFunc[i].iniSectionName)) { for (UInt32 k = 0; k < devAISGen.AISExtraFunc[i].numParams; k++) { // Write SET command tempAIS_bw.Write((UInt32)AIS.Set); //Write type field (32-bit only) tempAIS_bw.Write((UInt32)0x3); // Write appropriate parameter address tempAIS_bw.Write((UInt32) (devAISGen.AISExtraFunc[i].paramAddr + (k * 4))); //Write data to write tempAIS_bw.Write((UInt32)iniSecs[j].sectionValues[devAISGen.AISExtraFunc[i].paramNames[k].ToString()]); //Write Sleep value (should always be zero) //tempAIS_bw.Write((UInt32)0x1000); tempAIS_bw.Write((UInt32)0x0); } // Now that params are set, Jump to function tempAIS_bw.Write((UInt32)AIS.Jump); tempAIS_bw.Write(devAISGen.AISExtraFunc[i].funcAddr); // Call UARTSendDONE from AIS Extras if this is for UART boot if (devAISGen.SendUARTSendDONE) { tempAIS_bw.Write((UInt32)AIS.Jump); tempAIS_bw.Write(devAISGen.UARTSendDONEAddr); } } } } } } #endregion #region Application COFF file creation and loading // Create the COFF file object for the main application being loaded if (File.Exists(coffFileName)) { // The file exists, so use it cf = new COFFFile(coffFileName); Debug.DebugMSG("FileName {0} found.", coffFileName); } else { Debug.DebugMSG("FileName {0} NOT found.", coffFileName); throw new FileNotFoundException("AISGen: COFF file, " + coffFileName + ", not found."); } if (cf != null) { // Load the AISExtras COFF file AISCOFFLoad(cf, devAISGen); } #endregion #region Insert Final JUMP_CLOSE command tempAIS_bw.Write((UInt32)AIS.Jump_Close); tempAIS_bw.Write((UInt32)cf.Header["optEntryPoint"]); numTargetSections = (UInt32)cf.Header["numTargetSections"]; if (AISExtrasCF != null) { numTargetSections += (UInt32)AISExtrasCF.Header["numTargetSections"]; } tempAIS_bw.Write((UInt32)numTargetSections); //tempAIS_bw.Write((UInt32)0x0); //tempAIS_bw.Write((UInt32)totalLoadableSize); tempAIS_bw.Write((UInt32)0x0); // Flush the data to the file and then return to start devAISGen.devAISFileStream.Close(); #endregion #endregion #region Prepare the return byte array // Now create return Byte array based on tempAIS file and the bootmode EndianBinaryReader tempAIS_br; tempAIS_br = new EndianBinaryReader( new FileStream(devAISGen.devAISFileName, FileMode.Open, FileAccess.Read), Endian.LittleEndian); ASCIIEncoding enc = new ASCIIEncoding(); // Setup the binary reader object if (devAISGen.bootMode == BootModes.UART) { numWords = ((UInt32)tempAIS_br.BaseStream.Length) >> 2; devAISGen.AISData = new Byte[numWords << 3]; //Each word converts to 8 ASCII bytes } else { numWords = ((UInt32)tempAIS_br.BaseStream.Length) >> 2; devAISGen.AISData = new Byte[numWords << 2]; //Each word converts to 4 binary bytes } Debug.DebugMSG("Number of words in the stream is {0}", numWords); // Copy the data to the output Byte array for (UInt32 i = 0; i < numWords; i++) { if (devAISGen.bootMode == BootModes.UART) enc.GetBytes(tempAIS_br.ReadUInt32().ToString("X8")).CopyTo(devAISGen.AISData, i * 8); else BitConverter.GetBytes(tempAIS_br.ReadUInt32()).CopyTo(devAISGen.AISData, i * 4); } // Close the binary reader tempAIS_br.Close(); // Delete the temp AIS data file File.Delete(devAISGen.devAISFileName); // Close the COFF files since we are done with them AISExtrasCF.Close(); cf.Close(); // Clean up any embedded file resources that may have been extracted EmbeddedFileIO.CleanUpEmbeddedFiles(); #endregion // Console output Console.WriteLine("AIS file generation was successful."); // --------------------------------------------------------- // ******************* END AIS GENERATION ****************** // --------------------------------------------------------- // Return Byte Array return devAISGen.AISData; }
/* * I've been studying the NSBCA format heavily over the last few days trying to figure it out. * I've determined that the first offset in a joint animation contains Pivoting data, and the second section contains Rotation data. * Rotation keyframes are called when the second byte equals 0 and Pivot keyframes are called when it equals 128, however the data itself is definitely stored a little differently to how it is stored in NSBMD files. * Scaling keyframes hold two scaling values for whatever reason, with Translation keyframes being just straight values that can be a signed word/dword. * Each animation has a frame length, however each object in an animation seems to have a start and end position that typically don't match up with the total number of frames. * Now I haven't had much experience with model animations, but I'm guessing this might have like a decay effect on the animation if anyone has ever played around with animations in Maya? * The trickiest part is calculating the right number of keyframes stored in each object as there isn't an actual value written down anywhere. * From what I can tell it's calculated based on a bunch of things including the difference in object frame length over animation frame length, the rate in which the object (and possibly the animation) plays back as well as rounding to the upper whole number. * This looks a bit funky and overcomplicated but so far all the animations I've been working with calculate the correct number of keyframes, so I'm assuming I'm on the right track. * Am yet to get to the point of loading animations into a model, but hopefully I won't get some spastic result :S Object Flag: --zyx-Sr-RZYX-T- > found in the header of each object of an animation =========================== T - has Translation keyframes (0 Yes| 1 No) XYZ - flags for Translation attributes R - has Rotation/Pivot keyframes (0 Yes| 1 No) r - flag for Rotation/Pivot attribute S - has Scale keyframes (0 Yes| 1 No) xyz - flags for Scale attributes =========================== if T-XYZ = 1 > Fixed Translation value (signed dword) if R-r = 1 > Fixed Rotation/Pivot value (dword/2*word?) if S-xyz = 1 > Fixed Scale value (2*dword) Note: The below is only done when the bit flag equals 0 for that attribute (TX, TY, TZ, R/P, SX, SY, SZ) a|b = datasize = playback speed > a & b are flags stored in the object header for each attribute Translate ----------------------------------------------------------- 2|0 = word = 1/1 2|1 = word = 1/2 2|2 = word = 1/3 0|1 = dword = 1/2 Rotate ----------------------------------------------------------- 0|0 = 2*byte = 1/1 0|1 = 2*byte = 1/2 0|2 = 2*byte = 1/3 > byte0 = index > byte1 = 0 Rotation | 128 Pivot > not completely sure on rotation yet Scale ----------------------------------------------------------- 2|1 = 2*word = 1/1 2|1 = 2*word = 1/2 ----------------------------------------------------------- Attribute [animation flag|start|end|a|b] bytes/keyframes - animation length > bytes - the actual size of the data stored > keyframes - bytes/datasize(see above) Basabasa - 0 Pivot - 33 Rotation =========================================================== Translate [3|0|34|2|1] 38/19 - 36 Frames Rotate [3|0|34|0|1] 38/19 - 36 Frames Scale [3|0|34|2|1] 76/19 - 36 Frames =========================================================== Basabasa2 - 1 Pivot - 20 Rotation =========================================================== Rotate [3|0|78|0|1] 82/41 - 80 Frames =========================================================== Bilikyu - 31 Pivot =========================================================== Translate [3|0|58|2|1] 62/31 - 60 Frames Rotate [3|0|58|0|1] 62/31 - 60 Frames =========================================================== Donketu - 12 Pivot / 20 Rotation =========================================================== Translate [3|0|10|0|1] 24/06 - 11 Frames (dword) Translate [3|0|10|2|1] 12/06 - 11 Frames Translate [1|0|02|2|0] 04/02 - 02 Frames Rotate [3|0|10|0|1] 14/07 - 11 Frames =========================================================== Gesso - 39 Pivot =========================================================== Translate [0|0|16|2|2] 14/07 - 19 Frames Translate [0|0|16|2|2] 12/06 - 18 Frames Translate [0|0|12|2|2] 10/05 - 14 Frames Scale [0|0|16|2|2] 28/07 - 19 Frames Scale [0|0|16|2|2] 24/06 - 18 Frames Rotate [0|0|16|0|2] 16/08 - 19 Frames Rotate [0|0|16|0|2] 16/08 - 18 Frames Rotate [0|0|12|0|2] 14/07 - 14 Frames =========================================================== TTL Bird =========================================================== Translate [1|0|05|2|0] 10/05 - 05 Frames Rotate [1|0|05|0|0] 10/05 - 05 Frames =========================================================== Gamaguchi - 11 Pivot - 52 Rotation =========================================================== Translate [3|0|08|2|0] 16/08 - 08 Frames Translate [3|0|07|2|0] 14/07 - 07 Frames Translate [3|0|16|2|0] 32/16 - 16 Frames Rotate [3|0|08|0|0] 16/08 - 08 Frames Rotate [1|0|07|0|0] 14/07 - 07 Frames Rotate [3|0|16|0|0] 32/16 - 16 Frames Scale [3|0|08|2|0] 32/08 - 08 Frames Scale [1|0|07|2|0] 28/07 - 07 Frames =========================================================== */ public static NSBCA_File Read(string Filename) { byte[] file_ = File.ReadAllBytes(Filename); if (file_[0] == 76 && file_[1] == 90 && file_[2] == 55 && file_[3] == 55) { } EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(file_), Endianness.LittleEndian); NSBCA_File ns = new NSBCA_File(); ns.Header.ID = er.ReadString(Encoding.ASCII, 4); if (ns.Header.ID == "BCA0") { ns.Header.Magic = er.ReadBytes(4); ns.Header.file_size = er.ReadInt32(); ns.Header.header_size = er.ReadInt16(); ns.Header.nSection = er.ReadInt16(); ns.Header.Section_Offset = new Int32[ns.Header.nSection]; for (int i = 0; i < ns.Header.nSection; i++) { ns.Header.Section_Offset[i] = er.ReadInt32(); } ns.JNT0.ID = er.ReadString(Encoding.ASCII, 4); if (ns.JNT0.ID == "JNT0") { ns.JNT0.Size = er.ReadInt32(); //3D Info Structure ns.JNT0.dummy = er.ReadByte(); ns.JNT0.num_objs = er.ReadByte(); ns.JNT0.section_size = er.ReadInt16(); ns.JNT0.unknownBlock.header_size = er.ReadInt16(); ns.JNT0.unknownBlock.section_size = er.ReadInt16(); ns.JNT0.unknownBlock.constant = er.ReadInt32(); ns.JNT0.unknownBlock.unknown1 = new short[ns.JNT0.num_objs]; ns.JNT0.unknownBlock.unknown2 = new short[ns.JNT0.num_objs]; for (int i = 0; i < ns.JNT0.num_objs; i++) { ns.JNT0.unknownBlock.unknown1[i] = er.ReadInt16(); ns.JNT0.unknownBlock.unknown2[i] = er.ReadInt16(); } ns.JNT0.infoBlock.header_size = er.ReadInt16(); ns.JNT0.infoBlock.data_size = er.ReadInt16(); ns.JNT0.infoBlock.Data = new NSBCA_File.jnt0.Info.info[ns.JNT0.num_objs]; for (int i = 0; i < ns.JNT0.num_objs; i++) { ns.JNT0.infoBlock.Data[i].Objectoffset = er.ReadInt32(); } ns.JNT0.names = new string[ns.JNT0.num_objs]; for (int i = 0; i < ns.JNT0.num_objs; i++) { ns.JNT0.names[i] = er.ReadString(Encoding.ASCII, 16).Replace("\0", ""); } ns.JAC = new NSBCA_File.J_AC[ns.JNT0.num_objs]; for (int i = 0; i < ns.JNT0.num_objs; i++) { er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.JNT0.infoBlock.Data[i].Objectoffset; ns.JAC[i].ID = er.ReadString(Encoding.ASCII, 4); if (ns.JAC[i].ID == "J" + (char)0x00 + "AC") { ns.JAC[i].NrFrames = er.ReadInt16(); ns.JAC[i].NrObjects = er.ReadInt16(); ns.JAC[i].Unknown1 = er.ReadInt32(); ns.JAC[i].Offset1 = er.ReadInt32(); ns.JAC[i].Offset2 = er.ReadInt32(); long curposs = er.BaseStream.Position; if (ns.JAC[i].Offset2 != ns.JAC[i].Offset1) { er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.JNT0.infoBlock.Data[i].Objectoffset + ns.JAC[i].Offset1; ns.JAC[i].JointData = er.ReadBytes(ns.JAC[i].Offset2 - ns.JAC[i].Offset1); er.BaseStream.Position = curposs; } long dataoffset = 0; ns.JAC[i].ObjInfoOffset = new Int32[ns.JAC[i].NrObjects]; for (int j = 0; j < ns.JAC[i].NrObjects; j++) { ns.JAC[i].ObjInfoOffset[j] = er.ReadInt16(); } ns.JAC[i].ObjInfo = new NSBCA_File.J_AC.objInfo[ns.JAC[i].NrObjects]; for (int j = 0; j < ns.JAC[i].NrObjects; j++) { er.BaseStream.Position = ns.Header.Section_Offset[0] +/* ns.JNT0.section_size*/ns.JNT0.infoBlock.Data[i].Objectoffset + ns.JAC[i].ObjInfoOffset[j];// + 8; ns.JAC[i].ObjInfo[j].Flag = er.ReadInt16(); ns.JAC[i].ObjInfo[j].Unknown1 = er.ReadByte(); ns.JAC[i].ObjInfo[j].ID = er.ReadByte(); ns.JAC[i].ObjInfo[j].translate = new List<float>[3]; ns.JAC[i].ObjInfo[j].translate[0] = new List<float>(); ns.JAC[i].ObjInfo[j].translate[1] = new List<float>(); ns.JAC[i].ObjInfo[j].translate[2] = new List<float>(); ns.JAC[i].ObjInfo[j].translate_keyframes = new List<float>[3]; ns.JAC[i].ObjInfo[j].translate_keyframes[0] = new List<float>(); ns.JAC[i].ObjInfo[j].translate_keyframes[1] = new List<float>(); ns.JAC[i].ObjInfo[j].translate_keyframes[2] = new List<float>(); ns.JAC[i].ObjInfo[j].rotate = new List<float>(); ns.JAC[i].ObjInfo[j].rotate_keyframes = new List<float>[2]; ns.JAC[i].ObjInfo[j].rotate_keyframes[0] = new List<float>(); ns.JAC[i].ObjInfo[j].rotate_keyframes[1] = new List<float>(); ns.JAC[i].ObjInfo[j].scale = new List<float>[3][]; ns.JAC[i].ObjInfo[j].scale[0] = new List<float>[2]; ns.JAC[i].ObjInfo[j].scale[1] = new List<float>[2]; ns.JAC[i].ObjInfo[j].scale[2] = new List<float>[2]; ns.JAC[i].ObjInfo[j].scale[0][0] = new List<float>(); ns.JAC[i].ObjInfo[j].scale[0][1] = new List<float>(); ns.JAC[i].ObjInfo[j].scale[1][0] = new List<float>(); ns.JAC[i].ObjInfo[j].scale[1][1] = new List<float>(); ns.JAC[i].ObjInfo[j].scale[2][0] = new List<float>(); ns.JAC[i].ObjInfo[j].scale[2][1] = new List<float>(); ns.JAC[i].ObjInfo[j].scale_keyframes = new List<float>[3][]; ns.JAC[i].ObjInfo[j].scale_keyframes[0] = new List<float>[2]; ns.JAC[i].ObjInfo[j].scale_keyframes[1] = new List<float>[2]; ns.JAC[i].ObjInfo[j].scale_keyframes[2] = new List<float>[2]; ns.JAC[i].ObjInfo[j].scale_keyframes[0][0] = new List<float>(); ns.JAC[i].ObjInfo[j].scale_keyframes[0][1] = new List<float>(); ns.JAC[i].ObjInfo[j].scale_keyframes[1][0] = new List<float>(); ns.JAC[i].ObjInfo[j].scale_keyframes[1][1] = new List<float>(); ns.JAC[i].ObjInfo[j].scale_keyframes[2][0] = new List<float>(); ns.JAC[i].ObjInfo[j].scale_keyframes[2][1] = new List<float>(); double[] speed = { 1.0D, 0.5D, 0.33333333333333331D }; if (((ns.JAC[i].ObjInfo[j].Flag >> 1) & 1) == 0) { //struct.DModelAnimation.MTransformAni trans[] = new struct.DModelAnimation.MTransformAni[3]; //string msg = new StringBuilder().Append(msg).Append("\n -> Translate: ").ToString(); //string[] type = { "X", "Y", "Z" }; for (int k = 0; k < 3; k++) { //trans[k] = new struct.DModelAnimation.MTransformAni(this); int tflag = ns.JAC[i].ObjInfo[j].Flag >> 3 + k & 1; //msg = new StringBuilder().Append(msg).Append("\n -> T").Append(type[k]).Append(tflag).Append("[").ToString(); if (tflag == 1) { int tvar = er.ReadInt32(); //trans[k].setFrame((float)tvar / divide); ns.JAC[i].ObjInfo[j].translate[k].Add((float)tvar / 4096f); //msg = (new StringBuilder()).Append(msg).Append(tvar).ToString(); continue; } else { int param2 = er.ReadInt32(); int startFrame = param2 & 0xffff; ns.JAC[i].ObjInfo[j].tStart = startFrame; int endFrame = param2 >> 16 & 0xfff; ns.JAC[i].ObjInfo[j].tEnd = endFrame; int var2 = param2 >> 28 & 3; int speedId = param2 >> 30 & 3; int toffset = er.ReadInt32(); int width = var2 != 0 ? 2 : 4; int extra = (ns.JAC[i].Unknown1 != 3 ? 0 : ns.JAC[i].NrFrames - endFrame); int length = (int)Math.Ceiling((double)(ns.JAC[i].NrFrames + extra) * speed[speedId]); long curpos = er.BaseStream.Position; for (int t = 0; t < length; t++) { er.BaseStream.Position = ns.Header.Section_Offset[0] +/* ns.JNT0.section_size*/ns.JNT0.infoBlock.Data[i].Objectoffset + toffset + (t * width); if (dataoffset == 0) { dataoffset = toffset; } float keyFrame = (width != 2 ? (float)er.ReadInt32() : (float)er.ReadInt16()); ns.JAC[i].ObjInfo[j].translate_keyframes[k].Add((float)LibNDSFormats.NSBMD.NsbmdGlRenderer.sign((int)keyFrame, (width != 2 ? 32 : 16)) / 4096f); //m = (new StringBuilder()).append(m).append("\n -> #").append(t).append(": ").append(keyFrame).toString(); } er.BaseStream.Position = curpos; } } } if (((ns.JAC[i].ObjInfo[j].Flag >> 6) & 1) == 0) { int rflag = ns.JAC[i].ObjInfo[j].Flag >> 8 & 1; if (rflag == 1) { //dataParser _tmp14 = pa; int rvar = er.ReadInt32(); //dataParser.getInt(data, jump, 4); ns.JAC[i].ObjInfo[j].rotate.Add((float)rvar); //msg = (new StringBuilder()).append(msg).append(rvar).toString(); //jump += 4; } else { int param2 = er.ReadInt32(); int startFrame = param2 & 0xffff; ns.JAC[i].ObjInfo[j].rStart = startFrame; int endFrame = param2 >> 16 & 0xfff; ns.JAC[i].ObjInfo[j].rEnd = endFrame; int var2 = param2 >> 28 & 3; int speedId = param2 >> 30 & 3; int roffset = er.ReadInt32(); int width = 2;//var2 != 0 ? 2 : 4; int length = (int)Math.Ceiling((double)(ns.JAC[i].NrFrames) * speed[speedId]); long curpos = er.BaseStream.Position; for (int r = 0; r < length; r++) { er.BaseStream.Position = ns.Header.Section_Offset[0] +/* ns.JNT0.section_size*/ns.JNT0.infoBlock.Data[i].Objectoffset + roffset + (r * width); if (dataoffset == 0) { dataoffset = roffset; } int rvar6 = er.ReadInt16(); int rindex = rvar6 & 0x7fff; int mode = rvar6 >> 15 & 1; ns.JAC[i].ObjInfo[j].rotate_keyframes[0].Add(rindex); ns.JAC[i].ObjInfo[j].rotate_keyframes[1].Add(mode); } er.BaseStream.Position = curpos; } } if ((ns.JAC[i].ObjInfo[j].Flag >> 9 & 1) == 0) { //struct.DModelAnimation.MScaleAni scale[] = new struct.DModelAnimation.MScaleAni[3]; //msg = (new StringBuilder()).append(msg).append("\n -> Scale: ").toString(); for (int k = 0; k < 3; k++) { //scale[k] = new struct.DModelAnimation.MScaleAni(this); int sflag = ns.JAC[i].ObjInfo[j].Flag >> 11 + k & 1; //msg = (new StringBuilder()).append(msg).append("\n -> S").append(type[k]).append(sflag).append("[").toString(); if (sflag == 1) { //dataParser _tmp19 = pa; int svar1 = er.ReadInt32();//dataParser.getInt(data, jump, 4); ns.JAC[i].ObjInfo[j].scale[k][0].Add((float)svar1 / 4096f); //dataParser _tmp20 = pa; int svar2 = er.ReadInt32();//dataParser.getSign(data, jump + 4, 4); ns.JAC[i].ObjInfo[j].scale[k][1].Add((float)svar2 / 4096f); //int svar3 = er.ReadInt32();//dataParser.getSign(data, jump + 4, 4); //int svar4 = er.ReadInt32();//dataParser.getSign(data, jump + 4, 4); //ns.JAC[i].ObjInfo[j].scale[k][1].Add((float)svar2 / 4096f); //scale[k].setFrame(new float[] { // (float)svar1 / divide, (float)svar2 / divide //}); //msg = (new StringBuilder()).append(msg).append(svar1).append("|").append(svar2).toString(); //jump += 8; continue; } else { int param2 = er.ReadInt32(); int startFrame = param2 & 0xffff; ns.JAC[i].ObjInfo[j].sStart = startFrame; int endFrame = param2 >> 16 & 0xfff; ns.JAC[i].ObjInfo[j].sEnd = endFrame; int var2 = param2 >> 28 & 3; int speedId = param2 >> 30 & 3; int soffset = er.ReadInt32(); int width = var2 != 0 ? 2 : 4; int length = (int)Math.Ceiling((double)(ns.JAC[i].NrFrames) * speed[speedId]); long curpos = er.BaseStream.Position; for (int s = 0; s < length; s++) { er.BaseStream.Position = ns.Header.Section_Offset[0] +/* ns.JNT0.section_size*/ns.JNT0.infoBlock.Data[i].Objectoffset + soffset + (s * width * 2); if (dataoffset == 0) { dataoffset = soffset; } ns.JAC[i].ObjInfo[j].scale_keyframes[k][0].Add((float)(width != 2 ? (float)er.ReadInt32() : (float)er.ReadInt16()) / 4096f); ns.JAC[i].ObjInfo[j].scale_keyframes[k][1].Add((float)(width != 2 ? (float)er.ReadInt32() : (float)er.ReadInt16()) / 4096f); } er.BaseStream.Position = curpos; } } } } if (dataoffset != 0) { curposs = er.BaseStream.Position; er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.JNT0.infoBlock.Data[i].Objectoffset + ns.JAC[i].Offset2; ns.JAC[i].RotationData = er.ReadBytes((int)dataoffset - ns.JAC[i].Offset2); er.BaseStream.Position = curposs; } } else { //MessageBox.Show("Error"); er.Close(); return ns; } } } else { //MessageBox.Show("Error"); er.Close(); return ns; } } else { //MessageBox.Show("Error"); er.Close(); return ns; } er.Close(); return ns; }
private void SaveFiles() { if (saveFileDialog1.ShowDialog() == DialogResult.OK) { string savePath = saveFileDialog1.FileName; FileStream originalArc = new FileStream(ArcFilePath, FileMode.Open); EndianBinaryReader reader = new EndianBinaryReader(originalArc, GameFormatReader.Common.Endian.Big); List<byte> testList = reader.ReadBytes((int)reader.BaseStream.Length).ToList(); reader.Close(); List<Message> exportList = new List<Message>(); foreach (Message mes in MessageList) { mes.ProofReadTagstoCodes(); Message temp = mes.Copy(); exportList.Add(temp); } byte[] newBMGFile = TextBankClass.ExportBMGFromPath(exportList); testList.RemoveRange(1344, testList.Count - 1344); testList.AddRange(newBMGFile); byte[] newBMCFile = ColorClass.BMCExporter(ColorList); testList.RemoveRange(256, newBMCFile.Length); testList.InsertRange(256, newBMCFile); FileStream testStream = new FileStream(savePath, FileMode.Create); EndianBinaryWriter writer = new EndianBinaryWriter(testStream, Endian.Big); writer.Write(testList.ToArray()); writer.BaseStream.Position = 128; writer.Write((int)newBMGFile.Length); writer.BaseStream.Position = 4; writer.Write((int)testList.Count); writer.Flush(); writer.Close(); } }
/// <summary> /// SecureGenAIS command. /// </summary> /// <param name="coffFileName">File name of input .out file</param> /// <param name="bootMode">AISGen Object for the particular device</param> /// <returns>Bytes of the binary or AIS boot image</returns> public static Byte[] SecureGenAIS(String coffFileName, AISGen devAISGen, INISection[] iniSecs) { UInt32 busWidth = 8; UInt32 addrWidth = 16; UInt32 numTargetSections = 0; UInt32 numWords; UInt32 entryPoint = 0x00000000; Boolean seqReadEn = false; // Not supported on all devices Byte[] secureKeyData = null; String currHashAlgorithmString = "SHA1"; // Default hash algorithm Hashtable UARTSendDONE_DataSection=null, UARTSendDONE_TextSection=null; // Hash tables to keep track of the input object and binary files List<SecureObjectFile> objectFiles = new List<SecureObjectFile>(); List<SecureBinaryFile> binaryFiles = new List<SecureBinaryFile>(); // COFF file objects for the main application and the AIS extras executable COFFFile AISExtrasCF=null; // Set defaults devAISGen.secureType = SecureType.NONE; devAISGen.bootLoaderExitType = BootLoaderExitType.NONE; devAISGen.currHashAlgorithmValue = SHA_Algorithm.SHA1; devAISGen.finalFxnName = null; devAISGen.sectionsToEncrypt = null; devAISGen.rsaObject = null; devAISGen.customerEncryptionKey = null; devAISGen.keyEncryptionKey = null; devAISGen.genericKeyHeaderData = null; devAISGen.currHashAlgorithm = null; devAISGen.signatureByteCnt = 0; devAISGen.signatureCnt = 0; // List to keep track of loadable sections and their occupied memory ranges devAISGen.sectionMemory = new List<MemoryRange>(); // Setup the binary writer to generate the temp AIS file devAISGen.devAISStream = new MemoryStream(); EndianBinaryWriter tempAIS_bw = new EndianBinaryWriter( devAISGen.devAISStream, devAISGen.devEndian); // Setup the binary writer to store data for signing devAISGen.signatureStream = new MemoryStream(); EndianBinaryWriter sig_bw = new EndianBinaryWriter( devAISGen.signatureStream, devAISGen.devEndian); #region INI Data parsing // Get data from the GENERAL INI Section for (UInt32 i = 0; i < iniSecs.Length; i++) { INISection sec = iniSecs[i]; if (sec.iniSectionName.Equals("GENERAL", StringComparison.OrdinalIgnoreCase)) { foreach (DictionaryEntry de in sec.sectionValues) { // Read buswidth if (((String)de.Key).Equals("BUSWIDTH", StringComparison.OrdinalIgnoreCase)) busWidth = (UInt32)sec.sectionValues["BUSWIDTH"]; // Read BootMode (unless already set) if ((((String)de.Key).Equals("BOOTMODE", StringComparison.OrdinalIgnoreCase)) && (devAISGen.bootMode == BootModes.NONE)) devAISGen.bootMode = (BootModes) Enum.Parse(typeof(BootModes), (String)sec.sectionValues["BOOTMODE"], true); // Read Addr width (for I2C/SPI) if (((String)de.Key).Equals("ADDRWIDTH", StringComparison.OrdinalIgnoreCase)) addrWidth = (UInt32)sec.sectionValues["ADDRWIDTH"]; // Sequential Read ENABLE if (((String)de.Key).Equals("SEQREADEN", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["SEQREADEN"]).Equals("ON", StringComparison.OrdinalIgnoreCase)) seqReadEn = true; if (((String)sec.sectionValues["SEQREADEN"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) seqReadEn = true; } // Finalize fxn symbol name if (((String)de.Key).Equals("FINALFXNSYMBOLNAME", StringComparison.OrdinalIgnoreCase)) { devAISGen.finalFxnName = (String)sec.sectionValues["FINALFXNSYMBOLNAME"]; } // Read entrypoint value if (((String)de.Key).Equals("ENTRYPOINT", StringComparison.OrdinalIgnoreCase)) entryPoint = (UInt32)sec.sectionValues["ENTRYPOINT"]; } } if (sec.iniSectionName.Equals("SECURITY", StringComparison.OrdinalIgnoreCase)) { foreach (DictionaryEntry de in sec.sectionValues) { // Security Type if (((String)de.Key).Equals("SECURITYTYPE", StringComparison.OrdinalIgnoreCase)) { devAISGen.secureType = (SecureType) Enum.Parse(typeof(SecureType), (String)sec.sectionValues["SECURITYTYPE"], true); } // Boot exit type if (((String)de.Key).Equals("BOOTEXITTYPE", StringComparison.OrdinalIgnoreCase)) { devAISGen.bootLoaderExitType = (BootLoaderExitType) Enum.Parse(typeof(BootLoaderExitType), (String)sec.sectionValues["BOOTEXITTYPE"], true); } // Encrypted section settings if (((String)de.Key).Equals("ENCRYPTSECTIONS", StringComparison.OrdinalIgnoreCase)) { Char[] separators = new Char[]{','}; String encryptSections = (String)sec.sectionValues["ENCRYPTSECTIONS"]; devAISGen.sectionsToEncrypt = encryptSections.Split(separators,StringSplitOptions.RemoveEmptyEntries); for( int k = 0; k<devAISGen.sectionsToEncrypt.Length; k++) { devAISGen.sectionsToEncrypt[k] = devAISGen.sectionsToEncrypt[k].Trim(); } } // AES Encryption Key (CEK) if (((String)de.Key).Equals("ENCRYPTIONKEY", StringComparison.OrdinalIgnoreCase)) { devAISGen.customerEncryptionKey = new Byte[16]; devAISGen.CEKInitialValue = new Byte[16]; String keyString = (String)sec.sectionValues["ENCRYPTIONKEY"]; if (keyString.Length != 32) { Console.WriteLine("AES Encryption Key is wrong length!"); return null; } for (int j=0; j<keyString.Length; j+=2) { devAISGen.customerEncryptionKey[(j>>1)] = Convert.ToByte(keyString.Substring(j,2),16); } // Generate IV as encrypted version of AES Key using (MemoryStream ms = new MemoryStream(devAISGen.CEKInitialValue)) { Aes myAES = new AesManaged(); myAES.KeySize = 128; myAES.Mode = CipherMode.ECB; myAES.Padding = PaddingMode.None; ICryptoTransform encryptor = myAES.CreateEncryptor(devAISGen.customerEncryptionKey, new Byte[16]); CryptoStream cs = new CryptoStream(ms,encryptor,CryptoStreamMode.Write); cs.Write(devAISGen.customerEncryptionKey,0,devAISGen.customerEncryptionKey.Length); } FileIO.SetFileData("cek.bin",devAISGen.customerEncryptionKey,true); FileIO.SetFileText("FROM_cek.init",KeyToBinaryString(devAISGen.customerEncryptionKey,0xA,true,true),true); FileIO.SetFileData("cek_cbc_iv.bin",devAISGen.CEKInitialValue,true); } // Key Encryption Key (not normally known, here for debug/testing purposes) if (((String)de.Key).Equals("KEYENCRYPTIONKEY", StringComparison.OrdinalIgnoreCase)) { devAISGen.keyEncryptionKey = new Byte[16]; String keyString = (String)sec.sectionValues["KEYENCRYPTIONKEY"]; if (keyString.Length != 32) { Console.WriteLine("Key Encryption Key is wrong length!"); return null; } for (int j=0; j<keyString.Length; j+=2) { devAISGen.keyEncryptionKey[(j>>1)] = Convert.ToByte(keyString.Substring(j,2),16); } FileIO.SetFileData("kek.bin",devAISGen.keyEncryptionKey,true); FileIO.SetFileText("FROM_kek.init",KeyToBinaryString(devAISGen.keyEncryptionKey,0xE,true,true),true); } // Generic Secure Option to force JTAG off as part of the key loading if (((String)de.Key).Equals("GENERICJTAGFORCEOFF", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["GENERICJTAGFORCEOFF"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) devAISGen.genericJTAGForceOff = true; else devAISGen.genericJTAGForceOff = false; } // Generic Secure Option to select the hash algorithm for signatures if (((String)de.Key).Equals("GENERICSHASELECTION", StringComparison.OrdinalIgnoreCase)) { currHashAlgorithmString = (String)sec.sectionValues["GENERICSHASELECTION"]; devAISGen.currHashAlgorithmValue = (SHA_Algorithm) Enum.Parse(typeof(SHA_Algorithm), (String)sec.sectionValues["GENERICSHASELECTION"], true); } // Generic Key Header file if (((String)de.Key).Equals("GENKEYHEADERFILENAME", StringComparison.OrdinalIgnoreCase)) { String genKeyHeaderFileName = (String)sec.sectionValues["GENKEYHEADERFILENAME"]; devAISGen.genericKeyHeaderData = new Byte[32]; // Open file, read contents, copy to our AIS array using (FileStream tempFS = new FileStream(genKeyHeaderFileName, FileMode.Open, FileAccess.Read)) { tempFS.Read(devAISGen.genericKeyHeaderData,0,32); } } // Custom Secure RSA Key File if (((String)de.Key).Equals("RSAKEYFILENAME", StringComparison.OrdinalIgnoreCase)) { String rsaKeyFileName = (String)sec.sectionValues["RSAKEYFILENAME"]; devAISGen.rsaObject = RSAKey.LoadFromFile(rsaKeyFileName); if (devAISGen.rsaObject == null) { Console.WriteLine("RSA key loading failed!"); return null; } // Update the hash algo string if RSA key size is 2048 bits if (devAISGen.rsaObject.KeySize == 2048) { currHashAlgorithmString = "SHA256"; devAISGen.currHashAlgorithmValue = SHA_Algorithm.SHA256; } Console.WriteLine("MapNameToOid({1}) = {0}",CryptoConfig.MapNameToOID(currHashAlgorithmString),currHashAlgorithmString); } } } if (sec.iniSectionName.Equals("SECURELEGACY", StringComparison.OrdinalIgnoreCase)) { foreach (DictionaryEntry de in sec.sectionValues) { // Legacy secure option to encrypt the boot image if (((String)de.Key).Equals("ENCRYPTIMAGE", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["ENCRYPTIMAGE"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) devAISGen.secureLegacyEncryptImage = true; else devAISGen.secureLegacyEncryptImage = false; } } devAISGen.bootMode = BootModes.LEGACY; } if (sec.iniSectionName.Equals("BINARYINPUTFILE", StringComparison.OrdinalIgnoreCase)) { SecureBinaryFile currFile = new SecureBinaryFile(); currFile.fileName = null; currFile.useEntryPoint = false; currFile.loadAddr = 0x00000000; currFile.entryPointAddr = 0x00000000; currFile.encrypt = false; foreach (DictionaryEntry de in sec.sectionValues) { // File name for binary section data if (((String)de.Key).Equals("FILENAME", StringComparison.OrdinalIgnoreCase)) { currFile.fileName = (String) sec.sectionValues["FILENAME"]; } // Binary section's load address in the memory map if (((String)de.Key).Equals("LOADADDRESS", StringComparison.OrdinalIgnoreCase)) { currFile.loadAddr = (UInt32) sec.sectionValues["LOADADDRESS"]; } // Binary section's entry point address in the memory map if (((String)de.Key).Equals("ENTRYPOINTADDRESS", StringComparison.OrdinalIgnoreCase)) { currFile.entryPointAddr = (UInt32) sec.sectionValues["ENTRYPOINTADDRESS"]; } // Option to specify that this entry point should be used for AIS if (((String)de.Key).Equals("USEENTRYPOINT", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["USEENTRYPOINT"]).Equals("YES", StringComparison.OrdinalIgnoreCase)) currFile.useEntryPoint = true; if (((String)sec.sectionValues["USEENTRYPOINT"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) currFile.useEntryPoint = true; } // Option to specify that this entry point should be used for AIS if (((String)de.Key).Equals("ENCRYPT", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["ENCRYPT"]).Equals("YES", StringComparison.OrdinalIgnoreCase)) currFile.encrypt = true; if (((String)sec.sectionValues["ENCRYPT"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) currFile.encrypt = true; } } if (currFile.fileName == null) { Console.WriteLine("ERROR: File name must be provided for binary input file."); return null; } if (currFile.loadAddr == 0x00000000) { Console.WriteLine("ERROR: Valid load address must be provided for binary input file."); return null; } binaryFiles.Add(currFile); } if (sec.iniSectionName.Equals("OBJECTINPUTFILE", StringComparison.OrdinalIgnoreCase)) { SecureObjectFile currFile = new SecureObjectFile(); currFile.useEntryPoint = false; currFile.fileName = null; currFile.encrypt = false; foreach (DictionaryEntry de in sec.sectionValues) { // File name for binary section data if (((String)de.Key).Equals("FILENAME", StringComparison.OrdinalIgnoreCase)) { currFile.fileName = (String) sec.sectionValues["FILENAME"]; } // Option to specify that this entry point should be used for AIS if (((String)de.Key).Equals("USEENTRYPOINT", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["USEENTRYPOINT"]).Equals("YES", StringComparison.OrdinalIgnoreCase)) currFile.useEntryPoint = true; if (((String)sec.sectionValues["USEENTRYPOINT"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) currFile.useEntryPoint = true; } // Option to specify that this entry point should be used for AIS if (((String)de.Key).Equals("ENCRYPT", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["ENCRYPT"]).Equals("YES", StringComparison.OrdinalIgnoreCase)) currFile.encrypt = true; if (((String)sec.sectionValues["ENCRYPT"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) currFile.encrypt = true; } } if (currFile.fileName == null) { Console.WriteLine("ERROR: File name must be provided for input object file."); return null; } objectFiles.Add(currFile); } } #endregion #region INI data validation // INI Input Validation // 1) Make sure a secure type has been specified if (devAISGen.secureType == SecureType.NONE) { Console.WriteLine("ERROR: The device's security type was not specified!"); return null; } else { Console.WriteLine("Creating boot image for a {0} secure device.",devAISGen.secureType.ToString().ToLower()); // 2) Make sure we have a CEK and IV if (devAISGen.customerEncryptionKey == null) { Console.WriteLine("ERROR: No encryption key was specified!"); return null; } // 3) If custom secure, make sure we have an rsaObject and CEK if ((devAISGen.secureType == SecureType.CUSTOM) && (devAISGen.rsaObject == null)) { Console.WriteLine("ERROR: No RSA key file was specified!"); return null; } // 3b) Make sure RSA key size is supported if ((devAISGen.secureType == SecureType.CUSTOM) && (devAISGen.rsaObject != null)) { if ( (devAISGen.rsaObject.KeySize != 1024) && (devAISGen.rsaObject.KeySize != 2048) ) { Console.WriteLine("ERROR: No RSA key size is invalid!"); return null; } else { Console.WriteLine("INFO: RSA key is {0} bits.",devAISGen.rsaObject.KeySize); } } // 4) Specify Boot Exit type (if not legacy boot) if (devAISGen.bootMode != BootModes.LEGACY) { if (devAISGen.bootLoaderExitType == BootLoaderExitType.NONE) { Console.WriteLine("ERROR: No boot loader exit type was specified!"); return null; } else { Console.WriteLine("INFO: Boot exit type has been selected as {0}.",devAISGen.bootLoaderExitType); } } // 5) If generic secure, make sure we have the CEK header info (either encrypted or unencrypted) if ((devAISGen.secureType == SecureType.GENERIC) && (devAISGen.genericKeyHeaderData == null)) { Console.WriteLine("WARNING: Encrypted Key Header data is absent - generating plaintext version. "); Console.WriteLine(" The Customer Encryption Key will be transferred in plaintext! "); } // 6) Give warning if generic device and no sections are specified for encryption if (devAISGen.bootMode != BootModes.LEGACY) { if ((devAISGen.secureType == SecureType.GENERIC) && (devAISGen.sectionsToEncrypt == null)) { Console.WriteLine("WARNING: Generic Secure device was specified, but no input sections were indicated for encryption."); Console.WriteLine(" Only boot image signing will take place."); } } } // 2) Make sure valid hash algorithm was selected try { devAISGen.currHashAlgorithm = HashAlgorithm.Create(currHashAlgorithmString); Console.WriteLine("INFO: Current SHA algorithm is {0}.",devAISGen.currHashAlgorithmValue); } catch (Exception e) { Console.WriteLine("Invalid Hash Algorithm Selected. Exception message: {0}.",e.Message); return null; } #endregion #region Secure Key Structure and Data preparation if ( devAISGen.secureType == SecureType.GENERIC ) { if ((devAISGen.genericKeyHeaderData != null) && (devAISGen.genericKeyHeaderData.Length >= 32)) { // Create our own key header secureKeyData = new Byte[32]; Array.Copy(devAISGen.genericKeyHeaderData,0,secureKeyData,0,32); } else { // Create our own key header secureKeyData = new Byte[32]; // Init with Random Data (new Random()).NextBytes(secureKeyData); // Copy in the magic word for the generic key header structure BitConverter.GetBytes((UInt32)SecureLoadMagic.GENKEY_MAGIC).CopyTo(secureKeyData, 0); // Insert JTAGForceOff word BitConverter.GetBytes( (UInt32) (devAISGen.genericJTAGForceOff ? 0x00000001 : 0x00000000) ).CopyTo(secureKeyData, 4); // Inset Hash algorithm selection word (right now default to SHA-1 BitConverter.GetBytes( (UInt32)devAISGen.currHashAlgorithmValue ).CopyTo(secureKeyData, 8); // Insert key Data (at offset 16) devAISGen.customerEncryptionKey.CopyTo(secureKeyData, 16); // FIXME: For debug write the data out to file FileIO.SetFileData("gen_keyhdr_unencrypted.bin",secureKeyData,true); // FIXME: Debug to write out the encrypted CEK structure (encrypted with KEK, using KEK encrypted KEK as IV) if (devAISGen.keyEncryptionKey != null) { Byte[] iv = new Byte[16]; using (MemoryStream ms = new MemoryStream(iv)) { Aes myAES = new AesManaged(); myAES.KeySize = 128; myAES.Mode = CipherMode.ECB; myAES.Padding = PaddingMode.None; ICryptoTransform encryptor = myAES.CreateEncryptor(devAISGen.keyEncryptionKey, new Byte[16]); CryptoStream cs = new CryptoStream(ms,encryptor,CryptoStreamMode.Write); cs.Write(devAISGen.keyEncryptionKey,0,devAISGen.keyEncryptionKey.Length); } Byte[] encSecureKeyData = new Byte[32]; using (MemoryStream ms = new MemoryStream(encSecureKeyData)) { Aes myAES = new AesManaged(); myAES.KeySize = 128; myAES.Mode = CipherMode.CBC; myAES.Padding = PaddingMode.None; ICryptoTransform encryptor = myAES.CreateEncryptor(devAISGen.keyEncryptionKey, iv); CryptoStream cs = new CryptoStream(ms,encryptor,CryptoStreamMode.Write); cs.Write(secureKeyData,0,secureKeyData.Length); } // FIXME: For debug write the data out to file FileIO.SetFileData("gen_keyhdr_encrypted.bin",encSecureKeyData,true); } } } else if ( devAISGen.secureType == SecureType.CUSTOM ) { // Create RPK Verify Struct secureKeyData = RSAKey.CreateCustomSecureKeyVerifyStruct(devAISGen.rsaObject); FileIO.SetFileData("rpk_struct.bin",secureKeyData,true); // Calculate the SHA hash of the Root Public Key Byte[] digest = devAISGen.currHashAlgorithm.ComputeHash(secureKeyData); #if (!OLD_MPK_METHOD) for (int i=16;i<digest.Length;i++) { digest[i-16] ^= digest[i]; } #endif // Write the expected MPK (hash of RPK structure truncated to 128 bits) in binary format to file mpk.bin Byte[] mpk = new Byte[16]; Array.Copy(digest,0,mpk,0,16); FileIO.SetFileData("mpk.bin",mpk,true); FileIO.SetFileText("FROM_mpk.init",KeyToBinaryString(mpk,0x12,false,true),true); } #endregion #region Handle the case of Legacy boot mode if (devAISGen.bootMode == BootModes.LEGACY) { UInt32 fileSize = 0, secureDataSize = 0, totalImgSize = 0, paddingSize = 0; UInt32 loadAddr = 0; Byte[] fileData; // Validate an input binary file was given in the INI file if (binaryFiles.Count == 0) { Console.WriteLine("ERROR: You did not supply a binary file section in the INI file!"); return null; } if (binaryFiles.Count > 1) { Console.WriteLine("WARNING: You supplied too many biinary file sections in the INI file."); Console.WriteLine(" Only using the first one."); } // Set load addr to start of L2 for legacy boot mode loadAddr = devAISGen.Cache[0].startAddr + 0x10; // Figure out the size of the secure data region (signature + keystruct) if (devAISGen.secureType == SecureType.CUSTOM) { // On custom secure we have rsa keySize bits for signature and modulus of key struct, // plus eight additional bytes from key struct secureDataSize = (UInt32) (8 + (devAISGen.rsaObject.KeySize >> 3) + (devAISGen.rsaObject.KeySize >> 3)); } else if (devAISGen.secureType == SecureType.GENERIC) { // On generic secure we have 32 for key and HashSize bits rounded up to nearst 16 bytes // for signature data. secureDataSize = (UInt32) (32 + ((((devAISGen.currHashAlgorithm.HashSize >> 3)+15)>>4)<<4)); } // Verify legacy input binary file exists, and get data if it does if (File.Exists(binaryFiles[0].fileName)) { Byte[] tempFileData = FileIO.GetFileData(binaryFiles[0].fileName); fileSize = (UInt32) tempFileData.Length; totalImgSize = 16 + fileSize + secureDataSize; if (totalImgSize > 16*1024) { Console.WriteLine("The input image is too large. Reduce its size by {0} bytes.", (totalImgSize - (16*1024))); return null; } // Figure out how much to pad input file region to acheive complete image ending on 1K boundary paddingSize = (((totalImgSize+1023) >> 10) << 10) - totalImgSize; // Copy to final data array of fileSize fileSize = fileSize + paddingSize; fileData = new Byte[fileSize]; tempFileData.CopyTo(fileData,0); // Adjust total image size to final amount totalImgSize = 16 + fileSize + secureDataSize; } else { Console.WriteLine("Error: Binary file was not found!"); return null; } if ( ((binaryFiles[0].entryPointAddr & 0x00FFFFFF) < loadAddr) || ((binaryFiles[0].entryPointAddr & 0x00FFFFFF) > (loadAddr+fileSize)) ) { Console.WriteLine("ERROR: Entry point falls outside load image region."); return null; } // Place header // Config Word - indicates total image size, nor width (if applicable) if (busWidth == 16) { tempAIS_bw.Write((UInt32)(((((totalImgSize >> 10)-1) & 0xF) << 8)|(0x1 << 0)|(0x0 << 4))); sig_bw.Write((UInt32)(((((totalImgSize >> 10)-1) & 0xF) << 8)|(0x1 << 0)|(0x0 << 4))); } else { tempAIS_bw.Write((UInt32)(((((totalImgSize >> 10)-1) & 0xF) << 8)|(0x0 << 0)|(0x0 << 4))); sig_bw.Write((UInt32)(((((totalImgSize >> 10)-1) & 0xF) << 8)|(0x0 << 0)|(0x0 << 4))); } devAISGen.signatureByteCnt += 4; // Magic Number - indicates signed or encrypted if (devAISGen.secureLegacyEncryptImage) { tempAIS_bw.Write((UInt32)SecureLegacyMagic.ENCMOD_MAGIC); sig_bw.Write((UInt32)SecureLegacyMagic.ENCMOD_MAGIC); } else { tempAIS_bw.Write((UInt32)SecureLegacyMagic.SIGNMOD_MAGIC); sig_bw.Write((UInt32)SecureLegacyMagic.SIGNMOD_MAGIC); } devAISGen.signatureByteCnt += 4; // Entry Point - where to jump within the image upon load tempAIS_bw.Write( (UInt32)binaryFiles[0].entryPointAddr ); sig_bw.Write( (UInt32)binaryFiles[0].entryPointAddr ); devAISGen.signatureByteCnt += 4; // SecureDataSize - size of data following image for key struct & signature tempAIS_bw.Write( (UInt32)secureDataSize ); sig_bw.Write( (UInt32)secureDataSize ); // Now place padded binary contents if (!devAISGen.secureLegacyEncryptImage) { // Non-encrypted section tempAIS_bw.Write(fileData); sig_bw.Write(fileData); } else { // Encrypted section // Write unencrypted data to the signature buffer sig_bw.Write(fileData); // Encrypt data using CBC algorithm try { Byte[] encData = AesManagedUtil.AesCTSEncrypt(fileData,devAISGen.customerEncryptionKey,devAISGen.CEKInitialValue); // Write encrypted section data out to AIS data stream tempAIS_bw.Write(encData); } catch(Exception e) { Console.WriteLine("Exception during encryption operation: {0}",e.Message); } } devAISGen.signatureByteCnt += (Int32) fileSize; // Now place the key data tempAIS_bw.Write(secureKeyData); sig_bw.Write(secureKeyData); devAISGen.signatureByteCnt += secureKeyData.Length; // Finally place the signature which covers the entire image SecureAISInsertSignature(devAISGen.signatureStream, devAISGen); // Flush the data and then return to start devAISGen.devAISStream.Flush(); devAISGen.devAISStream.Seek(0,SeekOrigin.Begin); devAISGen.signatureStream.Close(); } #endregion #region AIS Generation else { // --------------------------------------------------------- // ****************** BEGIN AIS GENERATION ***************** // --------------------------------------------------------- Console.WriteLine("Begining the AIS file generation."); // Diaplay currently selected boot mode Console.WriteLine("AIS file being generated for bootmode: {0}.",Enum.GetName(typeof(BootModes),devAISGen.bootMode)); #region AIS Extras and UARTSendDONE Setup //Create the COFF file object for the AISExtras file (if it exists/is defined) if (devAISGen.AISExtraFileName != null) { EmbeddedFileIO.ExtractFile(Assembly.GetExecutingAssembly(), devAISGen.AISExtraFileName, false); if (File.Exists(devAISGen.AISExtraFileName)) { // The file exists, so use it AISExtrasCF = new COFFFile(devAISGen.AISExtraFileName); } else { throw new FileNotFoundException("The AISExtra file, " + devAISGen.AISExtraFileName + ", was not found."); } } // If we have the AISExtras COFF file object, use it to setup the addresses // for the AISExtra functions. These will utilize the L1P and L1D spaces that // are usually cache. if ( (AISExtrasCF != null) && (devAISGen.AISExtraFunc != null)) { // Use symbols to get address for AISExtra functions and parameters for (Int32 i = 0; i < devAISGen.AISExtraFunc.Length; i++) { Hashtable sym = AISExtrasCF.symFind("_" + devAISGen.AISExtraFunc[i].funcName); devAISGen.AISExtraFunc[i].funcAddr = (UInt32)sym["value"]; sym = AISExtrasCF.symFind(".params"); devAISGen.AISExtraFunc[i].paramAddr = (UInt32)sym["value"]; } // If the bootMode is UART we need the UARTSendDONE function if (devAISGen.bootMode == BootModes.UART) { // Set address for the UARTSendDone Function in the .text:uart section UARTSendDONE_TextSection = AISExtrasCF.secFind(".text:uart"); UARTSendDONE_DataSection = AISExtrasCF.secFind(".data:uart"); // Eliminate these as loadable since they will be loaded first, separate // from the main COFF file UARTSendDONE_TextSection["copyToTarget"] = false; UARTSendDONE_DataSection["copyToTarget"] = false; AISExtrasCF.Header["numTargetSections"] = ((UInt32)AISExtrasCF.Header["numTargetSections"] - (UInt32)2); // Set the actual run address for the UARTSendDONE function if ((UARTSendDONE_TextSection != null) && (UARTSendDONE_DataSection != null)) { Debug.DebugMSG("UART section found"); devAISGen.UARTSendDONEAddr = (UInt32)UARTSendDONE_TextSection["phyAddr"]; Hashtable sym = AISExtrasCF.symFind("_UARTSendDONE"); if (sym != null) { devAISGen.UARTSendDONEAddr = (UInt32)sym["value"]; Debug.DebugMSG("UARTSendDONE at 0x{0:X8}",devAISGen.UARTSendDONEAddr); } } else { Console.WriteLine("UARTSendDONE function not found in AISExtra COFF file!!!"); return null; } } } // Setup boolean indicating whether to include UARTSendDONE jump commands if ((devAISGen.bootMode == BootModes.UART) && (devAISGen.UARTSendDONEAddr != 0x0)) devAISGen.SendUARTSendDONE = true; else devAISGen.SendUARTSendDONE = false; #endregion #region Write AIS MAGIC Number and initial data // Write the premilinary header and fields (everything before first AIS command) switch (devAISGen.bootMode) { case BootModes.EMIFA: { if (busWidth == 16) tempAIS_bw.Write((UInt32)(0x1 << 0)|(0x2 << 4)); else tempAIS_bw.Write((UInt32)(0x0 << 0)|(0x2 << 4)); tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } case BootModes.NAND: { tempAIS_bw.Write((UInt32)AIS.MagicNumber); tempAIS_bw.Write((UInt32)0); tempAIS_bw.Write((UInt32)0); tempAIS_bw.Write((UInt32)0); break; } case BootModes.UART: { tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } case BootModes.I2CMASTER: { if (addrWidth == 16) tempAIS_bw.Write((UInt32)2); else tempAIS_bw.Write((UInt32)1); tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } case BootModes.SPIMASTER: { if (addrWidth == 24) tempAIS_bw.Write((UInt32)3); else if (addrWidth == 16) tempAIS_bw.Write((UInt32)2); else tempAIS_bw.Write((UInt32)1); tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } default: { tempAIS_bw.Write((UInt32)AIS.MagicNumber); break; } }; // Add the AIS magic number to signature buffer if ( devAISGen.secureType != SecureType.NONE ) { sig_bw.Write((UInt32)AIS.MagicNumber); devAISGen.signatureByteCnt += 4; } #endregion #region Send Secure Key Load command and data tempAIS_bw.Write((UInt32)AIS.SecureKeyLoad); sig_bw.Write((UInt32)AIS.SecureKeyLoad); devAISGen.signatureByteCnt += 4; tempAIS_bw.Write(secureKeyData); sig_bw.Write(secureKeyData); devAISGen.signatureByteCnt += secureKeyData.Length; #endregion #region Send the exit mode type if ( devAISGen.secureType != SecureType.NONE ) { // Write AIS opcode tempAIS_bw.Write((UInt32)AIS.SetSecExitMode); sig_bw.Write((UInt32)AIS.SetSecExitMode); // Write exit type tempAIS_bw.Write((UInt32)devAISGen.bootLoaderExitType); sig_bw.Write((UInt32)devAISGen.bootLoaderExitType); devAISGen.signatureByteCnt += 8; } #endregion #region Send UARTSendDONE sections // Send UART code if it exists if (devAISGen.SendUARTSendDONE) { CRCCheckType tempCRCType = devAISGen.crcType; devAISGen.crcType = CRCCheckType.NO_CRC; devAISGen.SendUARTSendDONE = false; SecureAISSectionLoad(AISExtrasCF, UARTSendDONE_TextSection, devAISGen, false); SecureAISSectionLoad(AISExtrasCF, UARTSendDONE_DataSection, devAISGen, false); devAISGen.SendUARTSendDONE = true; devAISGen.crcType = tempCRCType; } #endregion #region ROM Function insertion // Insert words for ROM function execution for (UInt32 i = 0; i < devAISGen.ROMFunc.Length; i++) { for (UInt32 j = 0; j < iniSecs.Length; j++) { if (iniSecs[j].iniSectionName.Equals(devAISGen.ROMFunc[i].iniSectionName)) { UInt32 funcIndex = i; tempAIS_bw.Write((UInt32)AIS.FunctionExec); sig_bw.Write((UInt32)AIS.FunctionExec); devAISGen.signatureByteCnt += 4; tempAIS_bw.Write((((UInt32)devAISGen.ROMFunc[i].numParams) << 16) + ((UInt32)funcIndex)); sig_bw.Write((((UInt32)devAISGen.ROMFunc[i].numParams) << 16) + ((UInt32)funcIndex)); devAISGen.signatureByteCnt += 4; // Write Paramter values read from INI file for (Int32 k = 0; k < devAISGen.ROMFunc[i].numParams; k++) { //FIXME Debug.DebugMSG("\tParam name: {0}, Param num: {1}, Value: {2}\n", devAISGen.ROMFunc[i].paramNames[k], k, iniSecs[j].sectionValues[devAISGen.ROMFunc[i].paramNames[k].ToUpper()]); tempAIS_bw.Write((UInt32)iniSecs[j].sectionValues[devAISGen.ROMFunc[i].paramNames[k].ToUpper()]); sig_bw.Write((UInt32)iniSecs[j].sectionValues[devAISGen.ROMFunc[i].paramNames[k].ToUpper()]); devAISGen.signatureByteCnt += 4; } //Insert signature SecureAISInsertSignature(devAISGen.signatureStream,devAISGen); // Call UARTSendDONE from AIS Extras if this is for UART boot if (devAISGen.SendUARTSendDONE) { tempAIS_bw.Write((UInt32)AIS.Jump); tempAIS_bw.Write(devAISGen.UARTSendDONEAddr); sig_bw.Write((UInt32)AIS.Jump); sig_bw.Write(devAISGen.UARTSendDONEAddr); devAISGen.signatureByteCnt += 8; // Insert signature SecureAISInsertSignature(devAISGen.signatureStream,devAISGen); } } } } #endregion #region Insert seqread command if (seqReadEn == true) { tempAIS_bw.Write((UInt32)AIS.SeqReadEnable); sig_bw.Write((UInt32)AIS.SeqReadEnable); devAISGen.signatureByteCnt += 4; } #endregion #region AIS executable data download if (AISExtrasCF != null) { // Load the AISExtras COFF file SecureAISCOFFLoad(AISExtrasCF, devAISGen); // Increment section count numTargetSections += (UInt32)AISExtrasCF.Header["numTargetSections"]; } #endregion #region AIS Extras init function execution //Insert calls for any AISExtra Init functions (like power domains) if (AISExtrasCF != null) { for (UInt32 i = 0; i < devAISGen.AISExtraFunc.Length; i++) { if (devAISGen.AISExtraFunc[i].isInitFunc) { for (UInt32 j = 0; j < iniSecs.Length; j++) { if (iniSecs[j].iniSectionName.Equals(devAISGen.AISExtraFunc[i].iniSectionName)) { for (UInt32 k = 0; k < devAISGen.AISExtraFunc[i].numParams; k++) { // Write SET command tempAIS_bw.Write((UInt32)AIS.Set); sig_bw.Write((UInt32)AIS.Set); //Write type field (32-bit only) tempAIS_bw.Write((UInt32)0x3); sig_bw.Write((UInt32)0x3); // Write appropriate parameter address tempAIS_bw.Write((UInt32) (devAISGen.AISExtraFunc[i].paramAddr + (k * 4))); sig_bw.Write((UInt32) (devAISGen.AISExtraFunc[i].paramAddr + (k * 4))); //Write data to write tempAIS_bw.Write((UInt32)iniSecs[j].sectionValues[devAISGen.AISExtraFunc[i].paramNames[k].ToString()]); sig_bw.Write((UInt32)iniSecs[j].sectionValues[devAISGen.AISExtraFunc[i].paramNames[k].ToString()]); //Write Sleep value (should always be zero) tempAIS_bw.Write((UInt32)0x0); sig_bw.Write((UInt32)0x0); devAISGen.signatureByteCnt += 20; // Insert signature SecureAISInsertSignature(devAISGen.signatureStream, devAISGen); } // Now that params are set, Jump to function tempAIS_bw.Write((UInt32)AIS.Jump); tempAIS_bw.Write(devAISGen.AISExtraFunc[i].funcAddr); sig_bw.Write((UInt32)AIS.Jump); sig_bw.Write(devAISGen.AISExtraFunc[i].funcAddr); devAISGen.signatureByteCnt += 8; // Insert signature SecureAISInsertSignature(devAISGen.signatureStream, devAISGen); // Call UARTSendDONE from AIS Extras if this is for UART boot if (devAISGen.SendUARTSendDONE) { tempAIS_bw.Write((UInt32)AIS.Jump); tempAIS_bw.Write(devAISGen.UARTSendDONEAddr); sig_bw.Write((UInt32)AIS.Jump); sig_bw.Write(devAISGen.UARTSendDONEAddr); devAISGen.signatureByteCnt += 8; // Insert signature SecureAISInsertSignature(devAISGen.signatureStream, devAISGen); } } } } } } #endregion Debug.DebugMSG("Starting binary file section loads."); #region Insert binary data files as SECTION_LOAD commands // Insert binary files for (Int32 i=0; i<binaryFiles.Count; i++) { if (File.Exists(binaryFiles[i].fileName)) { SecureAISBinarySectionLoad(binaryFiles[i].fileName, devAISGen, binaryFiles[i].loadAddr, binaryFiles[i].encrypt); Debug.DebugMSG("Binary file {0} found.", binaryFiles[i].fileName); numTargetSections++; if (binaryFiles[i].useEntryPoint) { entryPoint = binaryFiles[i].entryPointAddr; } } else { Console.WriteLine("WARNING: Binary input file {0} was not found. Skipping.",binaryFiles[i].fileName); } } #endregion Debug.DebugMSG("Starting object file section loads."); #region COFF file parsing and loading // Create the COFF file object for the main application being loaded if (File.Exists(coffFileName)) { SecureObjectFile currFile = new SecureObjectFile(); currFile.useEntryPoint = true; currFile.fileName = coffFileName; currFile.encrypt = false; // Cycle throught all other object files loaded via INI file and unset their // useEntryPoint boolean, warning us as we do Boolean showWarning = false; for (Int32 i=0; i<objectFiles.Count; i++) { // Insert binary file if (objectFiles[i].useEntryPoint) { objectFiles[i].useEntryPoint = false; showWarning = true; } } if (showWarning) Console.WriteLine("WARNING: Ignoring useEntryPoint flag from all object file sections of INI file"); objectFiles.Add(currFile); } // Insert object files for (Int32 i=0; i<objectFiles.Count; i++) { if (File.Exists(objectFiles[i].fileName)) { // FIXME: Add support to detect ELF or COFF and support ELF parsing // Parse the object file COFFFile cf = new COFFFile(objectFiles[i].fileName); if (cf != null) { String[] tempEncryptString = null; if (objectFiles[i].encrypt) { // If this Object file is specified for encryption, temporarily set // global sectionsToEncrypt string to "ALL" tempEncryptString = devAISGen.sectionsToEncrypt; devAISGen.sectionsToEncrypt = new String[1]{"ALL"}; // Load the object file contents SecureAISCOFFLoad(cf, devAISGen); // Increment section count numTargetSections += (UInt32)cf.Header["numTargetSections"]; // If this Object file is specified for encryption, reset the // global sectionsToEncrypt string to its original value devAISGen.sectionsToEncrypt = tempEncryptString; } else { // Load the object file contents SecureAISCOFFLoad(cf, devAISGen); } } else { Console.WriteLine("ERROR: Parsing the input object file {0} failed!",objectFiles[i].fileName); } if (entryPoint == 0x00000000) { if (objectFiles[i].useEntryPoint) { entryPoint = (UInt32)cf.Header["optEntryPoint"]; } } // Insert final function register function if (devAISGen.finalFxnName != null) { Hashtable symbol; // Look for the symbol in the Coff file symbols table symbol = cf.symFind(devAISGen.finalFxnName); // If found, insert the command if (symbol != null) { tempAIS_bw.Write((UInt32)AIS.FinalFxnReg); tempAIS_bw.Write((UInt32)symbol["value"]); sig_bw.Write((UInt32)AIS.FinalFxnReg); sig_bw.Write((UInt32)symbol["value"]); devAISGen.signatureByteCnt += 8; Console.WriteLine("Finalize function symbol, '{0}', found as address 0x{1:X8}.",devAISGen.finalFxnName,(UInt32)symbol["value"]); } else { Console.WriteLine("Finalize function symbol, '{0}', not found.",devAISGen.finalFxnName); } } // Close object file if (cf != null) cf.Close(); } else { Console.WriteLine("WARNING: Input object file {0} was not found. Skipping.",objectFiles[i].fileName); } } #endregion #region Insert Final JUMP_CLOSE command tempAIS_bw.Write((UInt32)AIS.Jump_Close); tempAIS_bw.Write(entryPoint); sig_bw.Write((UInt32)AIS.Jump_Close); sig_bw.Write(entryPoint); devAISGen.signatureByteCnt += 8; if (entryPoint == 0x00000000) Console.WriteLine("WARNING: Entry point never set or set to invalid value"); // Insert signature SecureAISInsertSignature(devAISGen.signatureStream, devAISGen); // Flush the data and then return to start devAISGen.devAISStream.Flush(); devAISGen.devAISStream.Seek(0,SeekOrigin.Begin); devAISGen.signatureStream.Close(); #endregion // Console output Console.WriteLine("AIS file generation was successful."); // --------------------------------------------------------- // ******************* END AIS GENERATION ****************** // --------------------------------------------------------- } #endregion #region Prepare the return byte array // Now create return byte array based on AIS Stream data EndianBinaryReader tempAIS_br; tempAIS_br = new EndianBinaryReader( devAISGen.devAISStream, Endian.LittleEndian); numWords = ((UInt32)tempAIS_br.BaseStream.Length) >> 2; devAISGen.AISData = new Byte[numWords << 2]; //Each word converts to 4 binary bytes Debug.DebugMSG("Number of words in the stream is {0}", numWords); // Copy the data to the output Byte array for (UInt32 i = 0; i < numWords; i++) { BitConverter.GetBytes(tempAIS_br.ReadUInt32()).CopyTo(devAISGen.AISData, i * 4); } // Close the binary reader tempAIS_br.Close(); // Close the COFF files since we are done with them if (AISExtrasCF != null) AISExtrasCF.Close(); // Clean up any embedded file resources that may have been extracted EmbeddedFileIO.CleanUpEmbeddedFiles(); #endregion // Return Byte Array return devAISGen.AISData; }
public void LoadFromArc(string fileName) { string tempFileName = ""; using (FileStream yaz0TestStream = new FileStream(fileName, FileMode.Open)) { EndianBinaryReader yaz0TestReader = new EndianBinaryReader(yaz0TestStream, Endian.Big); string yaz0Test = yaz0TestReader.ReadString(4); if (yaz0Test == "Yaz0") { byte[] uncompressedArc = DecodeYaz0(yaz0TestReader); yaz0TestReader.Close(); fileName = Path.GetTempFileName(); tempFileName = fileName; FileInfo info = new FileInfo(fileName); info.Attributes = FileAttributes.Temporary; using (FileStream tempStream = new FileStream(fileName, FileMode.Open)) { EndianBinaryWriter tempWriter = new EndianBinaryWriter(tempStream, Endian.Big); tempWriter.Write(uncompressedArc); tempWriter.Flush(); tempWriter.Close(); } } } RARC loadedArc = new RARC(fileName); if (File.Exists(tempFileName)) { File.Delete(tempFileName); } FilesFromArc = new List<FileData>(); for (int i = 0; i < loadedArc.Nodes.Count(); i++) { for (int j = 0; j < loadedArc.Nodes[i].Entries.Count(); j++) { if (loadedArc.Nodes[i].Entries[j].Data != null) { FileData file = new FileData(); file.Name = loadedArc.Nodes[i].Entries[j].Name; file.Data = loadedArc.Nodes[i].Entries[j].Data; FilesFromArc.Add(file); } } } foreach (FileData file in FilesFromArc) { if (file.Name.Contains(".dzb")) { using (EndianBinaryReader reader = new EndianBinaryReader(file.Data, Endian.Big)) { Collision = new CollisionMesh(); Collision.Load(reader); } } if (file.Name.Contains(".dzs") || file.Name.Contains(".dzr")) { using (EndianBinaryReader reader = new EndianBinaryReader(file.Data, Endian.Big)) { Read(reader); } } if (file.Name.Contains(".bdl") || file.Name.Contains(".bmd")) { //Not implemented } } }
public static NSBTP_File Read(string Filename) { EndianBinaryReader er = new EndianBinaryReader(File.OpenRead(Filename), Endianness.LittleEndian); NSBTP_File ns = new NSBTP_File(); ns.Header.ID = er.ReadString(Encoding.ASCII, 4); if (ns.Header.ID == "BTP0") { ns.Header.Magic = er.ReadBytes(4); ns.Header.file_size = er.ReadInt32(); ns.Header.header_size = er.ReadInt16(); ns.Header.nSection = er.ReadInt16(); ns.Header.Section_Offset = new Int32[ns.Header.nSection]; for (int i = 0; i < ns.Header.nSection; i++) { ns.Header.Section_Offset[i] = er.ReadInt32(); } ns.PAT0.ID = er.ReadString(Encoding.ASCII, 4); if (ns.PAT0.ID == "PAT0") { ns.PAT0.Size = er.ReadInt32(); //3D Info Structure ns.PAT0.dummy = er.ReadByte(); ns.PAT0.num_objs = er.ReadByte(); ns.PAT0.section_size = er.ReadInt16(); ns.PAT0.unknownBlock.header_size = er.ReadInt16(); ns.PAT0.unknownBlock.section_size = er.ReadInt16(); ns.PAT0.unknownBlock.constant = er.ReadInt32(); ns.PAT0.unknownBlock.unknown1 = new short[ns.PAT0.num_objs]; ns.PAT0.unknownBlock.unknown2 = new short[ns.PAT0.num_objs]; for (int i = 0; i < ns.PAT0.num_objs; i++) { ns.PAT0.unknownBlock.unknown1[i] = er.ReadInt16(); ns.PAT0.unknownBlock.unknown2[i] = er.ReadInt16(); } ns.PAT0.infoBlock.header_size = er.ReadInt16(); ns.PAT0.infoBlock.data_size = er.ReadInt16(); ns.PAT0.infoBlock.Data = new NSBTP_File.pat0.Info.info[ns.PAT0.num_objs]; for (int i = 0; i < ns.PAT0.num_objs; i++) { ns.PAT0.infoBlock.Data[i].MPToffset = er.ReadInt32(); } ns.PAT0.names = new string[ns.PAT0.num_objs]; for (int i = 0; i < ns.PAT0.num_objs; i++) { ns.PAT0.names[i] = er.ReadString(Encoding.ASCII, 16).Replace("\0", ""); } ns.MPT.ID = er.ReadString(Encoding.ASCII, 4); if (ns.MPT.ID == "M" + (char)0x00 + "PT") { ns.MPT.NoFrames = er.ReadInt16(); ns.MPT.NoTex = er.ReadByte(); ns.MPT.NoPal = er.ReadByte(); ns.MPT.Texoffset = er.ReadInt16(); ns.MPT.Paloffset = er.ReadInt16(); //3D Info Structure ns.MPT.dummy = er.ReadByte(); ns.MPT.num_objs = er.ReadByte(); ns.MPT.section_size = er.ReadInt16(); ns.MPT.unknownBlock.header_size = er.ReadInt16(); ns.MPT.unknownBlock.section_size = er.ReadInt16(); ns.MPT.unknownBlock.constant = er.ReadInt32(); ns.MPT.unknownBlock.unknown1 = new short[ns.MPT.num_objs]; ns.MPT.unknownBlock.unknown2 = new short[ns.MPT.num_objs]; for (int i = 0; i < ns.MPT.num_objs; i++) { ns.MPT.unknownBlock.unknown1[i] = er.ReadInt16(); ns.MPT.unknownBlock.unknown2[i] = er.ReadInt16(); } ns.MPT.infoBlock.header_size = er.ReadInt16(); ns.MPT.infoBlock.data_size = er.ReadInt16(); ns.MPT.infoBlock.Data = new NSBTP_File.M_PT.Info.info[ns.MPT.num_objs]; ns.AnimData = new NSBTP_File.animData[ns.MPT.num_objs]; for (int i = 0; i < ns.MPT.num_objs; i++) { ns.MPT.infoBlock.Data[i].KeyFrames = er.ReadInt32(); ns.MPT.infoBlock.Data[i].Unknown1 = er.ReadInt16(); ns.MPT.infoBlock.Data[i].Offset = er.ReadInt16(); ns.AnimData[i].KeyFrames = new NSBTP_File.animData.keyFrame[ns.MPT.infoBlock.Data[i].KeyFrames]; for (int j = 0; j < ns.MPT.infoBlock.Data[i].KeyFrames; j++) { long curpos = er.BaseStream.Position; er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.PAT0.section_size + ns.MPT.infoBlock.Data[i].Offset + j*4 + 8; ns.AnimData[i].KeyFrames[j].Start = er.ReadInt16(); ns.AnimData[i].KeyFrames[j].texId = er.ReadByte(); ns.AnimData[i].KeyFrames[j].palId = er.ReadByte(); er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.PAT0.section_size + ns.MPT.Texoffset + ns.AnimData[i].KeyFrames[j].texId * 16 + 8; ns.AnimData[i].KeyFrames[j].texName = LibNDSFormats.Utils.ReadNSBMDString(er); er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.PAT0.section_size + ns.MPT.Paloffset + ns.AnimData[i].KeyFrames[j].palId * 16 + 8; ns.AnimData[i].KeyFrames[j].palName = LibNDSFormats.Utils.ReadNSBMDString(er); er.BaseStream.Position = curpos; } } ns.MPT.names = new string[ns.MPT.num_objs]; for (int i = 0; i < ns.MPT.num_objs; i++) { ns.MPT.names[i] = LibNDSFormats.Utils.ReadNSBMDString(er); } } else { MessageBox.Show("NSBTP Error"); er.Close(); return ns; } } else { MessageBox.Show("NSBTP Error"); er.Close(); return ns; } } else { MessageBox.Show("NSBTP Error"); er.Close(); return ns; } er.Close(); return ns; }
/// <summary> /// Load materials in stream. /// </summary> /// <param name="stream">Stream to use.</param> /// <returns>Material definitions.</returns> public static IEnumerable<NsbmdAnimation> ReadJnt0(Stream stream, int blockoffset) { EndianBinaryReader reader = new EndianBinaryReader(stream, Endianness.LittleEndian); int blocksize, blockptr, blocklimit; int num, objnum, i, j, r; List<int> dataoffset = new List<int>(); int sec1offset, sec2offset; NsbmdAnimation[] animation = new NsbmdAnimation[1]; List<int> animlen = new List<int>(); //////////////////////////////////////////////// // joint blockptr = blockoffset + 4; // already read the ID, skip 4 bytes blocksize = reader.ReadInt32(); // block size blocklimit = blocksize + blockoffset; reader.ReadByte(); // skip dummy 0 num = reader.ReadByte(); //assert(num > 0); // no of joint must == 1 Console.WriteLine("No. of Joint = %02x\n", num); //dataoffset = (int*)malloc(sizeof(int)); //if (!dataoffset) return NULL; reader.BaseStream.Seek(10 + (num << 2), SeekOrigin.Current); // skip [char xyz], useless blockptr += 10; reader.BaseStream.Seek(4, SeekOrigin.Current); // go straight to joint data offset blockptr += 4; for (i = 0; i < num; i++) dataoffset.Add(getdword(reader.ReadBytes(4)) + blockoffset); //fseek( fnsbca, 16 * num, SEEK_CUR ); // skip names blockptr += 16 * num; for (i = 0; i < num; i++) { reader.BaseStream.Seek(dataoffset[i], SeekOrigin.Begin); //j = getdword(); if (reader.ReadBytes(4) == new byte[] {0x4A,0x00,0x41,0x43 }) return null; blockptr += 4; animlen.Add(getword(reader.ReadBytes(2))); objnum = getword(reader.ReadBytes(2)); //if (objnum != g_model[0].objnum) return NULL; blockptr += 4; //animation = (ANIMATION*)calloc(sizeof(ANIMATION), objnum); //if (!animation) return NULL; animation = new NsbmdAnimation[objnum]; reader.BaseStream.Seek(4, SeekOrigin.Current); // skip 4 zeros blockptr += 4; sec1offset = getdword(reader.ReadBytes(4)) + dataoffset[i]; sec2offset = getdword(reader.ReadBytes(4)) + dataoffset[i]; blockptr += 8; for (j = 0; j < objnum; j++) { animation[j] = new NsbmdAnimation(); animation[j].dataoffset = getword(reader.ReadBytes(2)) + dataoffset[i]; } for (j = 0; j < objnum; j++) { NSBMD.NsbmdAnimation anim = animation[j]; r = getdword(reader.ReadBytes(4)); anim.flag = r; // if ((r >> 1 & 1) == 0) //{ // any transformation? if ((r >> 1 & 1) == 0) { // translation if ((r & 4) == 1) { // use Base T } else { if ((r & 8) == 1) { // consTX anim.m_trans[0] = ((float)getdword(reader.ReadBytes(4))) / 4096.0f; } else { } if ((r & 0x10) == 1) { // consTY anim.m_trans[1] = ((float)getdword(reader.ReadBytes(4))) / 4096.0f; } else { } if ((r & 0x20) == 1) { // consTZ anim.m_trans[0] = ((float)getdword(reader.ReadBytes(4))) / 4096.0f; } else { } } } if ((r >> 6 & 1) == 0) { // rotation if ((r & 0x100) == 1) { // constR anim.a = ((float)getword(reader.ReadBytes(2))) / 4096.0f; anim.b = ((float)getword(reader.ReadBytes(2))) / 4096.0f; } else { } } if ((r >> 9 & 1) == 0) { // scale if ((r & 0x400) == 1) { // use Base S } else { if ((r & 0x800) == 1) { // consSX anim.m_scale[0] = ((float)getdword(reader.ReadBytes(4))) / 4096.0f; } else { } if ((r & 0x1000) == 1) {// consSY anim.m_scale[0] = ((float)getdword(reader.ReadBytes(4))) / 4096.0f; } else { } if ((r & 0x2000) == 1) {// consSZ anim.m_scale[0] = ((float)getdword(reader.ReadBytes(4))) / 4096.0f; } else { } } // } } animation[j] = anim; } } reader.Close(); //free(dataoffset); return animation; }
public static NSBTA_File Read(string Filename) { EndianBinaryReader er = new EndianBinaryReader(File.OpenRead(Filename), Endianness.LittleEndian); NSBTA_File ns = new NSBTA_File(); ns.Header.ID = er.ReadString(Encoding.ASCII, 4); if (ns.Header.ID == "BTA0") { ns.Header.Magic = er.ReadBytes(4); ns.Header.file_size = er.ReadInt32(); ns.Header.header_size = er.ReadInt16(); ns.Header.nSection = er.ReadInt16(); ns.Header.Section_Offset = new Int32[ns.Header.nSection]; for (int i = 0; i < ns.Header.nSection; i++) { ns.Header.Section_Offset[i] = er.ReadInt32(); } ns.SRT0.ID = er.ReadString(Encoding.ASCII, 4); if (ns.SRT0.ID == "SRT0") { ns.SRT0.Size = er.ReadInt32(); //3D Info Structure ns.SRT0.dummy = er.ReadByte(); ns.SRT0.num_objs = er.ReadByte(); ns.SRT0.section_size = er.ReadInt16(); ns.SRT0.unknownBlock.header_size = er.ReadInt16(); ns.SRT0.unknownBlock.section_size = er.ReadInt16(); ns.SRT0.unknownBlock.constant = er.ReadInt32(); ns.SRT0.unknownBlock.unknown1 = new short[ns.SRT0.num_objs]; ns.SRT0.unknownBlock.unknown2 = new short[ns.SRT0.num_objs]; for (int i = 0; i < ns.SRT0.num_objs; i++) { ns.SRT0.unknownBlock.unknown1[i] = er.ReadInt16(); ns.SRT0.unknownBlock.unknown2[i] = er.ReadInt16(); } ns.SRT0.infoBlock.header_size = er.ReadInt16(); ns.SRT0.infoBlock.data_size = er.ReadInt16(); ns.SRT0.infoBlock.Data = new NSBTA_File.srt0.Info.info[ns.SRT0.num_objs]; for (int i = 0; i < ns.SRT0.num_objs; i++) { ns.SRT0.infoBlock.Data[i].MAToffset = er.ReadInt32(); } ns.SRT0.names = new string[ns.SRT0.num_objs]; for (int i = 0; i < ns.SRT0.num_objs; i++) { ns.SRT0.names[i] = er.ReadString(Encoding.ASCII, 16).Replace("\0", ""); } ns.MAT.ID = er.ReadString(Encoding.ASCII, 4); if (ns.MAT.ID == "M"+(char)0x00+"AT") { ns.MAT.Unknown1 = er.ReadInt16(); ns.MAT.Unknown2 = er.ReadByte(); ns.MAT.Unknown3 = er.ReadByte(); //3D Info Structure ns.MAT.dummy = er.ReadByte(); ns.MAT.num_objs = er.ReadByte(); ns.MAT.section_size = er.ReadInt16(); ns.MAT.unknownBlock.header_size = er.ReadInt16(); ns.MAT.unknownBlock.section_size = er.ReadInt16(); ns.MAT.unknownBlock.constant = er.ReadInt32(); ns.MAT.unknownBlock.unknown1 = new short[ns.MAT.num_objs]; ns.MAT.unknownBlock.unknown2 = new short[ns.MAT.num_objs]; for (int i = 0; i < ns.MAT.num_objs; i++) { ns.MAT.unknownBlock.unknown1[i] = er.ReadInt16(); ns.MAT.unknownBlock.unknown2[i] = er.ReadInt16(); } ns.MAT.infoBlock.header_size = er.ReadInt16(); ns.MAT.infoBlock.data_size = er.ReadInt16(); ns.MAT.infoBlock.Data = new NSBTA_File.M_AT.Info.info[ns.MAT.num_objs]; ns.SRTData = new NSBTA_File.srtData[ns.MAT.num_objs]; for (int i = 0; i < ns.MAT.num_objs; i++) { ns.MAT.infoBlock.Data[i].frame = new short[5]; ns.MAT.infoBlock.Data[i].var1 = new short[5]; ns.MAT.infoBlock.Data[i].var2 = new short[5]; ns.MAT.infoBlock.Data[i].var3 = new short[5]; ns.MAT.infoBlock.Data[i].frameStep = new int[5]; for (int j = 0; j < 5; j++) { ns.MAT.infoBlock.Data[i].frame[j] = er.ReadInt16(); ns.MAT.infoBlock.Data[i].var1[j] = (short)(er.ReadInt16() / 4096); ns.MAT.infoBlock.Data[i].var2[j] = er.ReadInt16(); ns.MAT.infoBlock.Data[i].var3[j] = (short)(er.ReadInt16() / 4096); } if (ns.MAT.infoBlock.Data[i].var1[0] > 1) { ns.SRTData[i].scaleS = new decimal[1]; ns.SRTData[i].scaleS[0] = Math.Abs(ns.MAT.infoBlock.Data[i].var2[0] / 4096); } else { ns.SRTData[i].scaleS = new decimal[ns.MAT.infoBlock.Data[i].frame[0]]; } if (ns.MAT.infoBlock.Data[i].var1[1] > 1) { ns.SRTData[i].scaleT = new decimal[1]; ns.SRTData[i].scaleT[0] = Math.Abs(ns.MAT.infoBlock.Data[i].var2[1] / 4096); } else { ns.SRTData[i].scaleT = new decimal[ns.MAT.infoBlock.Data[i].frame[1]]; } if (ns.MAT.infoBlock.Data[i].var1[2] > 1) { ns.SRTData[i].rotate = new decimal[2]; ns.SRTData[i].rotate[0] = ns.MAT.infoBlock.Data[i].var2[2]; ns.SRTData[i].rotate[1] = ns.MAT.infoBlock.Data[i].var3[2]; } else { ns.SRTData[i].rotate = new decimal[ns.MAT.infoBlock.Data[i].frame[2] * 2]; } if (ns.MAT.infoBlock.Data[i].var1[3] > 1) { ns.SRTData[i].translateS = new decimal[1]; ns.SRTData[i].translateS[0] = Math.Abs(ns.MAT.infoBlock.Data[i].var2[3] / 4096); } else { ns.SRTData[i].translateS = new decimal[ns.MAT.infoBlock.Data[i].frame[3]]; ns.MAT.infoBlock.Data[i].frameStep[3] = Math.Abs(ns.MAT.infoBlock.Data[i].var1[3] >> 1); } if (ns.MAT.infoBlock.Data[i].var1[4] > 1) { ns.SRTData[i].translateT = new decimal[1]; ns.SRTData[i].translateT[0] = Math.Abs(ns.MAT.infoBlock.Data[i].var2[4] / 4096); } else { ns.SRTData[i].translateT = new decimal[ns.MAT.infoBlock.Data[i].frame[4]]; ns.MAT.infoBlock.Data[i].frameStep[4] = Math.Abs(ns.MAT.infoBlock.Data[i].var1[4] >> 1); } //ns.SRTData[i].scaleS = new decimal[ns.MAT.infoBlock.Data[i].var1[0] == 3 ? 1 : ns.MAT.infoBlock.Data[i].frame[0]]; //ns.SRTData[i].scaleT = new decimal[ns.MAT.infoBlock.Data[i].var1[1] == 3 ? 1 : ns.MAT.infoBlock.Data[i].frame[1]]; //ns.SRTData[i].rotate = new decimal[ns.MAT.infoBlock.Data[i].var1[2] == 2 ? ns.MAT.infoBlock.Data[i].var1[2] == 3 ? 2 : 1 : ns.MAT.infoBlock.Data[i].frame[2]]; //ns.SRTData[i].translateS = new decimal[ns.MAT.infoBlock.Data[i].var1[3] == 3 ? 1 : ns.MAT.infoBlock.Data[i].frame[3]]; //ns.SRTData[i].translateT = new decimal[ns.MAT.infoBlock.Data[i].var1[4] == 3 ? 1 : ns.MAT.infoBlock.Data[i].frame[4]]; } ns.MAT.names = new string[ns.MAT.num_objs]; for (int i = 0; i < ns.MAT.num_objs; i++) { ns.MAT.names[i] = er.ReadString(Encoding.ASCII, 16).Replace("\0", ""); } for (int i = 0; i < ns.MAT.num_objs; i++) { if (ns.SRTData[i].scaleS.Length != 1) { er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.SRT0.section_size + ns.MAT.infoBlock.Data[i].var2[0] + 8; for (int j = 0; j < ns.SRTData[i].scaleS.Length; j++) { ns.SRTData[i].scaleS[j] = (decimal)(er.ReadInt16() / 4096d); } } if (ns.SRTData[i].scaleT.Length != 1) { er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.SRT0.section_size + ns.MAT.infoBlock.Data[i].var2[1] + 8; for (int j = 0; j < ns.SRTData[i].scaleT.Length; j++) { ns.SRTData[i].scaleT[j] = (decimal)(er.ReadInt16() / 4096d); } } if (ns.SRTData[i].rotate.Length != 2) { er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.SRT0.section_size + ns.MAT.infoBlock.Data[i].var2[2] + 8; for (int j = 0; j < ns.SRTData[i].rotate.Length; j++) { ns.SRTData[i].rotate[j] = (decimal)(er.ReadInt16() / 4096d); } } if (ns.SRTData[i].translateS.Length != 1) { er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.SRT0.section_size + ns.MAT.infoBlock.Data[i].var2[3] + 8; for (int j = 0; j < ns.SRTData[i].translateS.Length; j += (ns.MAT.infoBlock.Data[i].frameStep[3] == 0 ? 1 : ns.MAT.infoBlock.Data[i].frameStep[3])) { decimal value = (decimal)(er.ReadInt16() / 4096d); for (int k = 0; k < (ns.MAT.infoBlock.Data[i].frameStep[3] == 0 ? 1 : ns.MAT.infoBlock.Data[i].frameStep[3]); k++) { ns.SRTData[i].translateS[j + k] = value; } } } if (ns.SRTData[i].translateT.Length != 1) { er.BaseStream.Position = ns.Header.Section_Offset[0] + ns.SRT0.section_size + ns.MAT.infoBlock.Data[i].var2[4] + 8; for (int j = 0; j < ns.SRTData[i].translateT.Length; j +=( ns.MAT.infoBlock.Data[i].frameStep[4] == 0 ? 1 : ns.MAT.infoBlock.Data[i].frameStep[4])) { decimal value = (decimal)(er.ReadInt16() / 4096d); for (int k = 0; k < (ns.MAT.infoBlock.Data[i].frameStep[4] == 0 ? 1 : ns.MAT.infoBlock.Data[i].frameStep[4]); k++) { ns.SRTData[i].translateT[j + k] = value; } } } } } else { MessageBox.Show("Error"); er.Close(); return ns; } } else { MessageBox.Show("Error"); er.Close(); return ns; } } else { MessageBox.Show("Error"); er.Close(); return ns; } er.Close(); return ns; }
// Gen V private void listBox6_SelectedIndexChanged(object sender, EventArgs e) { listBox5.Items.Clear(); listBox4.Items.Clear(); if (radioButton18.Checked == true) { editorTileset = workingFolder + @"data\a\0\1\tilesets"; } else if (radioButton17.Checked == true) { editorTileset = workingFolder + @"data\a\1\7\bldtilesets"; } else { editorTileset = workingFolder + @"data\a\1\7\bld2tilesets"; } EndianBinaryReader er = new EndianBinaryReader(File.OpenRead(editorTileset + "\\" + listBox6.SelectedIndex.ToString("D4")), Endianness.LittleEndian); nsbtx = new NSBTX_File(); if (er.ReadString(Encoding.ASCII, 4) != "BTX0") { MessageBox.Show(rm.GetString("tilesetError"), null, MessageBoxButtons.OK, MessageBoxIcon.Stop); er.Close(); return; } else { nsbtx.Header.ID = "BTX0"; nsbtx.Header.Magic = er.ReadBytes(4); nsbtx.Header.file_size = er.ReadInt32(); nsbtx.Header.header_size = er.ReadInt16(); nsbtx.Header.nSection = er.ReadInt16(); nsbtx.Header.Section_Offset = new Int32[nsbtx.Header.nSection]; for (int i = 0; i < nsbtx.Header.nSection; i++) { nsbtx.Header.Section_Offset[i] = er.ReadInt32(); } nsbtx.TEX0.ID = er.ReadString(Encoding.ASCII, 4); if (nsbtx.TEX0.ID != "TEX0") { MessageBox.Show(rm.GetString("tilesetError")); er.Close(); return; } } nsbtx.TEX0.Section_size = er.ReadInt32(); nsbtx.TEX0.Padding1 = er.ReadInt32(); nsbtx.TEX0.Texture_Data_Size = (er.ReadInt16() << 3); nsbtx.TEX0.Texture_Info_Offset = er.ReadInt16(); nsbtx.TEX0.Padding2 = er.ReadInt32(); nsbtx.TEX0.Texture_Data_Offset = er.ReadInt32(); nsbtx.TEX0.Padding3 = er.ReadInt32(); nsbtx.TEX0.Compressed_Texture_Data_Size = (er.ReadInt16() << 3); nsbtx.TEX0.Compressed_Texture_Info_Offset = er.ReadInt16(); nsbtx.TEX0.Padding4 = er.ReadInt32(); nsbtx.TEX0.Compressed_Texture_Data_Offset = er.ReadInt32(); nsbtx.TEX0.Compressed_Texture_Info_Data_Offset = er.ReadInt32(); nsbtx.TEX0.Padding5 = er.ReadInt32(); nsbtx.TEX0.Palette_Data_Size = (er.ReadInt32() << 3); nsbtx.TEX0.Palette_Info_Offset = er.ReadInt32(); nsbtx.TEX0.Palette_Data_Offset = er.ReadInt32(); nsbtx.TexInfo.dummy = er.ReadByte(); nsbtx.TexInfo.num_objs = er.ReadByte(); nsbtx.TexInfo.section_size = er.ReadInt16(); nsbtx.TexInfo.unknownBlock.header_size = er.ReadInt16(); nsbtx.TexInfo.unknownBlock.section_size = er.ReadInt16(); nsbtx.TexInfo.unknownBlock.constant = er.ReadInt32(); nsbtx.TexInfo.unknownBlock.unknown1 = new List<short>(); nsbtx.TexInfo.unknownBlock.unknown2 = new List<short>(); for (int i = 0; i < nsbtx.TexInfo.num_objs; i++) { nsbtx.TexInfo.unknownBlock.unknown1.Add(er.ReadInt16()); nsbtx.TexInfo.unknownBlock.unknown2.Add(er.ReadInt16()); } nsbtx.TexInfo.infoBlock.header_size = er.ReadInt16(); nsbtx.TexInfo.infoBlock.data_size = er.ReadInt16(); nsbtx.TexInfo.infoBlock.TexInfo = new NSBTX_File.texInfo.Info.texInfo[nsbtx.TexInfo.num_objs]; //long compressedStartOffset = 0x00; for (int i = 0; i < nsbtx.TexInfo.num_objs; i++) { nsbtx.TexInfo.infoBlock.TexInfo[i].Texture_Offset = (er.ReadInt16() << 3); nsbtx.TexInfo.infoBlock.TexInfo[i].Parameters = er.ReadInt16(); nsbtx.TexInfo.infoBlock.TexInfo[i].Width = er.ReadByte(); nsbtx.TexInfo.infoBlock.TexInfo[i].Unknown1 = er.ReadByte(); nsbtx.TexInfo.infoBlock.TexInfo[i].Height = er.ReadByte(); nsbtx.TexInfo.infoBlock.TexInfo[i].Unknown2 = er.ReadByte(); nsbtx.TexInfo.infoBlock.TexInfo[i].coord_transf = (byte)(nsbtx.TexInfo.infoBlock.TexInfo[i].Parameters & 14); nsbtx.TexInfo.infoBlock.TexInfo[i].color0 = (byte)((nsbtx.TexInfo.infoBlock.TexInfo[i].Parameters >> 13) & 1); nsbtx.TexInfo.infoBlock.TexInfo[i].format = (byte)((nsbtx.TexInfo.infoBlock.TexInfo[i].Parameters >> 10) & 7); nsbtx.TexInfo.infoBlock.TexInfo[i].height = (byte)(8 << ((nsbtx.TexInfo.infoBlock.TexInfo[i].Parameters >> 7) & 7)); nsbtx.TexInfo.infoBlock.TexInfo[i].width = (byte)(8 << ((nsbtx.TexInfo.infoBlock.TexInfo[i].Parameters >> 4) & 7)); nsbtx.TexInfo.infoBlock.TexInfo[i].flip_Y = (byte)((nsbtx.TexInfo.infoBlock.TexInfo[i].Parameters >> 3) & 1); nsbtx.TexInfo.infoBlock.TexInfo[i].flip_X = (byte)((nsbtx.TexInfo.infoBlock.TexInfo[i].Parameters >> 2) & 1); nsbtx.TexInfo.infoBlock.TexInfo[i].repeat_Y = (byte)((nsbtx.TexInfo.infoBlock.TexInfo[i].Parameters >> 1) & 1); nsbtx.TexInfo.infoBlock.TexInfo[i].repeat_X = (byte)(nsbtx.TexInfo.infoBlock.TexInfo[i].Parameters & 1); nsbtx.TexInfo.infoBlock.TexInfo[i].depth = (byte)bpp[nsbtx.TexInfo.infoBlock.TexInfo[i].format]; if (nsbtx.TexInfo.infoBlock.TexInfo[i].width == 0x00) switch (nsbtx.TexInfo.infoBlock.TexInfo[i].Unknown1 & 0x3) { case 2: nsbtx.TexInfo.infoBlock.TexInfo[i].width = 0x200; break; default: nsbtx.TexInfo.infoBlock.TexInfo[i].width = 0x100; break; } if (nsbtx.TexInfo.infoBlock.TexInfo[i].height == 0x00) switch ((nsbtx.TexInfo.infoBlock.TexInfo[i].Height >> 3) & 0x3) { case 2: nsbtx.TexInfo.infoBlock.TexInfo[i].height = 0x200; break; default: nsbtx.TexInfo.infoBlock.TexInfo[i].height = 0x100; break; } int imgsize = (nsbtx.TexInfo.infoBlock.TexInfo[i].width * nsbtx.TexInfo.infoBlock.TexInfo[i].height * nsbtx.TexInfo.infoBlock.TexInfo[i].depth) / 8; long curpos = er.BaseStream.Position; if (nsbtx.TexInfo.infoBlock.TexInfo[i].format != 5) { er.BaseStream.Seek(nsbtx.TexInfo.infoBlock.TexInfo[i].Texture_Offset + nsbtx.Header.Section_Offset[0] + nsbtx.TEX0.Texture_Data_Offset, SeekOrigin.Begin); } else { er.BaseStream.Seek(nsbtx.Header.Section_Offset[0] + nsbtx.TEX0.Compressed_Texture_Data_Offset + nsbtx.TexInfo.infoBlock.TexInfo[i].Texture_Offset, SeekOrigin.Begin); } nsbtx.TexInfo.infoBlock.TexInfo[i].Image = er.ReadBytes(imgsize); er.BaseStream.Seek(curpos, SeekOrigin.Begin); if (nsbtx.TexInfo.infoBlock.TexInfo[i].format == 5) { //nsbtx.TexInfo.infoBlock.TexInfo[i].compressedDataStart = (uint)compressedStartOffset; //compressedStartOffset += imgsize / 2; curpos = er.BaseStream.Position; er.BaseStream.Seek(nsbtx.Header.Section_Offset[0] + nsbtx.TEX0.Compressed_Texture_Info_Data_Offset + nsbtx.TexInfo.infoBlock.TexInfo[i].Texture_Offset / 2, SeekOrigin.Begin); nsbtx.TexInfo.infoBlock.TexInfo[i].spData = er.ReadBytes(imgsize / 2); er.BaseStream.Seek(curpos, SeekOrigin.Begin); } } nsbtx.TexInfo.names = new List<string>(); for (int i = 0; i < nsbtx.TexInfo.num_objs; i++) { nsbtx.TexInfo.names.Add(er.ReadString(Encoding.ASCII, 16).Replace("\0", "")); listBox5.Items.Add(nsbtx.TexInfo.names[i]); } nsbtx.PalInfo.dummy = er.ReadByte(); nsbtx.PalInfo.num_objs = er.ReadByte(); nsbtx.PalInfo.section_size = er.ReadInt16(); nsbtx.PalInfo.unknownBlock.header_size = er.ReadInt16(); nsbtx.PalInfo.unknownBlock.section_size = er.ReadInt16(); nsbtx.PalInfo.unknownBlock.constant = er.ReadInt32(); nsbtx.PalInfo.unknownBlock.unknown1 = new List<short>(); nsbtx.PalInfo.unknownBlock.unknown2 = new List<short>(); for (int i = 0; i < nsbtx.PalInfo.num_objs; i++) { nsbtx.PalInfo.unknownBlock.unknown1.Add(er.ReadInt16()); nsbtx.PalInfo.unknownBlock.unknown2.Add(er.ReadInt16()); } nsbtx.PalInfo.infoBlock.header_size = er.ReadInt16(); nsbtx.PalInfo.infoBlock.data_size = er.ReadInt16(); nsbtx.PalInfo.infoBlock.PalInfo = new NSBTX_File.palInfo.Info.palInfo[nsbtx.PalInfo.num_objs]; for (int i = 0; i < nsbtx.PalInfo.num_objs; i++) { nsbtx.PalInfo.infoBlock.PalInfo[i].Palette_Offset = (er.ReadInt16() << 3); nsbtx.PalInfo.infoBlock.PalInfo[i].Color0 = er.ReadInt16(); er.BaseStream.Position -= 4; int palBase = er.ReadInt32(); int palAddr = palBase & 0xfff; long curpos = er.BaseStream.Position; er.BaseStream.Seek(nsbtx.Header.Section_Offset[0] + nsbtx.TEX0.Palette_Data_Offset, SeekOrigin.Begin); er.BaseStream.Seek(nsbtx.PalInfo.infoBlock.PalInfo[i].Palette_Offset, SeekOrigin.Current); nsbtx.PalInfo.infoBlock.PalInfo[i].pal = Tinke.Convertir.BGR555(er.ReadBytes(nsbtx.TEX0.Palette_Data_Size - nsbtx.PalInfo.infoBlock.PalInfo[i].Palette_Offset)); er.BaseStream.Seek(curpos, SeekOrigin.Begin); } nsbtx.PalInfo.names = new List<string>(); for (int i = 0; i < nsbtx.PalInfo.num_objs; i++) { nsbtx.PalInfo.names.Add(er.ReadString(Encoding.ASCII, 16).Replace("\0", "")); listBox4.Items.Add(nsbtx.PalInfo.names[i]); } List<int> offsets = new List<int>(); for (int i = 0; i < nsbtx.PalInfo.num_objs; i++) { //if(!offsets.Contains(nsbtx.PalInfo.infoBlock.PalInfo[i].Palette_Offset)) //{ offsets.Add(nsbtx.PalInfo.infoBlock.PalInfo[i].Palette_Offset); //} } offsets.Add((int)er.BaseStream.Length); offsets.Sort(); for (int i = 0; i < nsbtx.PalInfo.num_objs; i++) { int pallength; int j = -1; do { j++; } while (offsets[j] - nsbtx.PalInfo.infoBlock.PalInfo[i].Palette_Offset <= 0);//nsbtx.PalInfo.infoBlock.PalInfo[i + j].Palette_Offset - nsbtx.PalInfo.infoBlock.PalInfo[i].Palette_Offset == 0) pallength = offsets[j] - nsbtx.PalInfo.infoBlock.PalInfo[i].Palette_Offset; Color[] c_ = nsbtx.PalInfo.infoBlock.PalInfo[i].pal; List<Color> c = new List<Color>(); c.AddRange(nsbtx.PalInfo.infoBlock.PalInfo[i].pal.Take(pallength / 2)); nsbtx.PalInfo.infoBlock.PalInfo[i].pal = c.ToArray(); } er.Close(); listBox5.SelectedIndex = 0; if (nsbtx.PalInfo.num_objs != 0) { listBox4.SelectedIndex = 0; } }
/// <summary> /// genAIS command. Always use section-by-section CRC checks /// </summary> /// <param name="mainObjectFileName"></param> /// <param name="bootMode"></param> /// <returns>Bytes of the binary or text AIS command</returns> public static Byte[] GenAIS( AISGen devAISGen, List<String> inputFileNames, IniFile iniFile ) { UInt32 numWords; // Setup the binary writer to generate the temp AIS file devAISGen.devAISStream = new MemoryStream(); using ( devAISGen.writer = new EndianBinaryWriter( devAISGen.devAISStream, devAISGen.devEndian) ) { // List to keep track of loadable sections and their occupied memory ranges devAISGen.sectionMemory = new List<MemoryRange>(); // Initiate list to keep track of the input files devAISGen.objectFiles = new List<ObjectFile>(); // Get data from the GENERAL INI Section GeneralIniSectionParse(devAISGen, iniFile); #region Main AIS Generation // --------------------------------------------------------- // ****************** BEGIN AIS GENERATION ***************** // --------------------------------------------------------- Console.WriteLine("Begining the AIS file generation."); // Diaplay currently selected boot mode Console.WriteLine("AIS file being generated for bootmode: {0}.",Enum.GetName(typeof(AisBootModes),devAISGen.bootMode)); // Write the premilinary header and fields (everything before first AIS command) devAISGen.InsertAISPreamble(); Debug.DebugMSG("Preamble Complete"); // Parse the INI sections in order, inserting needed AIS commands if (iniFile != null) { foreach(IniSection sec in iniFile.Sections) { InsertAISCommandViaINI(devAISGen, sec); } Debug.DebugMSG("INI parsing complete"); } // Insert the object file passed in on the top-level (if it exists) if (inputFileNames != null) { foreach (String fn in inputFileNames) { String[] nameAndAddr = fn.Split('@'); Debug.DebugMSG("Inserting file " + nameAndAddr[0]); if (!File.Exists(nameAndAddr[0])) { Console.WriteLine("ERROR: {0} does not exist. Aborting...", nameAndAddr[0]); return null; } if (nameAndAddr.Length == 2) { UInt32 loadAddr; nameAndAddr[1] = nameAndAddr[1].ToLower(); if (nameAndAddr[1].StartsWith("0x")) { if (!UInt32.TryParse(nameAndAddr[1].Replace("0x", ""), NumberStyles.HexNumber, null, out loadAddr)) { Console.WriteLine("WARNING: Invalid address format, {0}. Ignoring...", nameAndAddr[1]); } else { devAISGen.InsertAISObjectFile(nameAndAddr[0], loadAddr); } } else if (UInt32.TryParse(nameAndAddr[1], out loadAddr)) { devAISGen.InsertAISObjectFile(nameAndAddr[0], loadAddr); } else { Console.WriteLine("WARNING: Invalid address format, {0}. Ignoring...", nameAndAddr[1]); } } else if (nameAndAddr.Length == 1) { // If we still have not had a valid entry point set, then use entry point from // first encountered non-binary file in the inputFileNames list if (devAISGen.entryPoint == 0xFFFFFFFF) { devAISGen.InsertAISObjectFile(nameAndAddr[0], true); } else { devAISGen.InsertAISObjectFile(nameAndAddr[0], false); } } else { Console.WriteLine("WARNING: Invalid filename format, {0}. Ignoring...", fn); } } Debug.DebugMSG("Main input file insertion complete."); } // If CRC type is for single CRC, send Request CRC now if (devAISGen.aisCRCType == AisCRCCheckType.SINGLE_CRC) { devAISGen.InsertAISRequestCRC(); } // Insert closing JumpClose AIS command (issue warning) if (devAISGen.entryPoint == 0xFFFFFFFF) { // No valid entry point was ever set (issue warning) Console.WriteLine("WARNING: Entry point set to null pointer!"); devAISGen.InsertAISJumpClose(0x00000000); } else { devAISGen.InsertAISJumpClose(devAISGen.entryPoint); } // Flush the data and then return to start devAISGen.devAISStream.Flush(); devAISGen.devAISStream.Seek(0,SeekOrigin.Begin); Console.WriteLine("AIS file generation was successful."); // --------------------------------------------------------- // ******************* END AIS GENERATION ****************** // --------------------------------------------------------- #endregion // Now create return Byte array based on tempAIS file and the bootmode EndianBinaryReader tempAIS_br = new EndianBinaryReader(devAISGen.devAISStream, Endian.LittleEndian); // Setup the binary reader object numWords = ((UInt32)tempAIS_br.BaseStream.Length) >> 2; devAISGen.AISData = new Byte[numWords << 2]; //Each word converts to 4 binary bytes Debug.DebugMSG("Number of words in the AIS output is {0}", numWords); // Copy the data to the output Byte array for (UInt32 i = 0; i < numWords; i++) { BitConverter.GetBytes(tempAIS_br.ReadUInt32()).CopyTo(devAISGen.AISData, i * 4); } // Close the binary reader tempAIS_br.Close(); } // Dispose of all object files foreach (ObjectFile file in devAISGen.objectFiles) { try { file.Dispose(); } catch (Exception e) { Console.WriteLine(e.Message); } } // Clean up any embedded file resources that may have been extracted EmbeddedFileIO.CleanUpEmbeddedFiles(); // Return Byte Array return devAISGen.AISData; }
/// <summary> /// SecureGenAIS command. /// </summary> /// <param name="inputFileNames">File name of input .out file</param> /// <param name="bootMode">AISGen Object for the particular device</param> /// <returns>Bytes of the binary or AIS boot image</returns> public static Byte[] SecureGenAIS(AISGen devAISGen, List<String> inputFileNames, IniFile iniFile) { UInt32 numWords; // Set defaults devAISGen.bootLoaderExitType = BootLoaderExitType.NONE; devAISGen.currHashAlgorithmValue = SHA_Algorithm.SHA1; devAISGen.sectionsToEncrypt = null; devAISGen.rsaObject = null; devAISGen.customerEncryptionKey = null; devAISGen.keyEncryptionKey = null; devAISGen.genericKeyHeaderData = null; devAISGen.currHashAlgorithm = null; // Setup the binary writer to generate the temp AIS file devAISGen.sigStream = new MemoryStream(); devAISGen.devAISStream = new MemoryStream(); devAISGen.sigWriter = new EndianBinaryWriter( devAISGen.sigStream, devAISGen.devEndian); using ( devAISGen.writer = new EndianBinaryWriter( devAISGen.devAISStream, devAISGen.devEndian) ) { // List to keep track of loadable sections and their occupied memory ranges devAISGen.sectionMemory = new List<MemoryRange>(); // Initiate list to keep track of the input files devAISGen.objectFiles = new List<ObjectFile>(); // Get data from the GENERAL INI Section GeneralIniSectionParse(devAISGen, iniFile); // Get data from the SECURITY INI Section if (SecurityIniSectionParse(devAISGen, iniFile) != retType.SUCCESS) { Console.WriteLine("Aborting..."); return null; } #region Handle the case of Legacy boot mode if (devAISGen.bootMode == AisBootModes.LEGACY) { UInt32 fileSize = 0, secureDataSize = 0, totalImgSize = 0, paddingSize = 0; UInt32 loadAddr = 0, fileCount = 0; Byte[] fileData; String fileName = null; Boolean encryptSections = false; UInt32 entryPointAddr = 0x00000000; // Check for legacy input file foreach( IniSection sec in iniFile.Sections) { if (sec.sectionName.Equals("LEGACYINPUTFILE", StringComparison.OrdinalIgnoreCase)) { fileCount++; foreach (DictionaryEntry de in sec.sectionValues) { // File name for binary section data if (((String)de.Key).Equals("FILENAME", StringComparison.OrdinalIgnoreCase)) { fileName = (String) sec.sectionValues["FILENAME"]; } // Binary section's load address in the memory map if (((String)de.Key).Equals("LOADADDRESS", StringComparison.OrdinalIgnoreCase)) { loadAddr = (UInt32) sec.sectionValues["LOADADDRESS"]; } // Binary section's entry point address in the memory map if (((String)de.Key).Equals("ENTRYPOINTADDRESS", StringComparison.OrdinalIgnoreCase)) { entryPointAddr = (UInt32) sec.sectionValues["ENTRYPOINTADDRESS"]; } // Binary section's entry point address in the memory map if (((String)de.Key).Equals("ENCRYPT", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["ENCRYPT"]).Equals("YES", StringComparison.OrdinalIgnoreCase)) encryptSections = true; if (((String)sec.sectionValues["ENCRYPT"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) encryptSections = true; } } if (fileName == null) { Console.WriteLine("ERROR: File name must be provided in INPUTFILE section."); return null; } // Insert the file into the AIS image if (( entryPointAddr == 0x00000000)) { Console.WriteLine("Entrypoint Address = {0} is not valid.", entryPointAddr); return null; } } } // Validate an input binary file was given in the INI file if (fileCount == 0) { Console.WriteLine("ERROR: You did not supply a binary file section in the INI file!"); return null; } if (fileCount > 1) { Console.WriteLine("WARNING: You supplied too many binary file sections in the INI file."); Console.WriteLine(" Only using the first one."); } // Figure out the size of the secure data region (signature + keystruct) if (devAISGen.SecureType == AisSecureType.CUSTOM) { // On custom secure we have rsa keySize bits for signature and modulus of key struct, // plus eight additional bytes from key struct secureDataSize = (UInt32) (8 + (devAISGen.rsaObject.KeySize >> 3) + (devAISGen.rsaObject.KeySize >> 3)); } else if (devAISGen.SecureType == AisSecureType.GENERIC) { // On generic secure we have 32 for key and HashSize bits rounded up to nearst 16 bytes // for signature data. secureDataSize = (UInt32) (32 + ((((devAISGen.currHashAlgorithm.HashSize >> 3)+15)>>4)<<4)); } // Verify legacy input binary file exists, and get data if it does if (File.Exists(fileName)) { Byte[] tempFileData = FileIO.GetFileData(fileName); fileSize = (UInt32) tempFileData.Length; totalImgSize = 16 + fileSize + secureDataSize; if (totalImgSize > 16*1024) { Console.WriteLine("WARNING: The input image is too large for the ROM boot loader."); Console.WriteLine("Reduce its size by {0} bytes.", (totalImgSize - (16*1024))); } // Figure out how much to pad input file region to acheive complete image ending on 1K boundary paddingSize = (((totalImgSize+1023) >> 10) << 10) - totalImgSize; // Copy to final data array of fileSize fileSize = fileSize + paddingSize; fileData = new Byte[fileSize]; tempFileData.CopyTo(fileData,0); // Adjust total image size to final amount totalImgSize = 16 + fileSize + secureDataSize; } else { Console.WriteLine("Error: Binary file was not found!"); return null; } if ( ((entryPointAddr & 0x00FFFFFF) < loadAddr) || ((entryPointAddr & 0x00FFFFFF) > (loadAddr+fileSize)) ) { Console.WriteLine("ERROR: Entry point falls outside load image region."); return null; } // Place header // Config Word - indicates total image size, nor width (if applicable) if (devAISGen.busWidth == 16) { devAISGen.writer.Write ((UInt32)(((((totalImgSize >> 10)-1) & 0xFFFF) << 8)|(0x1 << 0)|(0x0 << 4))); devAISGen.sigWriter.Write((UInt32)(((((totalImgSize >> 10)-1) & 0xFFFF) << 8)|(0x1 << 0)|(0x0 << 4))); } else { devAISGen.writer.Write ((UInt32)(((((totalImgSize >> 10)-1) & 0xFFFF) << 8)|(0x0 << 0)|(0x0 << 4))); devAISGen.sigWriter.Write((UInt32)(((((totalImgSize >> 10)-1) & 0xFFFF) << 8)|(0x0 << 0)|(0x0 << 4))); } // Magic Number - indicates signed or encrypted if (encryptSections) { devAISGen.writer.Write((UInt32)SecureLegacyMagic.ENCMOD_MAGIC); devAISGen.sigWriter.Write((UInt32)SecureLegacyMagic.ENCMOD_MAGIC); } else { devAISGen.writer.Write((UInt32)SecureLegacyMagic.SIGNMOD_MAGIC); devAISGen.sigWriter.Write((UInt32)SecureLegacyMagic.SIGNMOD_MAGIC); } // Entry Point - where to jump within the image upon load devAISGen.writer.Write( entryPointAddr ); devAISGen.sigWriter.Write( entryPointAddr ); // SecureDataSize - size of data following image for key struct & signature devAISGen.writer.Write( (UInt32)secureDataSize ); devAISGen.sigWriter.Write( (UInt32)secureDataSize ); // Now place padded binary contents if (!encryptSections) { // Non-encrypted section devAISGen.writer.Write(fileData); devAISGen.sigWriter.Write(fileData); } else { // Encrypted section // Write unencrypted data to the signature buffer devAISGen.sigWriter.Write(fileData); // Encrypt data using CBC algorithm try { Byte[] encData = AesManagedUtil.AesCTSEncrypt(fileData,devAISGen.customerEncryptionKey,devAISGen.CEKInitialValue); // Write encrypted section data out to AIS data stream devAISGen.writer.Write(encData); } catch(Exception e) { Console.WriteLine("Exception during encryption operation: {0}",e.Message); } } // Now place the key data devAISGen.writer.Write(devAISGen.secureKeyData); devAISGen.sigWriter.Write(devAISGen.secureKeyData); // Finally place the signature which covers the entire image InsertAISSecureSignature( devAISGen ); // Flush the data and then return to start devAISGen.devAISStream.Flush(); devAISGen.devAISStream.Seek(0,SeekOrigin.Begin); devAISGen.sigStream.Close(); } #endregion #region AIS Generation else { // --------------------------------------------------------- // ****************** BEGIN AIS GENERATION ***************** // --------------------------------------------------------- Console.WriteLine("Begining the Secure AIS file generation."); // Diaplay currently selected boot mode Console.WriteLine("AIS file being generated for bootmode: {0}.",Enum.GetName(typeof(AisBootModes),devAISGen.bootMode)); // Write the premilinary header and fields (everything before first AIS command) devAISGen.InsertAISPreamble(); Debug.DebugMSG("Preamble Complete"); // Write the Secure Key command and key data devAISGen.InsertAISSecureKeyLoad(devAISGen.secureKeyData); Debug.DebugMSG("Secure Key Insertion Complete"); // Insert Exit Mode type devAISGen.InsertAISSetExitMode(devAISGen.bootLoaderExitType); Debug.DebugMSG("Set Exit Mode complete"); // Parse the INI sections in order, inserting needed AIS commands foreach(IniSection sec in iniFile.Sections) { InsertSecureAISCommandViaINI(devAISGen, sec); } Debug.DebugMSG("INI parsing complete"); // Insert the object file(s) passed in on the top-level (if it exists) foreach (String fn in inputFileNames) { String[] nameAndAddr = fn.Split('@'); Debug.DebugMSG("Inserting file " + nameAndAddr[0]); if (!File.Exists(nameAndAddr[0])) { Console.WriteLine("ERROR: {0} does not exist. Aborting...", nameAndAddr[0]); return null; } // Handle binary files provided with a load address if (nameAndAddr.Length == 2) { UInt32 loadAddr; nameAndAddr[1] = nameAndAddr[1].ToLower(); if (nameAndAddr[1].StartsWith("0x")) { if (!UInt32.TryParse(nameAndAddr[1].Replace("0x", ""), NumberStyles.HexNumber, null, out loadAddr)) { Console.WriteLine("WARNING: Invalid address format, {0}. Ignoring...", nameAndAddr[1]); } else { devAISGen.InsertAISSecureObjectFile(nameAndAddr[0], loadAddr, false); } } else if (UInt32.TryParse(nameAndAddr[1], out loadAddr)) { devAISGen.InsertAISSecureObjectFile(nameAndAddr[0], loadAddr, false); } else { Console.WriteLine("WARNING: Invalid address format, {0}. Ignoring...", nameAndAddr[1]); } } // Handle Object files (ones provided without load address) else if (nameAndAddr.Length == 1) { // If we still have not had a valid entry point set, then use entry point from // first encountered non-binary file in the inputFileNames list if (devAISGen.entryPoint == 0xFFFFFFFF) { devAISGen.InsertAISSecureObjectFile(nameAndAddr[0], true, false); } else { devAISGen.InsertAISSecureObjectFile(nameAndAddr[0], false, false); } } else { Console.WriteLine("WARNING: Invalid filename format, {0}. Ignoring...", fn); } } Debug.DebugMSG("Main input file insertion complete."); // Insert closing JumpClose AIS command (issue warning) if (devAISGen.entryPoint == 0x00000000) { Console.WriteLine("WARNING: Entry point set to null pointer!"); } devAISGen.InsertAISJumpClose(devAISGen.entryPoint); // Insert final Signature InsertAISSecureSignature(devAISGen); // Flush the data and then return to start devAISGen.devAISStream.Flush(); devAISGen.devAISStream.Seek(0,SeekOrigin.Begin); Console.WriteLine("AIS file generation was successful."); // --------------------------------------------------------- // ******************* END AIS GENERATION ****************** // --------------------------------------------------------- } #endregion // Now create return byte array based on AIS Stream data EndianBinaryReader tempAIS_br = new EndianBinaryReader(devAISGen.devAISStream,Endian.LittleEndian); numWords = ((UInt32)tempAIS_br.BaseStream.Length) >> 2; devAISGen.AISData = new Byte[numWords << 2]; //Each word converts to 4 binary bytes Debug.DebugMSG("Number of words in the stream is {0}", numWords); // Copy the data to the output Byte array for (UInt32 i = 0; i < numWords; i++) { BitConverter.GetBytes(tempAIS_br.ReadUInt32()).CopyTo(devAISGen.AISData, i * 4); } // Close the binary reader tempAIS_br.Close(); } // Dispose of all object files foreach (ObjectFile file in devAISGen.objectFiles) { try { file.Dispose(); } catch (Exception e) { Console.WriteLine(e.Message); } } // Clean up any embedded file resources that may have been extracted EmbeddedFileIO.CleanUpEmbeddedFiles(); // Return Byte Array return devAISGen.AISData; }