public void ReplaceFsbFileWithWav(DatItem item, string wavFilename)
{
string tempWadFn = string.Format("{0}_{1}", _wadFilename, Guid.NewGuid().ToString("N"));
byte[] buff;
int filenameLen = 30;
uint fileSize = 0;
int diff;
//save WAD to temp file
using (FileStream fso = File.OpenWrite(tempWadFn))
{
using (FileStream fsi = File.OpenRead(_wadFilename))
{
if (item.FileOffset != 0)
copy(fsi, fso, item.FileOffset);
using (FileStream fs = File.OpenRead(wavFilename))
{
//not fully correct for XBADPCM
WavSingleChunkHeader wh = WavProcessor.ParseWavSingleChunkHeader(fs);
long p = fso.Position;
BinaryEndianWriter bw = new BinaryEndianWriter(fso);
byte[] fsbFilename = new byte[filenameLen];
//http://www.fmod.org/forum/viewtopic.php?t=1551
//FileHeader
bw.Write(Encoding.Default.GetBytes("FSB3"));
bw.Write((uint)1, EndianType.Little); //1 sample in file
bw.Write((uint)80, EndianType.Little); //sampleheader length
bw.Write(wh.ChunkLength, EndianType.Little); //sampleheader length
bw.Write((uint)0x00030001, EndianType.Little); //header version 3.1
bw.Write((uint)0, EndianType.Little); //global mode flags
//p = fso.Position;
//SampleHeader (80 byte version)
bw.Write((UInt16)80, EndianType.Little); //sampleheader length
fsi.Seek(24 + 2, SeekOrigin.Current); //skip the start of the source fsb file name
fsi.Read(fsbFilename, 0, filenameLen); //read filename from file being replaced
bw.Write(fsbFilename); //write filename
//sampleheader length (What's this about?)
uint lenSamp = (uint)Math.Round(((double)wh.SamplesPerSec / (double)wh.AvgBytesPerSec) * wh.ChunkLength);
if (lenSamp < 0xFA00)
lenSamp = 0xFA00; //set smallest allowed size? May be a memory allocation thing for FSB
bw.Write(lenSamp, EndianType.Little); //sampleheader length
bw.Write(wh.ChunkLength, EndianType.Little); //compressed bytes
bw.Write((uint)0x0, EndianType.Little); //loop start
bw.Write(lenSamp - 1, EndianType.Little); //loop end
bw.Write((uint)0x20400040, EndianType.Little); //sample mode
bw.Write(wh.SamplesPerSec, EndianType.Little); //frequency
bw.Write((ushort)0xFF, EndianType.Little); //default volume
bw.Write((ushort)0x0080, EndianType.Little); //default pan
bw.Write((ushort)0x0080, EndianType.Little); //default pri
bw.Write(wh.Channels, EndianType.Little); //channels
bw.Write((float)1, EndianType.Little); //min distance
bw.Write((float)10000, EndianType.Little); //max distance
bw.Write((uint)0x0, EndianType.Little); //varfreq
bw.Write((ushort)0x0, EndianType.Little); //varvol
bw.Write((ushort)0x0, EndianType.Little); //varpan
copy(fs, fso, wh.ChunkLength);
fileSize = (uint)(24 + 80 + wh.ChunkLength);
if (fileSize % DatWad.FileAlignment != 0)
{
buff = new byte[DatWad.FileAlignment - (fileSize % DatWad.FileAlignment)];
for (int i = 0; i < buff.Length; i++)
buff[i] = DatWad.FileAlignmentPadValue;
fso.Write(buff, 0, buff.Length);
}
//move past the rest of this file being replaced
long itemSize = item.FileSize;
if (item.FileSize % DatWad.FileAlignment != 0)
itemSize += (DatWad.FileAlignment - (item.FileSize % DatWad.FileAlignment));
if (itemSize < fsi.Length)
fsi.Seek(itemSize - (24 + 2 + filenameLen), SeekOrigin.Current);
}
diff = (int)(fso.Position - fsi.Position);
//copy the rest of the file
copy(fsi, fso, fsi.Length - fsi.Position);
}
fso.Flush();
}
//rename the temp wad file
FileHelper.Delete(_wadFilename);
//save dat headers
//int diff = (int)fileSize - (int)item.FileSize;
foreach (DatItem di in _datItems.Values)
{
if (di == item)
di.FileSize = fileSize;
else
di.FileOffset = (uint)((int)di.FileOffset + (di.FileOffset > item.FileOffset ? diff : 0));
}
_headerFileSize = (uint)((int)_headerFileSize + diff);
this.save();
File.Move(tempWadFn, _wadFilename);
}