EveryFileExplorer/NDS/NitroSystem/SND/SDAT.cs
Gericom f9f00d193c Importing textures for bcmdl is possible now
And some older stuff I didn't commit yet.
2015-11-03 16:18:38 +01:00

320 lines
9.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibEveryFileExplorer.Files;
using System.Drawing;
using System.IO;
using LibEveryFileExplorer.IO;
using LibEveryFileExplorer.IO.Serialization;
namespace NDS.NitroSystem.SND
{
public class SDAT : FileFormat<SDAT.SDATIdentifier>, IViewable
{
public SDAT(byte[] Data)
{
EndianBinaryReaderEx er = new EndianBinaryReaderEx(new MemoryStream(Data), Endianness.LittleEndian);
try
{
Header = new SDATHeader(er);
if (Header.SYMBOffset != 0 && Header.SYMBLength != 0)
{
er.BaseStream.Position = Header.SYMBOffset;
SymbolBlock = new SYMB(er);
}
er.BaseStream.Position = Header.INFOOffset;
InfoBlock = new INFO(er);
er.BaseStream.Position = Header.FATOffset;
FileAllocationTable = new FAT(er);
er.BaseStream.Position = Header.FILEOffset;
File = new FILE(er);
}
finally
{
er.Close();
}
}
public System.Windows.Forms.Form GetDialog()
{
return new System.Windows.Forms.Form();
}
public SDATHeader Header;
public class SDATHeader
{
public SDATHeader(EndianBinaryReaderEx er)
{
er.ReadObject(this);
/*Signature = er.ReadString(Encoding.ASCII, 4);
if (Signature != "SDAT") throw new SignatureNotCorrectException(Signature, "SDAT", er.BaseStream.Position - 4);
Endianness = er.ReadUInt16();
Version = er.ReadUInt16();
FileSize = er.ReadUInt32();
HeaderSize = er.ReadUInt16();
NrBlocks = er.ReadUInt16();
SYMBOffset = er.ReadUInt32();
SYMBLength = er.ReadUInt32();
INFOOffset = er.ReadUInt32();
INFOLength = er.ReadUInt32();
FATOffset = er.ReadUInt32();
FATLength = er.ReadUInt32();
FILEOffset = er.ReadUInt32();
FILELength = er.ReadUInt32();
Padding = er.ReadBytes(16);*/
}
[BinaryStringSignature("SDAT")]
[BinaryFixedSize(4)]
public String Signature;
[BinaryBOM(0xFFFE)]
public UInt16 Endianness;
public UInt16 Version;
public UInt32 FileSize;
public UInt16 HeaderSize;
public UInt16 NrBlocks;
public UInt32 SYMBOffset;
public UInt32 SYMBLength;
public UInt32 INFOOffset;
public UInt32 INFOLength;
public UInt32 FATOffset;
public UInt32 FATLength;
public UInt32 FILEOffset;
public UInt32 FILELength;
[BinaryFixedSize(16)]
public byte[] Padding;//16
}
public SYMB SymbolBlock;
public class SYMB
{
public SYMB(EndianBinaryReader er)
{
long baseoffset = er.BaseStream.Position;
Signature = er.ReadString(Encoding.ASCII, 4);
if (Signature != "SYMB") throw new SignatureNotCorrectException(Signature, "SYMB", er.BaseStream.Position - 4);
SectionSize = er.ReadUInt32();
RecordOffsets = er.ReadUInt32s(8);
Padding = er.ReadBytes(24);
long curpos = er.BaseStream.Position;
er.BaseStream.Position = baseoffset + RecordOffsets[0];
SEQRecord = new SymbolRecord(er);
er.BaseStream.Position = baseoffset + RecordOffsets[1];
SEQARCRecord = new ArchiveSymbolRecord(er);
er.BaseStream.Position = baseoffset + RecordOffsets[2];
BANKRecord = new SymbolRecord(er);
er.BaseStream.Position = baseoffset + RecordOffsets[3];
WAVEARCRecord = new SymbolRecord(er);
er.BaseStream.Position = baseoffset + RecordOffsets[4];
PLAYERRecord = new SymbolRecord(er);
er.BaseStream.Position = baseoffset + RecordOffsets[5];
GROUPRecord = new SymbolRecord(er);
er.BaseStream.Position = baseoffset + RecordOffsets[6];
PLAYER2Record = new SymbolRecord(er);
er.BaseStream.Position = baseoffset + RecordOffsets[7];
STRMRecord = new SymbolRecord(er);
er.BaseStream.Position = curpos;
SEQRecord.ReadNames(er, baseoffset);
SEQARCRecord.ReadNames(er, baseoffset);
BANKRecord.ReadNames(er, baseoffset);
WAVEARCRecord.ReadNames(er, baseoffset);
PLAYERRecord.ReadNames(er, baseoffset);
GROUPRecord.ReadNames(er, baseoffset);
PLAYER2Record.ReadNames(er, baseoffset);
STRMRecord.ReadNames(er, baseoffset);
er.BaseStream.Position = baseoffset + SectionSize;
}
public String Signature;
public UInt32 SectionSize;
public UInt32[] RecordOffsets;
public Byte[] Padding;
public SymbolRecord SEQRecord;
public ArchiveSymbolRecord SEQARCRecord;
public SymbolRecord BANKRecord;
public SymbolRecord WAVEARCRecord;
public SymbolRecord PLAYERRecord;
public SymbolRecord GROUPRecord;
public SymbolRecord PLAYER2Record;
public SymbolRecord STRMRecord;
public class SymbolRecord
{
public SymbolRecord(EndianBinaryReader er)
{
NrEntries = er.ReadUInt32();
EntryOffsets = er.ReadUInt32s((int)NrEntries);
}
public UInt32 NrEntries;
public UInt32[] EntryOffsets;
public String[] Entries;
public void ReadNames(EndianBinaryReader er, long BaseOffset)
{
long curpos = er.BaseStream.Position;
Entries = new string[NrEntries];
for (int i = 0; i < NrEntries; i++)
{
if (EntryOffsets[i] != 0)
{
er.BaseStream.Position = BaseOffset + EntryOffsets[i];
Entries[i] = er.ReadStringNT(Encoding.ASCII);
}
else Entries[i] = "Entry " + i;
}
er.BaseStream.Position = curpos;
}
}
public class ArchiveSymbolRecord
{
public ArchiveSymbolRecord(EndianBinaryReader er)
{
NrEntries = er.ReadUInt32();
Entries = new ArchiveSymbolRecordEntry[NrEntries];
for (int i = 0; i < NrEntries; i++)
{
Entries[i] = new ArchiveSymbolRecordEntry(er);
}
}
public UInt32 NrEntries;
public ArchiveSymbolRecordEntry[] Entries;
public class ArchiveSymbolRecordEntry
{
public ArchiveSymbolRecordEntry(EndianBinaryReader er)
{
ArchiveNameOffset = er.ReadUInt32();
ArchiveSubRecordOffset = er.ReadUInt32();
}
public UInt32 ArchiveNameOffset;
public UInt32 ArchiveSubRecordOffset;
public String ArchiveName;
public SymbolRecord ArchiveSubRecord;
}
public void ReadNames(EndianBinaryReader er, long BaseOffset)
{
long curpos = er.BaseStream.Position;
for (int i = 0; i < NrEntries; i++)
{
if (Entries[i].ArchiveNameOffset != 0)
{
er.BaseStream.Position = BaseOffset + Entries[i].ArchiveNameOffset;
Entries[i].ArchiveName = er.ReadStringNT(Encoding.ASCII);
}
else Entries[i].ArchiveName = "Entry_" + i;
er.BaseStream.Position = BaseOffset + Entries[i].ArchiveSubRecordOffset;
Entries[i].ArchiveSubRecord = new SymbolRecord(er);
Entries[i].ArchiveSubRecord.ReadNames(er, BaseOffset);
}
er.BaseStream.Position = curpos;
}
}
}
public INFO InfoBlock;
public class INFO
{
public INFO(EndianBinaryReader er)
{
long baseoffset = er.BaseStream.Position;
Signature = er.ReadString(Encoding.ASCII, 4);
if (Signature != "INFO") throw new SignatureNotCorrectException(Signature, "INFO", er.BaseStream.Position - 4);
SectionSize = er.ReadUInt32();
RecordOffsets = er.ReadUInt32s(8);
Padding = er.ReadBytes(24);
//TODO
er.BaseStream.Position = baseoffset + SectionSize;
}
public String Signature;
public UInt32 SectionSize;
public UInt32[] RecordOffsets;
public Byte[] Padding;
}
public FAT FileAllocationTable;
public class FAT
{
public FAT(EndianBinaryReader er)
{
long baseoffset = er.BaseStream.Position;
Signature = er.ReadString(Encoding.ASCII, 4);
if (Signature != "FAT ") throw new SignatureNotCorrectException(Signature, "FAT ", er.BaseStream.Position - 4);
SectionSize = er.ReadUInt32();
NrEntries = er.ReadUInt32();
Entries = new FATEntry[NrEntries];
for (int i = 0; i < NrEntries; i++)
{
Entries[i] = new FATEntry(er);
}
er.BaseStream.Position = baseoffset + SectionSize;
}
public String Signature;
public UInt32 SectionSize;
public UInt32 NrEntries;
public FATEntry[] Entries;
public class FATEntry
{
public FATEntry(EndianBinaryReader er)
{
Offset = er.ReadUInt32();
Length = er.ReadUInt32();
Padding = er.ReadBytes(8);
}
public UInt32 Offset;
public UInt32 Length;
public Byte[] Padding;//8
}
}
public FILE File;
public class FILE
{
public FILE(EndianBinaryReader er)
{
long baseoffset = er.BaseStream.Position;
Signature = er.ReadString(Encoding.ASCII, 4);
if (Signature != "FILE") throw new SignatureNotCorrectException(Signature, "FILE", er.BaseStream.Position - 4);
SectionSize = er.ReadUInt32();
NrFiles = er.ReadUInt32();
while ((er.BaseStream.Position % 32) != 0) er.ReadByte();
FileData = er.ReadBytes((int)(baseoffset + SectionSize - er.BaseStream.Position));
er.BaseStream.Position = baseoffset + SectionSize;
}
public String Signature;
public UInt32 SectionSize;
public UInt32 NrFiles;
public Byte[] FileData;
}
public class SDATIdentifier : FileFormatIdentifier
{
public override string GetCategory()
{
return Category_Archives;
}
public override string GetFileDescription()
{
return "Nitro Sound Data (SDAT)";
}
public override string GetFileFilter()
{
return "Nitro Sound Data (*.sdat)|*.sdat";
}
public override Bitmap GetIcon()
{
return null;
}
public override FormatMatch IsFormat(EFEFile File)
{
if (File.Data.Length > 4 && File.Data[0] == 'S' && File.Data[1] == 'D' && File.Data[2] == 'A' && File.Data[3] == 'T') return FormatMatch.Content;
return FormatMatch.No;
}
}
}
}