public void SaveFile(string filename) { // Sort the values before we save them to the sfo file _values.Sort(); using (FileStream stream = File.Create(filename)) { using (StructWriter sw = new StructWriter(ByteOrder.LSB, stream)) { INDEX_TABLE_ENTRY[] indexes = new INDEX_TABLE_ENTRY[_values.Count]; string[] variablenames = new string[_values.Count]; int curkeynameoffset = 0; uint curvalueoffset = 0; for (int idx = 0; idx < _values.Count; idx++) { SFOValue value = _values[idx]; DATA_TYPE datatype = DATA_TYPE.BinaryData; uint datasize = 0; switch (value.ValueType) { case SFOType.Binary: { datatype = DATA_TYPE.BinaryData; datasize = (uint)value.ValueBinary.Length; break; } case SFOType.Int: { datatype = DATA_TYPE.Si32Integer; datasize = 4; break; } case SFOType.Text: { datatype = DATA_TYPE.Utf8Text; datasize = (uint)Encoding.UTF8.GetBytes(value.ValueString).Length + 1; break; } default: { throw new Exception("Unknown SFOType!"); } } indexes[idx].KeyNameOffset = (ushort)curkeynameoffset; indexes[idx].Unknown = 4; indexes[idx].DataType = datatype; indexes[idx].ValueDataSize = datasize; indexes[idx].ValueDataSizePlusPadding = GetPaddingSize(value.KeyName, datasize); indexes[idx].DataValueOffset = curvalueoffset; variablenames[idx] = value.KeyName; curkeynameoffset += value.KeyName.Length + 1; curvalueoffset += indexes[idx].ValueDataSizePlusPadding; } SFO_HEADER sfoheader = new SFO_HEADER(); sfoheader.magic = 0; sfoheader.signature = new char[] { 'P', 'S', 'F' }; sfoheader.FileVersionHigh = 1; sfoheader.FileVersionLow = 1; sfoheader.Unknown1 = 0; sfoheader.Start_of_Variable_Name_Table = PadOffset(Marshal.SizeOf(sfoheader) + (indexes.Length * Marshal.SizeOf(typeof(INDEX_TABLE_ENTRY)))); sfoheader.Start_of_Variable_Data_Table = PadOffset(sfoheader.Start_of_Variable_Name_Table + curkeynameoffset); sfoheader.NumberOfVariables = (uint)_values.Count; sw.WriteStruct(sfoheader); // Write variable information... sw.WriteStructs <INDEX_TABLE_ENTRY>(indexes); WritePadBytes(sw, sw.BaseStream.Position, sfoheader.Start_of_Variable_Name_Table); // Write variable names... sw.WriteStrings(StringType.NullTerminated, variablenames); WritePadBytes(sw, sw.BaseStream.Position, sfoheader.Start_of_Variable_Data_Table); // Write variable data... for (int idx = 0; idx < _values.Count; idx++) { SFOValue value = _values[idx]; switch (value.ValueType) { case SFOType.Binary: { sw.Write(value.ValueBinary); break; } case SFOType.Int: { sw.Write((Int32)value.ValueInt); break; } case SFOType.Text: { sw.WriteString(StringType.NullTerminated, value.ValueString); break; } } long pos = sw.BaseStream.Position; WritePadBytes(sw, indexes[idx].ValueDataSize, indexes[idx].ValueDataSizePlusPadding); } } } }
public void SaveFile(PARAM_SFO psfo, string filename) { // Sort the values before we save them to the sfo file //Array.Sort(psfo.Tables); using (FileStream stream = File.Create(filename)) { using (StructWriter sw = new StructWriter(ByteOrder.LSB, stream)) { //build index table INDEX_TABLE_ENTRY[] indexes = new INDEX_TABLE_ENTRY[psfo.Tables.Length]; PARAM_SFO.Table[] mytables = psfo.Tables; PARAM_SFO.index_table[] myindexes = new index_table[psfo.Tables.Length]; string[] variablenames = new string[psfo.Tables.Length]; string[] variablevalues = new string[psfo.Tables.Length]; int curkeynameoffset = 0; uint curvalueoffset = 0; for (int idx = 0; idx < psfo.Tables.Length; idx++) { PARAM_SFO.Table value = psfo.Tables[idx]; PARAM_SFO.FMT datatype = FMT.UINT32; uint datasize = 0; switch (value.Indextable.param_data_fmt) { case FMT.ASCII: { datatype = FMT.ASCII; datasize = (uint)Encoding.UTF8.GetBytes(value.Value.ToString()).Length + 1; break; } case FMT.UINT32: { datatype = FMT.UINT32; datasize = 4; break; } case FMT.UTF_8: { datatype = FMT.UTF_8; datasize = (uint)Encoding.UTF8.GetBytes(value.Value.ToString()).Length + 1; break; } default: { throw new Exception("Unknown SFOType!"); } } if (value.Indextable.param_key_offset != (ushort)curkeynameoffset) { string breakpoint = "This is for debug testing"; } //value.Indextable.param_key_offset = (ushort)curkeynameoffset; if (value.Indextable.param_data_fmt != datatype) { string breakpoint = "This is for debug testing"; } //value.Indextable.param_data_fmt = datatype; if (value.Indextable.param_data_len != datasize) { string breakpoint = "This is for debug testing"; } //value.Indextable.param_data_len = datasize; //if (value.Indextable.param_data_max_len != GetPaddingSize(value.Name, datasize)) //{ // string breakpoint = "This is for debug testing"; //} //value.Indextable.param_data_max_len = GetPaddingSize(value.Name, datasize); if (value.Indextable.param_data_offset != curvalueoffset) { string breakpoint = "This is for debug testing"; } //value.Indextable.param_data_offset = curvalueoffset; //we already have all the keynames curvalueoffset += value.Indextable.param_data_max_len; indexes[idx].KeyNameOffset = (ushort)curkeynameoffset; indexes[idx].Unknown = 4; if (datatype == FMT.UTF_8) { indexes[idx].DataType = DATA_TYPE.BinaryData; } if (datatype == FMT.ASCII) { indexes[idx].DataType = DATA_TYPE.Utf8Text; } if (datatype == FMT.UINT32) { indexes[idx].DataType = DATA_TYPE.Si32Integer; } indexes[idx].ValueDataSize = datasize; indexes[idx].ValueDataSizePlusPadding = GetPaddingSize(value.Name, datasize); indexes[idx].DataValueOffset = curvalueoffset; curkeynameoffset += value.Name.Length + 1; variablenames[idx] = value.Name; myindexes[idx] = value.Indextable; variablevalues[idx] = value.Value; } SFO_HEADER sfoheader = new SFO_HEADER(); sfoheader.magic = 0; sfoheader.signature = new char[] { 'P', 'S', 'F' }; sfoheader.FileVersionHigh = 1; sfoheader.FileVersionLow = 1; sfoheader.Unknown1 = 0; sfoheader.Start_of_Variable_Name_Table = Header.KeyTableStart; //PadOffset(Marshal.SizeOf(sfoheader) + (psfo.Tables.Length * Marshal.SizeOf(typeof(PARAM_SFO.index_table))));// sfoheader.Start_of_Variable_Data_Table = Header.DataTableStart; //PadOffset(sfoheader.Start_of_Variable_Name_Table + curkeynameoffset);// sfoheader.NumberOfVariables = Header.IndexTableEntries; //(uint)psfo.Tables.Length;// sw.WriteStruct(sfoheader); // Write variable information... sw.WriteStructs(indexes); WritePadBytes(sw, sw.BaseStream.Position, sfoheader.Start_of_Variable_Name_Table); // Write variable names... sw.WriteStrings(StringType.NullTerminated, variablenames); WritePadBytes(sw, sw.BaseStream.Position, sfoheader.Start_of_Variable_Data_Table); // Write variable data... for (int idx = 0; idx < psfo.Tables.Length; idx++) { PARAM_SFO.Table value = psfo.Tables[idx]; switch (value.Indextable.param_data_fmt) { case FMT.UTF_8: { sw.Write(value.Value); break; } case FMT.UINT32: { sw.Write(Convert.ToUInt32(value.Value)); break; } case FMT.ASCII: { sw.Write(value.Value); break; } } long pos = sw.BaseStream.Position; WritePadBytes(sw, myindexes[idx].param_data_len, myindexes[idx].param_data_max_len); } } } }