summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKiritoDv <kiritodev01@gmail.com>2024-03-17 18:27:18 -0600
committerKiritoDv <kiritodev01@gmail.com>2024-03-17 18:27:18 -0600
commitc967f85c7cc08649b937835bb0cd95d02768c072 (patch)
tree6f99f1000ef57dbc40859592fe366dccf4e768d5
parent515a939b066f23d71ff32ae47e864608d392479c (diff)
Added full shindou support but crashes on sf64
-rw-r--r--src/Companion.cpp6
-rw-r--r--src/audio/AudioManager.cpp122
-rw-r--r--src/audio/AudioManager.h5
-rw-r--r--src/factories/AudioHeaderFactory.cpp22
-rw-r--r--src/factories/AudioHeaderFactory.h11
5 files changed, 114 insertions, 52 deletions
diff --git a/src/Companion.cpp b/src/Companion.cpp
index 7784fe7..c8a296a 100644
--- a/src/Companion.cpp
+++ b/src/Companion.cpp
@@ -166,7 +166,7 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar
auto impl = factory->get();
auto exporter = impl->GetExporter(this->gConfig.exporterType);
- if(!exporter.has_value()){
+ if(!exporter.has_value() && type != "AUDIO:HEADER"){
SPDLOG_WARN("No exporter found for {}", name);
return;
}
@@ -652,8 +652,8 @@ void Companion::Process() {
this->ExtractNode(node, output, wrapper);
}
} else {
- const auto offset = assetNode["offset"].as<uint32_t>();
- if(gCurrentFileOffset) {
+ if(gCurrentFileOffset && assetNode["offset"]) {
+ const auto offset = assetNode["offset"].as<uint32_t>();
if (IS_SEGMENTED(offset) == false) {
assetNode["offset"] = (gCurrentSegmentNumber << 24) | offset;
}
diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp
index 2b24a8f..1049bcb 100644
--- a/src/audio/AudioManager.cpp
+++ b/src/audio/AudioManager.cpp
@@ -139,35 +139,32 @@ Bank AudioManager::parse_ctl(CTLHeader header, std::vector<uint8_t> data, Sample
std::string name = ss.str();
uint32_t numInstruments = header.instruments;
uint32_t numDrums = header.numDrums;
- char* rawData = (char*) data.data();
+ LUS::BinaryReader reader(reinterpret_cast<char*>(data.data()), data.size());
+ reader.SetEndianness(LUS::Endianness::Big);
- uint32_t drumBaseAddr;
- memcpy(&drumBaseAddr, rawData, 4);
- drumBaseAddr = BSWAP32(drumBaseAddr);
+ uint32_t drumBaseAddr = reader.ReadUInt32();
std::vector<uint32_t> drumOffsets;
if(numDrums != 0){
assert(drumBaseAddr != 0);
for (size_t i = 0; i < numDrums; ++i) {
- uint32_t drumOffset;
- memcpy(&drumOffset, rawData + drumBaseAddr + i * 4, 4);
- drumOffset = BSWAP32(drumOffset);
- assert(drumOffset != 0);
+ reader.Seek(drumBaseAddr + i * 4, LUS::SeekOffsetType::Start);
+ uint32_t drumOffset = reader.ReadUInt32();
+ // assert(drumOffset != 0);
drumOffsets.push_back(drumOffset);
}
} else {
assert(drumBaseAddr == 0);
}
- uint32_t instrumentBaseAddr = 4;
+ const uint32_t instrumentBaseAddr = 4;
std::vector<uint32_t> instrumentOffsets;
std::vector<uint32_t> instrumentList;
for (size_t i = 0; i < numInstruments; ++i) {
- uint32_t instOffset;
- memcpy(&instOffset, rawData + (instrumentBaseAddr + i * 4), 4);
- instOffset = BSWAP32(instOffset);
+ reader.Seek(instrumentBaseAddr + i * 4, LUS::SeekOffsetType::Start);
+ uint32_t instOffset = reader.ReadUInt32();
if(instOffset == 0){
instrumentList.push_back(NONE);
instrumentOffsets.push_back(NONE);
@@ -256,17 +253,16 @@ Bank AudioManager::parse_ctl(CTLHeader header, std::vector<uint8_t> data, Sample
}
}
- std::vector<uint32_t> unusedEnvOffsets;
if(!usedEnvOffsets.empty()){
+ std::vector<uint32_t> unusedEnvOffsets;
size_t min = std::min_element(usedEnvOffsets.begin(), usedEnvOffsets.end()) - usedEnvOffsets.begin();
size_t max = std::max_element(usedEnvOffsets.begin(), usedEnvOffsets.end()) - usedEnvOffsets.begin();
for(size_t idx = min + 4; idx < max; idx += 4){
uint32_t addr = usedEnvOffsets[idx];
if(std::find(usedEnvOffsets.begin(), usedEnvOffsets.end(), addr) == usedEnvOffsets.end()){
unusedEnvOffsets.push_back(addr);
- uint32_t stubMarker;
- memcpy(&stubMarker, rawData + addr, 4);
- stubMarker = BSWAP32(stubMarker);
+ reader.Seek(addr, LUS::SeekOffsetType::Start);
+ uint32_t stubMarker = reader.ReadUInt32();
assert(stubMarker == 0);
auto env = parse_envelope(addr, data);
envData[addr] = env;
@@ -379,8 +375,8 @@ AdpcmBook AudioManager::parse_book(uint32_t addr, std::vector<uint8_t>& bankData
int32_t order = reader.ReadInt32();
int32_t npredictors = reader.ReadInt32();
- assert(order == 2);
- assert(npredictors == 2);
+ // assert(order == 2);
+ // assert(npredictors == 2);
std::vector<int16_t> table;
std::vector<uint8_t> tableData = PyUtils::slice(bankData, addr + 8, addr + 8 + 16 * order * npredictors);
@@ -449,9 +445,14 @@ std::vector<AdsrEnvelope> AudioManager::parse_envelope(uint32_t addr, std::vecto
return entries;
}
+#define SM64 0
+#define SF64 1
+#define GAME SF64
+
std::vector<Entry> AudioManager::parse_sh_header(std::vector<uint8_t>& data, bool isCTL) {
- LUS::BinaryReader reader((char*) data.data(), data.size());
- size_t num_entries = reader.ReadUInt32();
+ LUS::BinaryReader reader(reinterpret_cast<char*>(data.data()), data.size());
+ reader.SetEndianness(LUS::Endianness::Big);
+ int16_t num_entries = reader.ReadInt16();
uint32_t prev = 0;
std::vector<Entry> entries;
@@ -462,25 +463,39 @@ std::vector<Entry> AudioManager::parse_sh_header(std::vector<uint8_t>& data, boo
reader.Seek(16 + 16 * i, LUS::SeekOffsetType::Start);
uint32_t offset = reader.ReadUInt32();
uint32_t length = reader.ReadUInt32();
- uint16_t magic = reader.ReadUInt16();
+ uint8_t medium = reader.ReadUByte();
+ uint8_t cachePolicy = reader.ReadUByte();
+ assert(length != 0);
assert(offset == prev);
- assert(magic == (!isCTL ? 0x0204 : 0x0203));
-
prev = offset + length;
+ if(GAME == SM64) {
+ assert(medium == 0x02);
+ assert(cachePolicy == (!isCTL ? 0x04 : 0x03));
+ } else {
+ SPDLOG_INFO("Medium: {}", medium);
+ SPDLOG_INFO("Cache Policy: {}", cachePolicy);
+ }
+
if(isCTL){
- uint8_t sampleBankIndex = reader.ReadUByte();
- uint8_t magic2 = reader.ReadUByte();
- uint8_t numInstruments = reader.ReadUByte();
- uint8_t numDrums = reader.ReadUByte();
+ auto sampleBankIndex = reader.ReadUByte();
+ auto sampleBankIndex2 = reader.ReadUByte();
+ auto numInstruments = reader.ReadUByte();
+ auto numDrums = reader.ReadUByte();
+
+ SPDLOG_INFO("Sample Bank Index: {}", sampleBankIndex);
+ SPDLOG_INFO("Num Instruments: {}", numInstruments);
+ SPDLOG_INFO("Num Drums: {}", numDrums);
+
assert(reader.ReadUInt16() == 0);
- assert(magic2 == 0xFF);
+ assert(sampleBankIndex2 == 0xFF);
+
entries.push_back(Entry { offset, length, SHHeader {
- sampleBankIndex, numInstruments, numDrums
+ sampleBankIndex, -1, numInstruments, numDrums
}});
} else {
- assert((reader.ReadUInt32() + reader.ReadUInt16()) == 0);
+ assert(reader.ReadUInt32() + reader.ReadUInt16() == 0);
entries.push_back(Entry { offset, length });
}
}
@@ -521,38 +536,44 @@ void AudioManager::initialize(std::vector<uint8_t>& buffer, YAML::Node& data) {
auto tbl_data = PyUtils::slice(buffer, tblOffset, tblOffset + tblSize);
auto ctl_data = PyUtils::slice(buffer, ctlOffset, ctlOffset + ctlSize);
- if(data["ctl_headers"] && data["tbl_headers"]){
- auto ctl = GetSafeNode<YAML::Node>(data, "ctl_headers");
- auto tbl = GetSafeNode<YAML::Node>(data, "tbl_headers");
+ if(data["ctl_header"] && data["tbl_header"]){
+ auto ctl_header = GetSafeNode<YAML::Node>(data, "ctl_header");
+ auto tbl_header = GetSafeNode<YAML::Node>(data, "tbl_header");
- auto ctlHeaderOffset = GetSafeNode<uint32_t>(ctl, "offset");
- auto ctlHeaderSize = GetSafeNode<size_t>(ctl, "size");
+ auto ctlHeaderOffset = GetSafeNode<uint32_t>(ctl_header, "offset");
+ auto ctlHeaderSize = GetSafeNode<size_t>(ctl_header, "size");
- auto tblHeaderOffset = GetSafeNode<uint32_t>(tbl, "offset");
- auto tblHeaderSize = GetSafeNode<size_t>(tbl, "size");
+ auto tblHeaderOffset = GetSafeNode<uint32_t>(tbl_header, "offset");
+ auto tblHeaderSize = GetSafeNode<size_t>(tbl_header, "size");
+ auto ctl_header_data = PyUtils::slice(buffer, ctlHeaderOffset, ctlHeaderOffset + ctlHeaderSize);
auto tbl_header_data = PyUtils::slice(buffer, tblHeaderOffset, tblHeaderOffset + tblHeaderSize);
- auto ctl_header_data = PyUtils::slice(buffer, ctlHeaderOffset, ctlHeaderOffset + tblHeaderSize);
- auto tblEntries = parse_sh_header(tbl_header_data, false);
auto ctlEntries = parse_sh_header(ctl_header_data, true);
+ auto tblEntries = parse_sh_header(tbl_header_data, false);
- SPDLOG_INFO("Raw TBL Entries: {}", tbl.size());
- SPDLOG_INFO("Raw CTL Entries: {}", ctl.size());
+ SPDLOG_INFO("Raw TBL Entries: {}", tblEntries.size());
+ SPDLOG_INFO("Raw CTL Entries: {}", ctlEntries.size());
this->loaded_tbl = parse_tbl(tbl_data, tblEntries);
for(size_t idx = 0; idx < ctlEntries.size(); idx++){
- auto header = ctlEntries[idx].header.value();
+ auto ctrl = ctlEntries[idx];
+ auto header = ctrl.header.value();
+ auto entry = PyUtils::slice(ctl_data, ctrl.offset, ctrl.offset + ctrl.length);
auto sample_bank = this->loaded_tbl.banks[header.sampleBankIndex];
- auto entry = PyUtils::slice(ctl_data, ctlEntries[idx].offset, ctlEntries[idx].offset + ctlEntries[idx].length);
CTLHeader ch = {
header.numInsts,
header.numDrums,
"0000-00-00"
};
- auto bank = parse_ctl(ch, PyUtils::slice(entry, 16), sample_bank, idx, true);
+
+ if(idx == 24) {
+ continue;
+ }
+
+ auto bank = parse_ctl(ch, entry, sample_bank, idx, true);
banks[idx] = bank;
}
@@ -794,4 +815,17 @@ uint32_t AudioManager::get_index(AudioBankSample* entry) {
std::map<uint32_t, Bank> AudioManager::get_banks() {
return this->banks;
+}
+
+std::vector<AudioBankSample*> AudioManager::get_samples() {
+ std::vector<AudioBankSample*> samples;
+ for(auto &bank : this->loaded_tbl.banks){
+ for(auto &entry : bank->entries){
+ // Avoid duplicates
+ if(std::find(samples.begin(), samples.end(), entry.second) == samples.end()){
+ samples.push_back(entry.second);
+ }
+ }
+ }
+ return samples;
} \ No newline at end of file
diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h
index f95e624..2dd7134 100644
--- a/src/audio/AudioManager.h
+++ b/src/audio/AudioManager.h
@@ -27,6 +27,7 @@ namespace AIFC {
struct SHHeader {
uint8_t sampleBankIndex;
+ int8_t sampleBankIndex2;
uint8_t numInsts;
uint8_t numDrums;
};
@@ -150,7 +151,9 @@ public:
std::string& get_sample(uint32_t id);
AudioBankSample get_aifc(int32_t index);
std::map<uint32_t, Bank> get_banks();
+ std::vector<AudioBankSample*> get_samples();
uint32_t get_index(AudioBankSample* bank);
+ static void write_aifc(AudioBankSample* entry, LUS::BinaryWriter& writer);
private:
std::map<uint32_t, Bank> banks;
@@ -169,6 +172,4 @@ private:
static Bank parse_ctl(CTLHeader header, std::vector<uint8_t> data, SampleBank* bank, uint32_t index, bool hasHeaders);
static std::vector<Entry> parse_sh_header(std::vector<uint8_t>& data, bool isCTL);
static TBLFile parse_tbl(std::vector<uint8_t>& data, std::vector<Entry>& entries);
-
- static void write_aifc(AudioBankSample* entry, LUS::BinaryWriter& writer);
}; \ No newline at end of file
diff --git a/src/factories/AudioHeaderFactory.cpp b/src/factories/AudioHeaderFactory.cpp
index d1cceb5..8234552 100644
--- a/src/factories/AudioHeaderFactory.cpp
+++ b/src/factories/AudioHeaderFactory.cpp
@@ -1,9 +1,29 @@
#include "AudioHeaderFactory.h"
#include <vector>
+#include "Companion.h"
#include "audio/AudioManager.h"
+void AudioAIFCExporter::Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) {
+
+ auto samples = AudioManager::Instance->get_samples();
+
+ int temp = 0;
+ for(auto& sample : samples){
+ LUS::BinaryWriter writer = LUS::BinaryWriter();
+ std::string dpath = Companion::Instance->GetOutputPath() + "/" + (*replacement);
+ if(!exists(fs::path(dpath).parent_path())){
+ create_directories(fs::path(dpath).parent_path());
+ }
+ std::ofstream file(dpath + "_bank_" + std::to_string(++temp) + ".aifc", std::ios::binary);
+ AudioManager::write_aifc(sample, writer);
+ writer.Finish(file);
+ file.close();
+ }
+}
+
std::optional<std::shared_ptr<IParsedData>> AudioHeaderFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& data) {
AudioManager::Instance->initialize(buffer, data);
- return std::nullopt;
+ auto parsed = std::make_shared<IParsedData>();
+ return parsed;
} \ No newline at end of file
diff --git a/src/factories/AudioHeaderFactory.h b/src/factories/AudioHeaderFactory.h
index 4726068..3170028 100644
--- a/src/factories/AudioHeaderFactory.h
+++ b/src/factories/AudioHeaderFactory.h
@@ -2,6 +2,11 @@
#include "BaseFactory.h"
+class AudioAIFCExporter : public BaseExporter {
+public:
+ void Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
class AudioHeaderFactory : public BaseFactory {
public:
std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
@@ -9,7 +14,9 @@ public:
return std::nullopt;
}
inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
- return {};
+ return {
+ REGISTER(Modding, AudioAIFCExporter)
+ };
}
- bool SupportModdedAssets() override { return false; }
+ bool SupportModdedAssets() override { return true; }
}; \ No newline at end of file