mirror of
https://github.com/blueskythlikesclouds/SonicAudioTools.git
synced 2024-11-27 17:00:53 +01:00
Support for Sonic Forces
This commit is contained in:
parent
218f1b8f37
commit
86a218f630
BIN
Dependencies/vgmstream.dll
vendored
BIN
Dependencies/vgmstream.dll
vendored
Binary file not shown.
@ -22,7 +22,7 @@ namespace AcbEditor
|
|||||||
Settings.Default.Reset();
|
Settings.Default.Reset();
|
||||||
Settings.Default.Save();
|
Settings.Default.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.Length < 1)
|
if (args.Length < 1)
|
||||||
{
|
{
|
||||||
Console.WriteLine(Resources.Description);
|
Console.WriteLine(Resources.Description);
|
||||||
@ -32,283 +32,316 @@ namespace AcbEditor
|
|||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
if (args[0].EndsWith(".acb"))
|
if (args[0].EndsWith(".acb"))
|
||||||
|
{
|
||||||
|
var extractor = new DataExtractor();
|
||||||
|
extractor.ProgressChanged += OnProgressChanged;
|
||||||
|
|
||||||
|
extractor.BufferSize = Settings.Default.BufferSize;
|
||||||
|
extractor.EnableThreading = Settings.Default.EnableThreading;
|
||||||
|
extractor.MaxThreads = Settings.Default.MaxThreads;
|
||||||
|
|
||||||
|
string baseDirectory = Path.GetDirectoryName(args[0]);
|
||||||
|
string outputDirectoryPath = Path.ChangeExtension(args[0], null);
|
||||||
|
string extAfs2ArchivePath = string.Empty;
|
||||||
|
|
||||||
|
Directory.CreateDirectory(outputDirectoryPath);
|
||||||
|
|
||||||
|
using (CriTableReader acbReader = CriTableReader.Create(args[0]))
|
||||||
{
|
{
|
||||||
var extractor = new DataExtractor();
|
acbReader.Read();
|
||||||
extractor.ProgressChanged += OnProgressChanged;
|
|
||||||
|
|
||||||
extractor.BufferSize = Settings.Default.BufferSize;
|
|
||||||
extractor.EnableThreading = Settings.Default.EnableThreading;
|
|
||||||
extractor.MaxThreads = Settings.Default.MaxThreads;
|
|
||||||
|
|
||||||
string baseDirectory = Path.GetDirectoryName(args[0]);
|
|
||||||
string outputDirectoryPath = Path.ChangeExtension(args[0], null);
|
|
||||||
string extAfs2ArchivePath = string.Empty;
|
|
||||||
|
|
||||||
Directory.CreateDirectory(outputDirectoryPath);
|
|
||||||
|
|
||||||
using (CriTableReader acbReader = CriTableReader.Create(args[0]))
|
|
||||||
{
|
|
||||||
acbReader.Read();
|
|
||||||
|
|
||||||
CriAfs2Archive afs2Archive = new CriAfs2Archive();
|
|
||||||
CriAfs2Archive extAfs2Archive = new CriAfs2Archive();
|
|
||||||
|
|
||||||
CriCpkArchive cpkArchive = new CriCpkArchive();
|
|
||||||
CriCpkArchive extCpkArchive = null;
|
|
||||||
|
|
||||||
extAfs2ArchivePath = outputDirectoryPath + ".awb";
|
|
||||||
bool found = File.Exists(extAfs2ArchivePath);
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
extAfs2ArchivePath = outputDirectoryPath + "_streamfiles.awb";
|
|
||||||
found = File.Exists(extAfs2ArchivePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
extAfs2ArchivePath = outputDirectoryPath + "_STR.awb";
|
|
||||||
found = File.Exists(extAfs2ArchivePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cpkMode = true;
|
|
||||||
|
|
||||||
long awbPosition = acbReader.GetPosition("AwbFile");
|
|
||||||
if (acbReader.GetLength("AwbFile") > 0)
|
|
||||||
{
|
|
||||||
using (SubStream afs2Stream = acbReader.GetSubStream("AwbFile"))
|
|
||||||
{
|
|
||||||
cpkMode = !CheckIfAfs2(afs2Stream);
|
|
||||||
|
|
||||||
if (cpkMode)
|
|
||||||
{
|
|
||||||
cpkArchive.Read(afs2Stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
afs2Archive.Read(afs2Stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (acbReader.GetLength("StreamAwbAfs2Header") > 0)
|
|
||||||
{
|
|
||||||
cpkMode = false;
|
|
||||||
|
|
||||||
using (SubStream extAfs2Stream = acbReader.GetSubStream("StreamAwbAfs2Header"))
|
|
||||||
{
|
|
||||||
extAfs2Archive.Read(extAfs2Stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
throw new FileNotFoundException("Cannot find the external .AWB file for this .ACB file. Please ensure that the external .AWB file is stored in the directory where the .ACB file is.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SubStream waveformTableStream = acbReader.GetSubStream("WaveformTable"))
|
|
||||||
using (CriTableReader waveformReader = CriTableReader.Create(waveformTableStream))
|
|
||||||
{
|
|
||||||
while (waveformReader.Read())
|
|
||||||
{
|
|
||||||
ushort id = waveformReader.GetUInt16("Id");
|
|
||||||
byte encodeType = waveformReader.GetByte("EncodeType");
|
|
||||||
bool streaming = waveformReader.GetBoolean("Streaming");
|
|
||||||
|
|
||||||
string outputName = id.ToString("D5");
|
|
||||||
if (streaming)
|
|
||||||
{
|
|
||||||
outputName += "_streaming";
|
|
||||||
}
|
|
||||||
|
|
||||||
outputName += GetExtension(encodeType);
|
|
||||||
outputName = Path.Combine(outputDirectoryPath, outputName);
|
|
||||||
|
|
||||||
if (streaming)
|
|
||||||
{
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
throw new Exception("Cannot find the external .AWB file for this .ACB file. Please ensure that the external .AWB file is stored in the directory where the .ACB file is.");
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (extCpkArchive == null && cpkMode)
|
|
||||||
{
|
|
||||||
extCpkArchive = new CriCpkArchive();
|
|
||||||
extCpkArchive.Load(extAfs2ArchivePath, Settings.Default.BufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
EntryBase afs2Entry = null;
|
|
||||||
|
|
||||||
if (cpkMode)
|
|
||||||
{
|
|
||||||
afs2Entry = extCpkArchive.GetById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
afs2Entry = extAfs2Archive.GetById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
extractor.Add(extAfs2ArchivePath, outputName, afs2Entry.Position, afs2Entry.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EntryBase afs2Entry = null;
|
|
||||||
|
|
||||||
if (cpkMode)
|
|
||||||
{
|
|
||||||
afs2Entry = cpkArchive.GetById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
afs2Entry = afs2Archive.GetById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
extractor.Add(args[0], outputName, awbPosition + afs2Entry.Position, afs2Entry.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extractor.Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (File.GetAttributes(args[0]).HasFlag(FileAttributes.Directory))
|
|
||||||
{
|
|
||||||
string baseDirectory = Path.GetDirectoryName(args[0]);
|
|
||||||
string acbPath = args[0] + ".acb";
|
|
||||||
|
|
||||||
string awbPath = args[0] + "_streamfiles.awb";
|
|
||||||
bool found = File.Exists(awbPath);
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
awbPath = args[0] + "_STR.awb";
|
|
||||||
found = File.Exists(awbPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
awbPath = args[0] + ".awb";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!File.Exists(acbPath))
|
|
||||||
{
|
|
||||||
throw new FileNotFoundException("Cannot find the .ACB file for this directory. Please ensure that the .ACB file is stored in the directory where this directory is.");
|
|
||||||
}
|
|
||||||
|
|
||||||
CriTable acbFile = new CriTable();
|
|
||||||
acbFile.Load(acbPath, Settings.Default.BufferSize);
|
|
||||||
|
|
||||||
CriAfs2Archive afs2Archive = new CriAfs2Archive();
|
CriAfs2Archive afs2Archive = new CriAfs2Archive();
|
||||||
CriAfs2Archive extAfs2Archive = new CriAfs2Archive();
|
CriAfs2Archive extAfs2Archive = new CriAfs2Archive();
|
||||||
|
|
||||||
CriCpkArchive cpkArchive = new CriCpkArchive();
|
CriCpkArchive cpkArchive = new CriCpkArchive();
|
||||||
CriCpkArchive extCpkArchive = new CriCpkArchive();
|
CriCpkArchive extCpkArchive = null;
|
||||||
cpkArchive.Mode = extCpkArchive.Mode = CriCpkMode.Id;
|
|
||||||
|
|
||||||
afs2Archive.ProgressChanged += OnProgressChanged;
|
extAfs2ArchivePath = outputDirectoryPath + ".awb";
|
||||||
extAfs2Archive.ProgressChanged += OnProgressChanged;
|
bool found = File.Exists(extAfs2ArchivePath);
|
||||||
cpkArchive.ProgressChanged += OnProgressChanged;
|
|
||||||
extCpkArchive.ProgressChanged += OnProgressChanged;
|
if (!found)
|
||||||
|
{
|
||||||
|
extAfs2ArchivePath = outputDirectoryPath + "_streamfiles.awb";
|
||||||
|
found = File.Exists(extAfs2ArchivePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
extAfs2ArchivePath = outputDirectoryPath + "_STR.awb";
|
||||||
|
found = File.Exists(extAfs2ArchivePath);
|
||||||
|
}
|
||||||
|
|
||||||
bool cpkMode = true;
|
bool cpkMode = true;
|
||||||
|
|
||||||
byte[] awbFile = (byte[])acbFile.Rows[0]["AwbFile"];
|
long awbPosition = acbReader.GetPosition("AwbFile");
|
||||||
byte[] streamAwbAfs2Header = (byte[])acbFile.Rows[0]["StreamAwbAfs2Header"];
|
if (acbReader.GetLength("AwbFile") > 0)
|
||||||
|
|
||||||
cpkMode = !(awbFile != null && awbFile.Length >= 4 && Encoding.ASCII.GetString(awbFile, 0, 4) == "AFS2") && (streamAwbAfs2Header == null || streamAwbAfs2Header.Length == 0);
|
|
||||||
|
|
||||||
using (CriTableReader reader = CriTableReader.Create((byte[])acbFile.Rows[0]["WaveformTable"]))
|
|
||||||
{
|
{
|
||||||
while (reader.Read())
|
using (SubStream afs2Stream = acbReader.GetSubStream("AwbFile"))
|
||||||
{
|
{
|
||||||
ushort id = reader.GetUInt16("Id");
|
cpkMode = !CheckIfAfs2(afs2Stream);
|
||||||
byte encodeType = reader.GetByte("EncodeType");
|
|
||||||
bool streaming = reader.GetBoolean("Streaming");
|
|
||||||
|
|
||||||
string inputName = id.ToString("D5");
|
|
||||||
if (streaming)
|
|
||||||
{
|
|
||||||
inputName += "_streaming";
|
|
||||||
}
|
|
||||||
|
|
||||||
inputName += GetExtension(encodeType);
|
|
||||||
inputName = Path.Combine(args[0], inputName);
|
|
||||||
|
|
||||||
if (!File.Exists(inputName))
|
|
||||||
{
|
|
||||||
throw new FileNotFoundException($"Cannot find audio file with id {id} for replacement.\nPath attempt: {inputName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cpkMode)
|
if (cpkMode)
|
||||||
{
|
{
|
||||||
CriCpkEntry entry = new CriCpkEntry();
|
cpkArchive.Read(afs2Stream);
|
||||||
entry.FilePath = new FileInfo(inputName);
|
}
|
||||||
entry.Id = id;
|
|
||||||
|
|
||||||
if (streaming)
|
else
|
||||||
{
|
{
|
||||||
extCpkArchive.Add(entry);
|
afs2Archive.Read(afs2Stream);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else
|
if (acbReader.GetLength("StreamAwbAfs2Header") > 0)
|
||||||
|
{
|
||||||
|
cpkMode = false;
|
||||||
|
|
||||||
|
using (SubStream extAfs2Stream = acbReader.GetSubStream("StreamAwbAfs2Header"))
|
||||||
|
{
|
||||||
|
bool utfMode = DataStream.ReadCString(extAfs2Stream, 4) == "@UTF";
|
||||||
|
extAfs2Stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
if (utfMode)
|
||||||
|
{
|
||||||
|
using (CriTableReader utfAfs2HeaderReader = CriTableReader.Create(extAfs2Stream))
|
||||||
{
|
{
|
||||||
cpkArchive.Add(entry);
|
utfAfs2HeaderReader.Read();
|
||||||
|
|
||||||
|
using (SubStream extAfs2HeaderStream = utfAfs2HeaderReader.GetSubStream("Header"))
|
||||||
|
{
|
||||||
|
extAfs2Archive.Read(extAfs2HeaderStream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CriAfs2Entry entry = new CriAfs2Entry();
|
extAfs2Archive.Read(extAfs2Stream);
|
||||||
entry.FilePath = new FileInfo(inputName);
|
}
|
||||||
entry.Id = id;
|
}
|
||||||
|
|
||||||
if (streaming)
|
if (!found)
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("Cannot find the external .AWB file for this .ACB file. Please ensure that the external .AWB file is stored in the directory where the .ACB file is.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (SubStream waveformTableStream = acbReader.GetSubStream("WaveformTable"))
|
||||||
|
using (CriTableReader waveformReader = CriTableReader.Create(waveformTableStream))
|
||||||
|
{
|
||||||
|
while (waveformReader.Read())
|
||||||
|
{
|
||||||
|
ushort id = waveformReader.GetUInt16("Id");
|
||||||
|
byte encodeType = waveformReader.GetByte("EncodeType");
|
||||||
|
bool streaming = waveformReader.GetBoolean("Streaming");
|
||||||
|
|
||||||
|
string outputName = id.ToString("D5");
|
||||||
|
if (streaming)
|
||||||
|
{
|
||||||
|
outputName += "_streaming";
|
||||||
|
}
|
||||||
|
|
||||||
|
outputName += GetExtension(encodeType);
|
||||||
|
outputName = Path.Combine(outputDirectoryPath, outputName);
|
||||||
|
|
||||||
|
if (streaming)
|
||||||
|
{
|
||||||
|
if (!found)
|
||||||
{
|
{
|
||||||
extAfs2Archive.Add(entry);
|
throw new Exception("Cannot find the external .AWB file for this .ACB file. Please ensure that the external .AWB file is stored in the directory where the .ACB file is.");
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (extCpkArchive == null && cpkMode)
|
||||||
|
{
|
||||||
|
extCpkArchive = new CriCpkArchive();
|
||||||
|
extCpkArchive.Load(extAfs2ArchivePath, Settings.Default.BufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntryBase afs2Entry = null;
|
||||||
|
|
||||||
|
if (cpkMode)
|
||||||
|
{
|
||||||
|
afs2Entry = extCpkArchive.GetById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
afs2Archive.Add(entry);
|
afs2Entry = extAfs2Archive.GetById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extractor.Add(extAfs2ArchivePath, outputName, afs2Entry.Position, afs2Entry.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EntryBase afs2Entry = null;
|
||||||
|
|
||||||
|
if (cpkMode)
|
||||||
|
{
|
||||||
|
afs2Entry = cpkArchive.GetById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
afs2Entry = afs2Archive.GetById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
extractor.Add(args[0], outputName, awbPosition + afs2Entry.Position, afs2Entry.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
acbFile.Rows[0]["AwbFile"] = null;
|
extractor.Run();
|
||||||
acbFile.Rows[0]["StreamAwbAfs2Header"] = null;
|
}
|
||||||
|
|
||||||
if (afs2Archive.Count > 0 || cpkArchive.Count > 0)
|
else if (File.GetAttributes(args[0]).HasFlag(FileAttributes.Directory))
|
||||||
|
{
|
||||||
|
string baseDirectory = Path.GetDirectoryName(args[0]);
|
||||||
|
string acbPath = args[0] + ".acb";
|
||||||
|
|
||||||
|
string awbPath = args[0] + "_streamfiles.awb";
|
||||||
|
bool found = File.Exists(awbPath);
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
awbPath = args[0] + "_STR.awb";
|
||||||
|
found = File.Exists(awbPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
awbPath = args[0] + ".awb";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(acbPath))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("Cannot find the .ACB file for this directory. Please ensure that the .ACB file is stored in the directory where this directory is.");
|
||||||
|
}
|
||||||
|
|
||||||
|
CriTable acbFile = new CriTable();
|
||||||
|
acbFile.Load(acbPath, Settings.Default.BufferSize);
|
||||||
|
|
||||||
|
CriAfs2Archive afs2Archive = new CriAfs2Archive();
|
||||||
|
CriAfs2Archive extAfs2Archive = new CriAfs2Archive();
|
||||||
|
|
||||||
|
CriCpkArchive cpkArchive = new CriCpkArchive();
|
||||||
|
CriCpkArchive extCpkArchive = new CriCpkArchive();
|
||||||
|
cpkArchive.Mode = extCpkArchive.Mode = CriCpkMode.Id;
|
||||||
|
|
||||||
|
afs2Archive.ProgressChanged += OnProgressChanged;
|
||||||
|
extAfs2Archive.ProgressChanged += OnProgressChanged;
|
||||||
|
cpkArchive.ProgressChanged += OnProgressChanged;
|
||||||
|
extCpkArchive.ProgressChanged += OnProgressChanged;
|
||||||
|
|
||||||
|
bool cpkMode = true;
|
||||||
|
|
||||||
|
byte[] awbFile = (byte[])acbFile.Rows[0]["AwbFile"];
|
||||||
|
byte[] streamAwbAfs2Header = (byte[])acbFile.Rows[0]["StreamAwbAfs2Header"];
|
||||||
|
|
||||||
|
cpkMode = !(awbFile != null && awbFile.Length >= 4 && Encoding.ASCII.GetString(awbFile, 0, 4) == "AFS2") && (streamAwbAfs2Header == null || streamAwbAfs2Header.Length == 0);
|
||||||
|
|
||||||
|
using (CriTableReader reader = CriTableReader.Create((byte[])acbFile.Rows[0]["WaveformTable"]))
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
Console.WriteLine("Saving internal AWB...");
|
ushort id = reader.GetUInt16("Id");
|
||||||
acbFile.Rows[0]["AwbFile"] = cpkMode ? cpkArchive.Save() : afs2Archive.Save();
|
byte encodeType = reader.GetByte("EncodeType");
|
||||||
Console.WriteLine();
|
bool streaming = reader.GetBoolean("Streaming");
|
||||||
}
|
|
||||||
|
string inputName = id.ToString("D5");
|
||||||
|
if (streaming)
|
||||||
|
{
|
||||||
|
inputName += "_streaming";
|
||||||
|
}
|
||||||
|
|
||||||
|
inputName += GetExtension(encodeType);
|
||||||
|
inputName = Path.Combine(args[0], inputName);
|
||||||
|
|
||||||
|
if (!File.Exists(inputName))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException($"Cannot find audio file with id {id} for replacement.\nPath attempt: {inputName}");
|
||||||
|
}
|
||||||
|
|
||||||
if (extAfs2Archive.Count > 0 || extCpkArchive.Count > 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Saving external AWB...");
|
|
||||||
if (cpkMode)
|
if (cpkMode)
|
||||||
{
|
{
|
||||||
extCpkArchive.Save(awbPath, Settings.Default.BufferSize);
|
CriCpkEntry entry = new CriCpkEntry();
|
||||||
|
entry.FilePath = new FileInfo(inputName);
|
||||||
|
entry.Id = id;
|
||||||
|
|
||||||
|
if (streaming)
|
||||||
|
{
|
||||||
|
extCpkArchive.Add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cpkArchive.Add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CriAfs2Entry entry = new CriAfs2Entry();
|
||||||
|
entry.FilePath = new FileInfo(inputName);
|
||||||
|
entry.Id = id;
|
||||||
|
|
||||||
|
if (streaming)
|
||||||
|
{
|
||||||
|
extAfs2Archive.Add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
afs2Archive.Add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
acbFile.Rows[0]["AwbFile"] = null;
|
||||||
|
acbFile.Rows[0]["StreamAwbAfs2Header"] = null;
|
||||||
|
|
||||||
|
if (afs2Archive.Count > 0 || cpkArchive.Count > 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Saving internal AWB...");
|
||||||
|
acbFile.Rows[0]["AwbFile"] = cpkMode ? cpkArchive.Save() : afs2Archive.Save();
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extAfs2Archive.Count > 0 || extCpkArchive.Count > 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Saving external AWB...");
|
||||||
|
if (cpkMode)
|
||||||
|
{
|
||||||
|
extCpkArchive.Save(awbPath, Settings.Default.BufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
extAfs2Archive.Save(awbPath, Settings.Default.BufferSize);
|
||||||
|
|
||||||
|
if (Encoding.UTF8.GetString(streamAwbAfs2Header, 0, 4) == "@UTF")
|
||||||
|
{
|
||||||
|
CriTable headerTable = new CriTable();
|
||||||
|
headerTable.Load(streamAwbAfs2Header);
|
||||||
|
|
||||||
|
headerTable.Rows[0]["Header"] = extAfs2Archive.Header;
|
||||||
|
headerTable.WriterSettings = CriTableWriterSettings.Adx2Settings;
|
||||||
|
acbFile.Rows[0]["StreamAwbAfs2Header"] = headerTable.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
extAfs2Archive.Save(awbPath, Settings.Default.BufferSize);
|
|
||||||
acbFile.Rows[0]["StreamAwbAfs2Header"] = extAfs2Archive.Header;
|
acbFile.Rows[0]["StreamAwbAfs2Header"] = extAfs2Archive.Header;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
acbFile.WriterSettings = CriTableWriterSettings.Adx2Settings;
|
acbFile.WriterSettings = CriTableWriterSettings.Adx2Settings;
|
||||||
acbFile.Save(acbPath, Settings.Default.BufferSize);
|
acbFile.Save(acbPath, Settings.Default.BufferSize);
|
||||||
}
|
}
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
}
|
}
|
||||||
|
@ -17,16 +17,6 @@ namespace CsbBuilder.Audio
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const string DllName = "vgmstream.dll";
|
public const string DllName = "vgmstream.dll";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Size of VGMSTREAM structure.
|
|
||||||
/// </summary>
|
|
||||||
public const int SizeOfVgmStream = 152;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Size of VGMSTREAMCHANNEL structure.
|
|
||||||
/// </summary>
|
|
||||||
public const int SizeOfVgmStreamChannel = 552;
|
|
||||||
|
|
||||||
#region VGMStream Exports
|
#region VGMStream Exports
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a VGMSTREAM from source file name by doing format detection and returns a usable pointer
|
/// Initializes a VGMSTREAM from source file name by doing format detection and returns a usable pointer
|
||||||
@ -165,15 +155,8 @@ namespace CsbBuilder.Audio
|
|||||||
/// Gets a pointer to the array of supported formats.
|
/// Gets a pointer to the array of supported formats.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DllImport(DllName, EntryPoint = "vgmstream_get_formats", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DllName, EntryPoint = "vgmstream_get_formats", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern IntPtr GetFormatsPtr();
|
public static extern IntPtr GetFormatsPtr(out int count);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the length of the format array.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[DllImport(DllName, EntryPoint = "vgmstream_get_formats_length", CallingConvention = CallingConvention.Cdecl)]
|
|
||||||
public static extern int GetFormatsLength();
|
|
||||||
|
|
||||||
[DllImport(DllName, EntryPoint = "get_vgmstream_coding_description", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DllName, EntryPoint = "get_vgmstream_coding_description", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern string GetCodingDescription(int codingEnumCode);
|
public static extern string GetCodingDescription(int codingEnumCode);
|
||||||
|
|
||||||
@ -189,28 +172,22 @@ namespace CsbBuilder.Audio
|
|||||||
/// Gets the sample count of a VGMSTREAM.
|
/// Gets the sample count of a VGMSTREAM.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static int GetSampleCount(IntPtr vgmstream)
|
[DllImport(DllName, EntryPoint = "get_vgmstream_sample_count", CallingConvention = CallingConvention.Cdecl)]
|
||||||
{
|
public static extern int GetSampleCount(IntPtr vgmstream);
|
||||||
return Marshal.ReadInt32(vgmstream);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the sample rate of a VGMSTREAM.
|
/// Gets the sample rate of a VGMSTREAM.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static int GetSampleRate(IntPtr vgmstream)
|
[DllImport(DllName, EntryPoint = "get_vgmstream_sample_rate", CallingConvention = CallingConvention.Cdecl)]
|
||||||
{
|
public static extern int GetSampleRate(IntPtr vgmstream);
|
||||||
return Marshal.ReadInt32(vgmstream, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the channel count of a VGMSTREAM.
|
/// Gets the channel count of a VGMSTREAM.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static int GetChannelCount(IntPtr vgmstream)
|
[DllImport(DllName, EntryPoint = "get_vgmstream_channels", CallingConvention = CallingConvention.Cdecl)]
|
||||||
{
|
public static extern int GetChannelCount(IntPtr vgmstream);
|
||||||
return Marshal.ReadInt32(vgmstream, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the absolute sample count of a VGMSTREAM.
|
/// Gets the absolute sample count of a VGMSTREAM.
|
||||||
@ -226,69 +203,50 @@ namespace CsbBuilder.Audio
|
|||||||
/// Gets the loop flag of a VGMSTREAM.
|
/// Gets the loop flag of a VGMSTREAM.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static bool GetLoopFlag(IntPtr vgmstream)
|
[DllImport(DllName, EntryPoint = "get_vgmstream_loop_flag", CallingConvention = CallingConvention.Cdecl)]
|
||||||
{
|
public static extern bool GetLoopFlag(IntPtr vgmstream);
|
||||||
return Marshal.ReadInt32(vgmstream, 28) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the loop flag of a VGMSTREAM.
|
/// Sets the loop flag of a VGMSTREAM.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static void SetLoopFlag(IntPtr vgmstream, bool value)
|
[DllImport(DllName, EntryPoint = "set_vgmstream_loop_flag", CallingConvention = CallingConvention.Cdecl)]
|
||||||
{
|
public static extern void SetLoopFlag(IntPtr vgmstream, bool value);
|
||||||
if (value && !GetLoopFlag(vgmstream))
|
|
||||||
{
|
|
||||||
Marshal.WriteIntPtr(vgmstream, 48, Marshal.AllocHGlobal(GetChannelCount(vgmstream) * SizeOfVgmStreamChannel));
|
|
||||||
}
|
|
||||||
|
|
||||||
Marshal.WriteInt32(vgmstream, 28, value ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the loop start sample of a VGMSTREAM.
|
/// Gets the loop start sample of a VGMSTREAM.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static int GetLoopStartSample(IntPtr vgmstream)
|
[DllImport(DllName, EntryPoint = "get_vgmstream_loop_start_sample", CallingConvention = CallingConvention.Cdecl)]
|
||||||
{
|
public static extern int GetLoopStartSample(IntPtr vgmstream);
|
||||||
return Marshal.ReadInt32(vgmstream, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the loop start sample of a VGMSTREAM.
|
/// Sets the loop start sample of a VGMSTREAM.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static void SetLoopStartSample(IntPtr vgmstream, int value)
|
[DllImport(DllName, EntryPoint = "set_vgmstream_loop_start_sample", CallingConvention = CallingConvention.Cdecl)]
|
||||||
{
|
public static extern void SetLoopStartSample(IntPtr vgmstream, int value);
|
||||||
Marshal.WriteInt32(vgmstream, 32, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the loop end sample of a VGMSTREAM.
|
/// Gets the loop end sample of a VGMSTREAM.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static int GetLoopEndSample(IntPtr vgmstream)
|
[DllImport(DllName, EntryPoint = "get_vgmstream_loop_end_sample", CallingConvention = CallingConvention.Cdecl)]
|
||||||
{
|
public static extern int GetLoopEndSample(IntPtr vgmstream);
|
||||||
return Marshal.ReadInt32(vgmstream, 36);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the loop end sample of a VGMSTREAM.
|
/// Sets the loop end sample of a VGMSTREAM.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static void SetLoopEndSample(IntPtr vgmstream, int value)
|
[DllImport(DllName, EntryPoint = "set_vgmstream_loop_end_sample", CallingConvention = CallingConvention.Cdecl)]
|
||||||
{
|
public static extern void SetLoopEndSample(IntPtr vgmstream, int value);
|
||||||
Marshal.WriteInt32(vgmstream, 36, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the current sample of a VGMSTREAM.
|
/// Gets the current sample of a VGMSTREAM.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static int GetCurrentSample(IntPtr vgmstream)
|
[DllImport(DllName, EntryPoint = "get_vgmstream_current_sample", CallingConvention = CallingConvention.Cdecl)]
|
||||||
{
|
public static extern int GetCurrentSample(IntPtr vgmstream);
|
||||||
return Marshal.ReadInt32(vgmstream, 52);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an array of supported formats.
|
/// Gets an array of supported formats.
|
||||||
@ -296,9 +254,9 @@ namespace CsbBuilder.Audio
|
|||||||
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
/// <param name="vgmstream">Pointer to VGMSTREAM.</param>
|
||||||
public static string[] GetFormats()
|
public static string[] GetFormats()
|
||||||
{
|
{
|
||||||
string[] formats = new string[GetFormatsLength()];
|
IntPtr ptr = GetFormatsPtr(out int count);
|
||||||
|
string[] formats = new string[count];
|
||||||
|
|
||||||
IntPtr ptr = GetFormatsPtr();
|
|
||||||
for (int i = 0; i < formats.Length; i++)
|
for (int i = 0; i < formats.Length; i++)
|
||||||
{
|
{
|
||||||
IntPtr stringPtr = Marshal.ReadIntPtr(ptr, i * IntPtr.Size);
|
IntPtr stringPtr = Marshal.ReadIntPtr(ptr, i * IntPtr.Size);
|
||||||
|
@ -47,7 +47,11 @@ namespace CsbBuilder
|
|||||||
private static void OnException(object sender, ThreadExceptionEventArgs e)
|
private static void OnException(object sender, ThreadExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
new ExceptionForm(e.Exception).ShowDialog();
|
new ExceptionForm(e.Exception).ShowDialog();
|
||||||
Application.Exit();
|
|
||||||
|
if (MessageBox.Show("Do you want to continue?", "CSB Builder", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.OK)
|
||||||
|
{
|
||||||
|
Application.Exit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,26 +21,6 @@ namespace SonicAudioCmd
|
|||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
using (Stream source = File.OpenRead(args[0]))
|
|
||||||
{
|
|
||||||
CriTableReader reader = CriTableReader.Create(source);
|
|
||||||
reader.MoveToRow(3);
|
|
||||||
|
|
||||||
long pos = reader.GetPosition("utf");
|
|
||||||
CriTableReader soundElementReader = reader.GetTableReader("utf");
|
|
||||||
|
|
||||||
while (soundElementReader.Read())
|
|
||||||
{
|
|
||||||
CriTable table = new CriTable();
|
|
||||||
table.Read(soundElementReader.GetSubStream("data"));
|
|
||||||
|
|
||||||
using (Stream output = File.Create(Path.GetFileName(soundElementReader.GetString("name") + "_" + table.Rows[0].GetValue<byte>("lpflg") + "_" + ".dsp")))
|
|
||||||
{
|
|
||||||
DataStream.WriteBytes(output, table.Rows[0].GetValue<byte[]>("header"));
|
|
||||||
DataStream.WriteBytes(output, table.Rows[0].GetValue<byte[]>("data"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace SonicAudioLib.CriMw
|
namespace SonicAudioLib.CriMw
|
||||||
{
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
struct CriTableHeader
|
struct CriTableHeader
|
||||||
{
|
{
|
||||||
public static readonly byte[] SignatureBytes = { 0x40, 0x55, 0x54, 0x46 };
|
public static readonly byte[] SignatureBytes = { 0x40, 0x55, 0x54, 0x46 };
|
||||||
@ -48,13 +50,14 @@ namespace SonicAudioLib.CriMw
|
|||||||
TypeMask = 15,
|
TypeMask = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
struct CriTableField
|
struct CriTableField
|
||||||
{
|
{
|
||||||
public uint Offset;
|
|
||||||
public CriFieldFlag Flag;
|
public CriFieldFlag Flag;
|
||||||
public string Name;
|
public string Name;
|
||||||
public uint Position;
|
public uint Position;
|
||||||
public uint Length;
|
public uint Length;
|
||||||
|
public uint Offset;
|
||||||
public object Value;
|
public object Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,15 +517,10 @@ namespace SonicAudioLib.IO
|
|||||||
|
|
||||||
public static void Pad(Stream destination, long alignment)
|
public static void Pad(Stream destination, long alignment)
|
||||||
{
|
{
|
||||||
long value = destination.Position;
|
while (destination.Position % alignment != 0)
|
||||||
|
|
||||||
while ((value % alignment) != 0)
|
|
||||||
{
|
{
|
||||||
value++;
|
WriteByte(destination, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] buffer = new byte[value - destination.Position];
|
|
||||||
destination.Write(buffer, 0, buffer.Length);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user