summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKiritoDv <kiritodev01@gmail.com>2024-11-19 16:40:24 -0600
committerLywx <kiritodev01@gmail.com>2024-11-21 00:05:17 -0600
commit528ea6090bbc39f77d320b3fb9b8caa4fe958948 (patch)
treef176350645d478cc80fa1505120591936ff9ba3b /src
parent4451ae28dba815411a39fcda22a3455d1ea69343 (diff)
Recreated audio export system to something more generic
Diffstat (limited to 'src')
-rw-r--r--src/Companion.cpp42
-rw-r--r--src/factories/BaseFactory.h4
-rw-r--r--src/factories/ResourceType.h16
-rw-r--r--src/factories/naudio/v0/AIFCDecode.cpp (renamed from src/factories/sm64/audio/AIFCDecode.cpp)0
-rw-r--r--src/factories/naudio/v0/AIFCDecode.h (renamed from src/factories/sm64/audio/AIFCDecode.h)0
-rw-r--r--src/factories/naudio/v0/AudioHeaderFactory.cpp (renamed from src/factories/sm64/audio/AudioHeaderFactory.cpp)0
-rw-r--r--src/factories/naudio/v0/AudioHeaderFactory.h (renamed from src/factories/sm64/audio/AudioHeaderFactory.h)0
-rw-r--r--src/factories/naudio/v0/AudioManager.cpp (renamed from src/factories/sm64/audio/AudioManager.cpp)0
-rw-r--r--src/factories/naudio/v0/AudioManager.h (renamed from src/factories/sm64/audio/AudioManager.h)0
-rw-r--r--src/factories/naudio/v0/BankFactory.cpp (renamed from src/factories/sm64/audio/BankFactory.cpp)0
-rw-r--r--src/factories/naudio/v0/BankFactory.h (renamed from src/factories/sm64/audio/BankFactory.h)0
-rw-r--r--src/factories/naudio/v0/SampleFactory.cpp (renamed from src/factories/sm64/audio/SampleFactory.cpp)0
-rw-r--r--src/factories/naudio/v0/SampleFactory.h (renamed from src/factories/sm64/audio/SampleFactory.h)0
-rw-r--r--src/factories/naudio/v0/SequenceFactory.cpp (renamed from src/factories/sm64/audio/SequenceFactory.cpp)0
-rw-r--r--src/factories/naudio/v0/SequenceFactory.h (renamed from src/factories/sm64/audio/SequenceFactory.h)0
-rw-r--r--src/factories/naudio/v1/AudioContext.cpp78
-rw-r--r--src/factories/naudio/v1/AudioContext.h35
-rw-r--r--src/factories/naudio/v1/AudioTableFactory.cpp131
-rw-r--r--src/factories/naudio/v1/AudioTableFactory.h53
-rw-r--r--src/factories/naudio/v1/BookFactory.cpp58
-rw-r--r--src/factories/naudio/v1/BookFactory.h35
-rw-r--r--src/factories/naudio/v1/DrumFactory.cpp63
-rw-r--r--src/factories/naudio/v1/DrumFactory.h37
-rw-r--r--src/factories/naudio/v1/EnvelopeFactory.cpp54
-rw-r--r--src/factories/naudio/v1/EnvelopeFactory.h41
-rw-r--r--src/factories/naudio/v1/InstrumentFactory.cpp70
-rw-r--r--src/factories/naudio/v1/InstrumentFactory.h40
-rw-r--r--src/factories/naudio/v1/LoopFactory.cpp56
-rw-r--r--src/factories/naudio/v1/LoopFactory.h36
-rw-r--r--src/factories/naudio/v1/SampleFactory.cpp81
-rw-r--r--src/factories/naudio/v1/SampleFactory.h41
-rw-r--r--src/factories/naudio/v1/SoundFontFactory.cpp148
-rw-r--r--src/factories/naudio/v1/SoundFontFactory.h37
33 files changed, 1144 insertions, 12 deletions
diff --git a/src/Companion.cpp b/src/Companion.cpp
index 8059e8c..19c4f1a 100644
--- a/src/Companion.cpp
+++ b/src/Companion.cpp
@@ -26,10 +26,6 @@
#include "factories/AssetArrayFactory.h"
#include "factories/ViewportFactory.h"
-#include "factories/sm64/audio/BankFactory.h"
-#include "factories/sm64/audio/AudioHeaderFactory.h"
-#include "factories/sm64/audio/SampleFactory.h"
-#include "factories/sm64/audio/SequenceFactory.h"
#include "factories/sm64/AnimationFactory.h"
#include "factories/sm64/BehaviorScriptFactory.h"
#include "factories/sm64/CollisionFactory.h"
@@ -66,6 +62,21 @@
#include "factories/sf64/ObjInitFactory.h"
#include "factories/sf64/TriangleFactory.h"
+#include "factories/naudio/v0/AudioHeaderFactory.h"
+#include "factories/naudio/v0/BankFactory.h"
+#include "factories/naudio/v0/SampleFactory.h"
+#include "factories/naudio/v0/SequenceFactory.h"
+
+#include "factories/naudio/v1/AudioContext.h"
+#include "factories/naudio/v1/SoundFontFactory.h"
+#include "factories/naudio/v1/AudioTableFactory.h"
+#include "factories/naudio/v1/InstrumentFactory.h"
+#include "factories/naudio/v1/SampleFactory.h"
+#include "factories/naudio/v1/DrumFactory.h"
+#include "factories/naudio/v1/EnvelopeFactory.h"
+#include "factories/naudio/v1/LoopFactory.h"
+#include "factories/naudio/v1/BookFactory.h"
+
using namespace std::chrono;
namespace fs = std::filesystem;
@@ -95,10 +106,6 @@ void Companion::Init(const ExportType type) {
this->RegisterFactory("VP", std::make_shared<ViewportFactory>());
// SM64 specific
- this->RegisterFactory("SM64:AUDIO_HEADER", std::make_shared<AudioHeaderFactory>());
- this->RegisterFactory("SM64:SEQUENCE", std::make_shared<SequenceFactory>());
- this->RegisterFactory("SM64:SAMPLE", std::make_shared<SampleFactory>());
- this->RegisterFactory("SM64:BANK", std::make_shared<BankFactory>());
this->RegisterFactory("SM64:DIALOG", std::make_shared<SM64::DialogFactory>());
this->RegisterFactory("SM64:TEXT", std::make_shared<SM64::TextFactory>());
this->RegisterFactory("SM64:DICTIONARY", std::make_shared<SM64::DictionaryFactory>());
@@ -137,6 +144,22 @@ void Companion::Init(const ExportType type) {
this->RegisterFactory("SF64:COLPOLY", std::make_shared<SF64::ColPolyFactory>());
this->RegisterFactory("SF64:TRIANGLE", std::make_shared<SF64::TriangleFactory>());
+ // NAudio specific
+ this->RegisterFactory("NAUDIO:V0:AUDIO_HEADER", std::make_shared<AudioHeaderFactory>());
+ this->RegisterFactory("NAUDIO:V0:SEQUENCE", std::make_shared<SequenceFactory>());
+ this->RegisterFactory("NAUDIO:V0:SAMPLE", std::make_shared<SampleFactory>());
+ this->RegisterFactory("NAUDIO:V0:BANK", std::make_shared<BankFactory>());
+
+ this->RegisterFactory("NAUDIO:V1:AUDIO_SETUP", std::make_shared<AudioContextFactory>());
+ this->RegisterFactory("NAUDIO:V1:AUDIO_TABLE", std::make_shared<AudioTableFactory>());
+ this->RegisterFactory("NAUDIO:V1:SOUND_FONT", std::make_shared<SoundFontFactory>());
+ this->RegisterFactory("NAUDIO:V1:INSTRUMENT", std::make_shared<InstrumentFactory>());
+ this->RegisterFactory("NAUDIO:V1:DRUM", std::make_shared<DrumFactory>());
+ this->RegisterFactory("NAUDIO:V1:SAMPLE", std::make_shared<NSampleFactory>());
+ this->RegisterFactory("NAUDIO:V1:ENVELOPE", std::make_shared<EnvelopeFactory>());
+ this->RegisterFactory("NAUDIO:V1:ADPCM_LOOP", std::make_shared<ADPCMLoopFactory>());
+ this->RegisterFactory("NAUDIO:V1:ADPCM_BOOK", std::make_shared<ADPCMBookFactory>());
+
this->Process();
}
@@ -1451,6 +1474,9 @@ std::optional<YAML::Node> Companion::AddAsset(YAML::Node asset) {
} else {
output = this->NormalizeAsset(typeId + "_" + Torch::to_hex(offset, false));
}
+
+ std::replace(output.begin(), output.end(), ':', '_');
+
asset["autogen"] = true;
asset["symbol"] = output;
diff --git a/src/factories/BaseFactory.h b/src/factories/BaseFactory.h
index d7b71e9..0320605 100644
--- a/src/factories/BaseFactory.h
+++ b/src/factories/BaseFactory.h
@@ -111,5 +111,7 @@ public:
return std::nullopt;
}
private:
- virtual std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() = 0;
+ virtual std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() {
+ return {};
+ }
}; \ No newline at end of file
diff --git a/src/factories/ResourceType.h b/src/factories/ResourceType.h
index 7039dbc..4f00098 100644
--- a/src/factories/ResourceType.h
+++ b/src/factories/ResourceType.h
@@ -15,9 +15,6 @@ enum class ResourceType {
Array = 0x4F415252, // OARR
Blob = 0x4F424C42, // OBLB
Texture = 0x4F544558, // OTEX
- Bank = 0x42414E4B, // BANK
- Sample = 0x41554643, // AIFC
- Sequence = 0x53455143, // SEQC
Lights = 0x46669697, // LGTS
Vec3f = 0x56433346, // VC3F
Vec3s = 0x56433353, // VC3S
@@ -63,5 +60,18 @@ enum class ResourceType {
ScriptCmd = 0x53434D44, // SCMD
Hitbox = 0x48544258, // HTBX
ObjectInit = 0x4F42494E, // OBIN
+
+ // NAudio v0
+ Bank = 0x42414E4B, // BANK
+ Sample = 0x41554643, // AIFC
+ Sequence = 0x53455143, // SEQC
+
+ // NAudio v1
+ SoundFont = 0x53464E54, // SFNT
+ Drum = 0x4452554D, // DRUM
+ Instrument = 0x494E5354, // INST
+ AdpcmLoop = 0x4150434C, // APCL
+ AdpcmBook = 0x41504342, // APCB
+ Envelope = 0x45564C50, // EVLP
};
} // namespace LUS
diff --git a/src/factories/sm64/audio/AIFCDecode.cpp b/src/factories/naudio/v0/AIFCDecode.cpp
index e627ad0..e627ad0 100644
--- a/src/factories/sm64/audio/AIFCDecode.cpp
+++ b/src/factories/naudio/v0/AIFCDecode.cpp
diff --git a/src/factories/sm64/audio/AIFCDecode.h b/src/factories/naudio/v0/AIFCDecode.h
index e141a80..e141a80 100644
--- a/src/factories/sm64/audio/AIFCDecode.h
+++ b/src/factories/naudio/v0/AIFCDecode.h
diff --git a/src/factories/sm64/audio/AudioHeaderFactory.cpp b/src/factories/naudio/v0/AudioHeaderFactory.cpp
index dc4d547..dc4d547 100644
--- a/src/factories/sm64/audio/AudioHeaderFactory.cpp
+++ b/src/factories/naudio/v0/AudioHeaderFactory.cpp
diff --git a/src/factories/sm64/audio/AudioHeaderFactory.h b/src/factories/naudio/v0/AudioHeaderFactory.h
index 1c5c0b1..1c5c0b1 100644
--- a/src/factories/sm64/audio/AudioHeaderFactory.h
+++ b/src/factories/naudio/v0/AudioHeaderFactory.h
diff --git a/src/factories/sm64/audio/AudioManager.cpp b/src/factories/naudio/v0/AudioManager.cpp
index c168a39..c168a39 100644
--- a/src/factories/sm64/audio/AudioManager.cpp
+++ b/src/factories/naudio/v0/AudioManager.cpp
diff --git a/src/factories/sm64/audio/AudioManager.h b/src/factories/naudio/v0/AudioManager.h
index b5a9dcc..b5a9dcc 100644
--- a/src/factories/sm64/audio/AudioManager.h
+++ b/src/factories/naudio/v0/AudioManager.h
diff --git a/src/factories/sm64/audio/BankFactory.cpp b/src/factories/naudio/v0/BankFactory.cpp
index 6e72c53..6e72c53 100644
--- a/src/factories/sm64/audio/BankFactory.cpp
+++ b/src/factories/naudio/v0/BankFactory.cpp
diff --git a/src/factories/sm64/audio/BankFactory.h b/src/factories/naudio/v0/BankFactory.h
index 9f4b260..9f4b260 100644
--- a/src/factories/sm64/audio/BankFactory.h
+++ b/src/factories/naudio/v0/BankFactory.h
diff --git a/src/factories/sm64/audio/SampleFactory.cpp b/src/factories/naudio/v0/SampleFactory.cpp
index b8bc7fa..b8bc7fa 100644
--- a/src/factories/sm64/audio/SampleFactory.cpp
+++ b/src/factories/naudio/v0/SampleFactory.cpp
diff --git a/src/factories/sm64/audio/SampleFactory.h b/src/factories/naudio/v0/SampleFactory.h
index ae940e2..ae940e2 100644
--- a/src/factories/sm64/audio/SampleFactory.h
+++ b/src/factories/naudio/v0/SampleFactory.h
diff --git a/src/factories/sm64/audio/SequenceFactory.cpp b/src/factories/naudio/v0/SequenceFactory.cpp
index 1090bac..1090bac 100644
--- a/src/factories/sm64/audio/SequenceFactory.cpp
+++ b/src/factories/naudio/v0/SequenceFactory.cpp
diff --git a/src/factories/sm64/audio/SequenceFactory.h b/src/factories/naudio/v0/SequenceFactory.h
index b26242c..b26242c 100644
--- a/src/factories/sm64/audio/SequenceFactory.h
+++ b/src/factories/naudio/v0/SequenceFactory.h
diff --git a/src/factories/naudio/v1/AudioContext.cpp b/src/factories/naudio/v1/AudioContext.cpp
new file mode 100644
index 0000000..3800eb2
--- /dev/null
+++ b/src/factories/naudio/v1/AudioContext.cpp
@@ -0,0 +1,78 @@
+#include "AudioContext.h"
+#include "spdlog/spdlog.h"
+#include "Companion.h"
+
+std::unordered_map<AudioTableType, std::unordered_map<uint32_t, AudioTableEntry>> AudioContext::tables;
+std::unordered_map<AudioTableType, std::vector<uint8_t>> AudioContext::data;
+std::unordered_map<AudioTableType, AudioTableData> AudioContext::tableData;
+
+std::optional<std::shared_ptr<IParsedData>> AudioContextFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto seq = GetSafeNode<YAML::Node>(node, "audio_seq");
+ auto seqSize = GetSafeNode<uint32_t>(seq, "size");
+ auto seqOffset = GetSafeNode<uint32_t>(seq, "offset");
+
+ auto bank = GetSafeNode<YAML::Node>(node, "audio_bank");
+ auto bankSize = GetSafeNode<uint32_t>(bank, "size");
+ auto bankOffset = GetSafeNode<uint32_t>(bank, "offset");
+
+ auto table = GetSafeNode<YAML::Node>(node, "audio_table");
+ auto tableSize = GetSafeNode<uint32_t>(table, "size");
+ auto tableOffset = GetSafeNode<uint32_t>(table, "offset");
+
+ AudioContext::data[AudioTableType::SEQ_TABLE] = std::vector<uint8_t>(buffer.begin() + seqOffset, buffer.begin() + seqOffset + seqSize);
+ AudioContext::data[AudioTableType::FONT_TABLE] = std::vector<uint8_t>(buffer.begin() + bankOffset, buffer.begin() + bankOffset + bankSize);
+ AudioContext::data[AudioTableType::SAMPLE_TABLE] = std::vector<uint8_t>(buffer.begin() + tableOffset, buffer.begin() + tableOffset + tableSize);
+
+ SPDLOG_INFO("Sequence Table 0x{:X}", seqOffset);
+ SPDLOG_INFO("Sound Font Table 0x{:X}", bankOffset);
+ SPDLOG_INFO("Sample Bank Table 0x{:X}", tableOffset);
+
+ return std::nullopt;
+}
+
+LUS::BinaryReader AudioContext::MakeReader(AudioTableType type, uint32_t offset) {
+ auto entry = AudioContext::data[type];
+
+ LUS::BinaryReader reader(entry.data(), entry.size());
+ reader.SetEndianness(Torch::Endianness::Big);
+ reader.Seek(offset, LUS::SeekOffsetType::Start);
+
+ return reader;
+}
+
+TunedSample AudioContext::LoadTunedSample(LUS::BinaryReader& reader, uint32_t parent, uint32_t sampleBankId) {
+ auto sampleAddr = reader.ReadUInt32();
+ auto tuning = reader.ReadFloat();
+
+ if(sampleAddr == 0){
+ if(tuning != 0.0f){
+ throw std::runtime_error("The provided tuned sample is invalid");
+ }
+ return { 0, 0, 0.0f };
+ }
+
+ YAML::Node node;
+ node["type"] = "NAUDIO:V1:SAMPLE";
+ node["parent"] = parent;
+ node["offset"] = parent + sampleAddr;
+ node["sampleBankId"] = sampleBankId;
+ Companion::Instance->AddAsset(node);
+
+ return { parent + sampleAddr, sampleBankId, tuning };
+}
+
+uint64_t AudioContext::GetPathByAddr(uint32_t addr) {
+ if(addr == 0){
+ return 0;
+ }
+
+ auto dec = Companion::Instance->GetNodeByAddr(addr);
+ if (dec.has_value()) {
+ std::string path = std::get<0>(dec.value());
+ uint64_t hash = CRC64(path.c_str());
+ SPDLOG_INFO("Found path of 0x{:X} {}", addr, path);
+ return hash;
+ } else {
+ throw std::runtime_error("Failed to find node by addr");
+ }
+} \ No newline at end of file
diff --git a/src/factories/naudio/v1/AudioContext.h b/src/factories/naudio/v1/AudioContext.h
new file mode 100644
index 0000000..0ea5014
--- /dev/null
+++ b/src/factories/naudio/v1/AudioContext.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "AudioTableFactory.h"
+#include "factories/naudio/v0/AudioHeaderFactory.h"
+#include "factories/BaseFactory.h"
+
+struct TunedSample {
+ uint32_t sample;
+ uint32_t sampleBankId;
+ float tuning;
+};
+
+class AudioContext {
+public:
+ static std::unordered_map<AudioTableType, std::unordered_map<uint32_t, AudioTableEntry>> tables;
+ static std::unordered_map<AudioTableType, std::shared_ptr<AudioTableData>> tableData;
+ static std::unordered_map<AudioTableType, std::vector<uint8_t>> data;
+
+ static LUS::BinaryReader MakeReader(AudioTableType type, uint32_t offset);
+ static TunedSample LoadTunedSample(LUS::BinaryReader& reader, uint32_t parent, uint32_t sampleBankId);
+ static uint64_t GetPathByAddr(uint32_t addr);
+};
+
+class AudioContextFactory : public BaseFactory {
+public:
+ std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
+
+ inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
+ return {
+ REGISTER(Header, AudioDummyExporter)
+ REGISTER(Binary, AudioDummyExporter)
+ REGISTER(Code, AudioDummyExporter)
+ };
+ }
+};
diff --git a/src/factories/naudio/v1/AudioTableFactory.cpp b/src/factories/naudio/v1/AudioTableFactory.cpp
new file mode 100644
index 0000000..2dcd665
--- /dev/null
+++ b/src/factories/naudio/v1/AudioTableFactory.cpp
@@ -0,0 +1,131 @@
+#include "AudioTableFactory.h"
+#include "utils/Decompressor.h"
+#include "spdlog/spdlog.h"
+#include "AudioContext.h"
+#include "Companion.h"
+#include <iomanip>
+
+#define INT2(c) std::dec << std::setfill(' ') << c
+#define HEX(c) "0x" << std::hex << std::setw(4) << std::setfill('0') << c
+#define ADDR(c) "0x" << std::hex << std::setw(5) << std::setfill('0') << c
+
+static const std::unordered_map <std::string, AudioTableType> gTableTypes = {
+ { "SOUNDFONT", AudioTableType::FONT_TABLE },
+ { "SAMPLE", AudioTableType::SAMPLE_TABLE },
+ { "SEQUENCE", AudioTableType::SEQ_TABLE }
+};
+
+ExportResult AudioTableHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ if(Companion::Instance->IsOTRMode()){
+ write << "static const ALIGN_ASSET(2) char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ write << "extern AudioTable " << symbol << ";\n";
+
+ return std::nullopt;
+}
+
+ExportResult AudioTableCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+ const auto offset = GetSafeNode<uint32_t>(node, "offset");
+ auto table = std::static_pointer_cast<AudioTableData>(raw);
+
+ if(table->type == AudioTableType::FONT_TABLE){
+ write << "#define SOUNDFONT_ENTRY(offset, size, medium, cachePolicy, bank1, bank2, numInst, numDrums) { \\\n";
+ write << fourSpaceTab << "offset, size, medium, cachePolicy, (((bank1) &0xFF) << 8) | ((bank2) &0xFF), \\\n";
+ write << fourSpaceTab << fourSpaceTab << "(((numInst) &0xFF) << 8) | ((numDrums) &0xFF) \\\n}\n\n";
+ }
+
+ write << "AudioTable " << symbol << " = {\n";
+ write << fourSpaceTab << "{ " << table->entries.size() << ", " << table->medium << ", " << table->addr << " },\n";
+ write << fourSpaceTab << "{ \n";
+
+ for(size_t i = 0; i < table->entries.size(); i++){
+ auto &entry = table->entries[i];
+
+ if(table->type == AudioTableType::FONT_TABLE) {
+ uint32_t numInstruments = (entry.shortData2 >> 8) & 0xFFu;
+ uint32_t numDrums = entry.shortData2 & 0xFFu;
+ uint32_t sampleBankId1 = (entry.shortData1 >> 8) & 0xFFu;
+ uint32_t sampleBankId2 = entry.shortData1 & 0xFFu;
+
+ write << fourSpaceTab << fourSpaceTab << "SOUNDFONT_ENTRY(" << ADDR(entry.addr) << ", " << HEX(entry.size) << ", " << INT2((uint32_t) entry.medium) << ", " << INT2((uint32_t) entry.cachePolicy) << ", " << INT2(numInstruments) << ", " << INT2(numDrums) << ", " << INT2(sampleBankId1) << ", " << INT2(sampleBankId2) << "),\n" ;
+ } else {
+ write << fourSpaceTab << fourSpaceTab << "{ " << ADDR(entry.addr) << ", " << HEX(entry.size) << ", " << (uint32_t) entry.medium << ", " << (uint32_t) entry.cachePolicy << " },\n";
+ }
+ }
+
+ write << fourSpaceTab << "},\n";
+ write << "};\n";
+
+ if (Companion::Instance->IsDebug()) {
+ write << "// Count: " << table->entries.size() << "\n";
+ }
+
+ return offset + 0x10 + (table->entries.size() * sizeof(AudioTableEntry));
+}
+
+ExportResult AudioTableBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto writer = LUS::BinaryWriter();
+ // auto data = std::static_pointer_cast<AudioTableEntry>(raw)->mBuffer;
+
+ // WriteHeader(writer, Torch::ResourceType::Blob, 0);
+ // writer.Write((uint32_t) data.size());
+ // writer.Write((char*) data.data(), data.size());
+ // writer.Finish(write);
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> AudioTableFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ // Parse table entry
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
+ auto [_, segment] = Decompressor::AutoDecode(node, buffer);
+ LUS::BinaryReader reader(segment.data, segment.size);
+ reader.SetEndianness(Torch::Endianness::Big);
+
+ auto format = GetSafeNode<std::string>(node, "format");
+ std::transform(format.begin(), format.end(), format.begin(), ::toupper);
+
+ if(!gTableTypes.contains(format)) {
+ return std::nullopt;
+ }
+
+ auto type = gTableTypes.at(format);
+ auto count = reader.ReadInt16();
+ auto bmedium = reader.ReadInt16();
+ auto baddr = reader.ReadUInt32();
+ reader.Read(0x8); // PAD
+
+ SPDLOG_INFO("count: {}", count);
+ SPDLOG_INFO("medium: {}", bmedium);
+ SPDLOG_INFO("addr: {}", baddr);
+
+ std::vector<AudioTableEntry> entries;
+ for(size_t i = 0; i < count; i++){
+ auto addr = reader.ReadUInt32();
+ auto size = reader.ReadUInt32();
+ auto medium = reader.ReadInt8();
+ auto policy = reader.ReadInt8();
+ auto sd1 = reader.ReadInt16();
+ auto sd2 = reader.ReadInt16();
+ auto sd3 = reader.ReadInt16();
+ auto entry = AudioTableEntry { addr, size, medium, policy, sd1, sd2, sd3 };
+ entries.push_back(entry);
+
+ if(type == AudioTableType::FONT_TABLE){
+ YAML::Node font;
+ font["type"] = "NAUDIO:V1:SOUND_FONT";
+ font["offset"] = addr;
+ Companion::Instance->AddAsset(font);
+ }
+
+ AudioContext::tables[type][addr] = entry;
+ }
+
+ auto table = std::make_shared<AudioTableData>(bmedium, offset, type, entries);
+ AudioContext::tableData[type] = table;
+ return table;
+}
diff --git a/src/factories/naudio/v1/AudioTableFactory.h b/src/factories/naudio/v1/AudioTableFactory.h
new file mode 100644
index 0000000..8d83dc0
--- /dev/null
+++ b/src/factories/naudio/v1/AudioTableFactory.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <factories/BaseFactory.h>
+
+struct AudioTableEntry {
+ uint32_t addr;
+ uint32_t size;
+ int8_t medium;
+ int8_t cachePolicy;
+ int16_t shortData1;
+ int16_t shortData2;
+ int16_t shortData3;
+};
+
+enum class AudioTableType {
+ SAMPLE_TABLE,
+ SEQ_TABLE,
+ FONT_TABLE
+};
+
+class AudioTableData : public IParsedData {
+public:
+ int16_t medium;
+ uint32_t addr;
+ AudioTableType type;
+ std::vector<AudioTableEntry> entries;
+
+ AudioTableData(int16_t medium, uint32_t addr, AudioTableType type, std::vector<AudioTableEntry> entries) : medium(medium), addr(addr), type(type), entries(entries) {}
+};
+
+class AudioTableHeaderExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class AudioTableBinaryExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class AudioTableCodeExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class AudioTableFactory : public BaseFactory {
+public:
+ std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
+ inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
+ return {
+ REGISTER(Header, AudioTableHeaderExporter)
+ REGISTER(Binary, AudioTableBinaryExporter)
+ REGISTER(Code, AudioTableCodeExporter)
+ };
+ }
+};
diff --git a/src/factories/naudio/v1/BookFactory.cpp b/src/factories/naudio/v1/BookFactory.cpp
new file mode 100644
index 0000000..96d1e53
--- /dev/null
+++ b/src/factories/naudio/v1/BookFactory.cpp
@@ -0,0 +1,58 @@
+#include "BookFactory.h"
+#include "utils/Decompressor.h"
+#include "Companion.h"
+
+ExportResult ADPCMBookHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ if(Companion::Instance->IsOTRMode()){
+ write << "static const ALIGN_ASSET(2) char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ write << "extern AdpcmBook " << symbol << ";\n";
+
+ return std::nullopt;
+}
+
+ExportResult ADPCMBookCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ return std::nullopt;
+}
+
+ExportResult ADPCMBookBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto writer = LUS::BinaryWriter();
+ auto data = std::static_pointer_cast<ADPCMBookData>(raw);
+
+ WriteHeader(writer, Torch::ResourceType::AdpcmBook, 0);
+ writer.Write(data->order);
+ writer.Write(data->numPredictors);
+ writer.Write((uint32_t) data->book.size());
+
+ for(auto& page : data->book){
+ writer.Write(page);
+ }
+
+ writer.Finish(write);
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> ADPCMBookFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
+ auto reader = AudioContext::MakeReader(AudioTableType::FONT_TABLE, offset);
+
+ auto book = std::make_shared<ADPCMBookData>();
+
+ book->order = reader.ReadInt32();
+ book->numPredictors = reader.ReadInt32();
+ size_t length = 8 * book->order * book->numPredictors;
+
+ if(length > 0x40){
+ return std::nullopt;
+ }
+
+ for(size_t i = 0; i < length; i++){
+ book->book.push_back(reader.ReadInt16());
+ }
+
+ return book;
+}
diff --git a/src/factories/naudio/v1/BookFactory.h b/src/factories/naudio/v1/BookFactory.h
new file mode 100644
index 0000000..a761f22
--- /dev/null
+++ b/src/factories/naudio/v1/BookFactory.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <factories/BaseFactory.h>
+#include "AudioContext.h"
+
+class ADPCMBookData : public IParsedData {
+public:
+ int32_t order;
+ int32_t numPredictors;
+ std::vector<int16_t> book;
+};
+
+class ADPCMBookHeaderExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class ADPCMBookBinaryExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class ADPCMBookCodeExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class ADPCMBookFactory : public BaseFactory {
+public:
+ std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
+ inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
+ return {
+ REGISTER(Header, ADPCMBookHeaderExporter)
+ REGISTER(Binary, ADPCMBookBinaryExporter)
+ REGISTER(Code, ADPCMBookCodeExporter)
+ };
+ }
+};
diff --git a/src/factories/naudio/v1/DrumFactory.cpp b/src/factories/naudio/v1/DrumFactory.cpp
new file mode 100644
index 0000000..bceaaae
--- /dev/null
+++ b/src/factories/naudio/v1/DrumFactory.cpp
@@ -0,0 +1,63 @@
+#include "DrumFactory.h"
+#include "utils/Decompressor.h"
+#include "Companion.h"
+
+ExportResult DrumHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ if(Companion::Instance->IsOTRMode()){
+ write << "static const ALIGN_ASSET(2) char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ write << "extern Drum " << symbol << ";\n";
+
+ return std::nullopt;
+}
+
+ExportResult DrumCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ return std::nullopt;
+}
+
+ExportResult DrumBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto writer = LUS::BinaryWriter();
+ auto data = std::static_pointer_cast<DrumData>(raw);
+
+ WriteHeader(writer, Torch::ResourceType::Drum, 0);
+ writer.Write(data->adsrDecayIndex);
+ writer.Write(data->pan);
+ writer.Write(data->isRelocated);
+ writer.Write(AudioContext::GetPathByAddr(data->tunedSample.sample));
+ writer.Write(data->tunedSample.tuning);
+ writer.Write(AudioContext::GetPathByAddr(data->envelope));
+
+ writer.Finish(write);
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> DrumFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
+ auto parent = GetSafeNode<uint32_t>(node, "parent");
+ auto sampleBankId = GetSafeNode<uint32_t>(node, "sampleBankId");
+
+ auto entry = AudioContext::tables[AudioTableType::FONT_TABLE].at(parent);
+
+ auto reader = AudioContext::MakeReader(AudioTableType::FONT_TABLE, offset);
+
+ auto drum = std::make_shared<DrumData>();
+ drum->adsrDecayIndex = reader.ReadInt8();
+ drum->pan = reader.ReadInt8();
+ drum->isRelocated = reader.ReadUByte();
+ reader.ReadUByte();;
+
+ drum->tunedSample = AudioContext::LoadTunedSample(reader, parent, sampleBankId);
+
+ auto envAddr = entry.addr + reader.ReadUInt32();
+ YAML::Node envelope;
+ envelope["type"] = "NAUDIO:V1:ENVELOPE";
+ envelope["offset"] = envAddr;
+ drum->envelope = envAddr;
+ Companion::Instance->AddAsset(envelope);
+
+ return drum;
+}
diff --git a/src/factories/naudio/v1/DrumFactory.h b/src/factories/naudio/v1/DrumFactory.h
new file mode 100644
index 0000000..e417e9a
--- /dev/null
+++ b/src/factories/naudio/v1/DrumFactory.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <factories/BaseFactory.h>
+#include "AudioContext.h"
+
+class DrumData : public IParsedData {
+public:
+ uint8_t adsrDecayIndex;
+ uint8_t pan;
+ uint8_t isRelocated;
+ TunedSample tunedSample;
+ uint32_t envelope;
+};
+
+class DrumHeaderExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class DrumBinaryExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class DrumCodeExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class DrumFactory : public BaseFactory {
+public:
+ std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
+ inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
+ return {
+ REGISTER(Header, DrumHeaderExporter)
+ REGISTER(Binary, DrumBinaryExporter)
+ REGISTER(Code, DrumCodeExporter)
+ };
+ }
+};
diff --git a/src/factories/naudio/v1/EnvelopeFactory.cpp b/src/factories/naudio/v1/EnvelopeFactory.cpp
new file mode 100644
index 0000000..3ba6755
--- /dev/null
+++ b/src/factories/naudio/v1/EnvelopeFactory.cpp
@@ -0,0 +1,54 @@
+#include "EnvelopeFactory.h"
+#include "utils/Decompressor.h"
+#include "Companion.h"
+
+ExportResult EnvelopeHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ if(Companion::Instance->IsOTRMode()){
+ write << "static const ALIGN_ASSET(2) char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ write << "extern Envelope " << symbol << ";\n";
+
+ return std::nullopt;
+}
+
+ExportResult EnvelopeCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ return std::nullopt;
+}
+
+ExportResult EnvelopeBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto writer = LUS::BinaryWriter();
+ auto data = std::static_pointer_cast<EnvelopeData>(raw);
+
+ WriteHeader(writer, Torch::ResourceType::Envelope, 0);
+ writer.Write((uint32_t) data->points.size());
+ for(auto& point : data->points){
+ writer.Write(point.delay);
+ writer.Write(point.arg);
+ }
+
+ writer.Finish(write);
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> EnvelopeFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
+ auto reader = AudioContext::MakeReader(AudioTableType::FONT_TABLE, offset);
+
+ std::vector<EnvelopePoint> temp;
+ while(true) {
+ int16_t delay = BSWAP16(reader.ReadInt16());
+ int16_t arg = BSWAP16(reader.ReadInt16());
+
+ temp.push_back({delay, arg});
+
+ if (1 <= (-delay) % (1 << 16) && (-delay) % (1 << 16) <= 3){
+ break;
+ }
+ }
+
+ return std::make_shared<EnvelopeData>(temp);
+}
diff --git a/src/factories/naudio/v1/EnvelopeFactory.h b/src/factories/naudio/v1/EnvelopeFactory.h
new file mode 100644
index 0000000..a75d031
--- /dev/null
+++ b/src/factories/naudio/v1/EnvelopeFactory.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <factories/BaseFactory.h>
+#include <vector>
+#include "AudioContext.h"
+
+struct EnvelopePoint {
+ int16_t delay;
+ int16_t arg;
+};
+
+class EnvelopeData : public IParsedData {
+public:
+ std::vector<EnvelopePoint> points;
+
+ EnvelopeData(std::vector<EnvelopePoint> points) : points(points) {};
+};
+
+class EnvelopeHeaderExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class EnvelopeBinaryExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class EnvelopeCodeExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class EnvelopeFactory : public BaseFactory {
+public:
+ std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
+ inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
+ return {
+ REGISTER(Header, EnvelopeHeaderExporter)
+ REGISTER(Binary, EnvelopeBinaryExporter)
+ REGISTER(Code, EnvelopeCodeExporter)
+ };
+ }
+};
diff --git a/src/factories/naudio/v1/InstrumentFactory.cpp b/src/factories/naudio/v1/InstrumentFactory.cpp
new file mode 100644
index 0000000..acfada1
--- /dev/null
+++ b/src/factories/naudio/v1/InstrumentFactory.cpp
@@ -0,0 +1,70 @@
+#include "InstrumentFactory.h"
+#include "utils/Decompressor.h"
+#include "Companion.h"
+
+ExportResult InstrumentHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ if(Companion::Instance->IsOTRMode()){
+ write << "static const ALIGN_ASSET(2) char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ write << "extern Instrument " << symbol << ";\n";
+
+ return std::nullopt;
+}
+
+ExportResult InstrumentCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ return std::nullopt;
+}
+
+ExportResult InstrumentBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto writer = LUS::BinaryWriter();
+ auto data = std::static_pointer_cast<InstrumentData>(raw);
+
+ WriteHeader(writer, Torch::ResourceType::Instrument, 0);
+ writer.Write(data->isRelocated);
+ writer.Write(data->normalRangeLo);
+ writer.Write(data->normalRangeHi);
+ writer.Write(data->adsrDecayIndex);
+ writer.Write(AudioContext::GetPathByAddr(data->envelope));
+ writer.Write(AudioContext::GetPathByAddr(data->lowPitchTunedSample.sample));
+ writer.Write(data->lowPitchTunedSample.tuning);
+ writer.Write(AudioContext::GetPathByAddr(data->normalPitchTunedSample.sample));
+ writer.Write(data->normalPitchTunedSample.tuning);
+ writer.Write(AudioContext::GetPathByAddr(data->highPitchTunedSample.sample));
+ writer.Write(data->highPitchTunedSample.tuning);
+
+ writer.Finish(write);
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> InstrumentFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
+ auto parent = GetSafeNode<uint32_t>(node, "parent");
+ auto sampleBankId = GetSafeNode<uint32_t>(node, "sampleBankId");
+
+ auto entry = AudioContext::tables[AudioTableType::FONT_TABLE].at(parent);
+
+ auto reader = AudioContext::MakeReader(AudioTableType::FONT_TABLE, offset);
+
+ auto instrument = std::make_shared<InstrumentData>();
+ instrument->isRelocated = reader.ReadUByte();
+ instrument->normalRangeLo = reader.ReadUByte();
+ instrument->normalRangeHi = reader.ReadUByte();
+ instrument->adsrDecayIndex = reader.ReadUByte();
+
+ auto envAddr = entry.addr + reader.ReadUInt32();
+ YAML::Node envelope;
+ envelope["type"] = "NAUDIO:V1:ENVELOPE";
+ envelope["offset"] = envAddr;
+ instrument->envelope = envAddr;
+ Companion::Instance->AddAsset(envelope);
+
+ instrument->lowPitchTunedSample = AudioContext::LoadTunedSample(reader, parent, sampleBankId);
+ instrument->normalPitchTunedSample = AudioContext::LoadTunedSample(reader, parent, sampleBankId);
+ instrument->highPitchTunedSample = AudioContext::LoadTunedSample(reader, parent, sampleBankId);
+
+ return instrument;
+}
diff --git a/src/factories/naudio/v1/InstrumentFactory.h b/src/factories/naudio/v1/InstrumentFactory.h
new file mode 100644
index 0000000..9d6ccf0
--- /dev/null
+++ b/src/factories/naudio/v1/InstrumentFactory.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <factories/BaseFactory.h>
+#include "AudioContext.h"
+
+class InstrumentData : public IParsedData {
+public:
+ uint8_t isRelocated;
+ uint8_t normalRangeLo;
+ uint8_t normalRangeHi;
+ uint8_t adsrDecayIndex;
+ uint32_t envelope;
+ TunedSample lowPitchTunedSample;
+ TunedSample normalPitchTunedSample;
+ TunedSample highPitchTunedSample;
+};
+
+class InstrumentHeaderExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class InstrumentBinaryExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class InstrumentCodeExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class InstrumentFactory : public BaseFactory {
+public:
+ std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
+ inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
+ return {
+ REGISTER(Header, InstrumentHeaderExporter)
+ REGISTER(Binary, InstrumentBinaryExporter)
+ REGISTER(Code, InstrumentCodeExporter)
+ };
+ }
+};
diff --git a/src/factories/naudio/v1/LoopFactory.cpp b/src/factories/naudio/v1/LoopFactory.cpp
new file mode 100644
index 0000000..522192e
--- /dev/null
+++ b/src/factories/naudio/v1/LoopFactory.cpp
@@ -0,0 +1,56 @@
+#include "LoopFactory.h"
+#include "utils/Decompressor.h"
+#include "Companion.h"
+
+ExportResult ADPCMLoopHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ if(Companion::Instance->IsOTRMode()){
+ write << "static const ALIGN_ASSET(2) char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ write << "extern AdpcmLoop " << symbol << ";\n";
+
+ return std::nullopt;
+}
+
+ExportResult ADPCMLoopCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ return std::nullopt;
+}
+
+ExportResult ADPCMLoopBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto writer = LUS::BinaryWriter();
+ auto data = std::static_pointer_cast<ADPCMLoopData>(raw);
+
+ WriteHeader(writer, Torch::ResourceType::AdpcmLoop, 0);
+ writer.Write(data->start);
+ writer.Write(data->end);
+ writer.Write(data->count);
+ if(data->count != 0){
+ for(size_t i = 0; i < 16; i++){
+ writer.Write(data->predictorState[i]);
+ }
+ }
+
+ writer.Finish(write);
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> ADPCMLoopFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
+ auto reader = AudioContext::MakeReader(AudioTableType::FONT_TABLE, offset);
+ auto loop = std::make_shared<ADPCMLoopData>();
+
+ loop->start = reader.ReadInt32();
+ loop->end = reader.ReadUInt32();
+ loop->count = reader.ReadUInt32();
+
+ if(loop->count != 0){
+ for(size_t i = 0; i < 16; i++){
+ loop->predictorState[i] = reader.ReadInt16();
+ }
+ }
+
+ return loop;
+}
diff --git a/src/factories/naudio/v1/LoopFactory.h b/src/factories/naudio/v1/LoopFactory.h
new file mode 100644
index 0000000..e281946
--- /dev/null
+++ b/src/factories/naudio/v1/LoopFactory.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <factories/BaseFactory.h>
+#include "AudioContext.h"
+
+class ADPCMLoopData : public IParsedData {
+public:
+ uint32_t start;
+ uint32_t end;
+ uint32_t count;
+ int16_t predictorState[16];
+};
+
+class ADPCMLoopHeaderExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class ADPCMLoopBinaryExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class ADPCMLoopCodeExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class ADPCMLoopFactory : public BaseFactory {
+public:
+ std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
+ inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
+ return {
+ REGISTER(Header, ADPCMLoopHeaderExporter)
+ REGISTER(Binary, ADPCMLoopBinaryExporter)
+ REGISTER(Code, ADPCMLoopCodeExporter)
+ };
+ }
+};
diff --git a/src/factories/naudio/v1/SampleFactory.cpp b/src/factories/naudio/v1/SampleFactory.cpp
new file mode 100644
index 0000000..cafbdd9
--- /dev/null
+++ b/src/factories/naudio/v1/SampleFactory.cpp
@@ -0,0 +1,81 @@
+#include "SampleFactory.h"
+#include "utils/Decompressor.h"
+#include "Companion.h"
+
+ExportResult NSampleHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ if(Companion::Instance->IsOTRMode()){
+ write << "static const ALIGN_ASSET(2) char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ write << "extern Sample " << symbol << ";\n";
+
+ return std::nullopt;
+}
+
+ExportResult NSampleCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ return std::nullopt;
+}
+
+ExportResult NSampleBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto writer = LUS::BinaryWriter();
+ auto data = std::static_pointer_cast<NSampleData>(raw);
+
+ WriteHeader(writer, Torch::ResourceType::Sample, 1);
+ writer.Write(data->codec);
+ writer.Write(data->medium);
+ writer.Write(data->unk);
+ writer.Write(data->size);
+
+ writer.Write(AudioContext::GetPathByAddr(data->loop));
+ writer.Write(AudioContext::GetPathByAddr(data->book));
+
+ auto entry = AudioContext::tableData[AudioTableType::SAMPLE_TABLE]->entries[data->sampleBankId];
+ auto buffer = AudioContext::data[AudioTableType::SAMPLE_TABLE];
+
+ writer.Write((uint32_t) data->size);
+ writer.Write((char*) buffer.data() + data->sampleAddr, data->size);
+
+ writer.Finish(write);
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> NSampleFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
+ auto parent = GetSafeNode<uint32_t>(node, "parent");
+ auto sampleBankId = GetSafeNode<uint32_t>(node, "sampleBankId");
+
+ auto entry = AudioContext::tables[AudioTableType::FONT_TABLE].at(parent);
+ auto reader = AudioContext::MakeReader(AudioTableType::FONT_TABLE, offset);
+
+ auto sample = std::make_shared<NSampleData>();
+
+ uint32_t flags = reader.ReadUInt32();
+ uint32_t addr = reader.ReadUInt32();
+
+ sample->codec = (flags >> 28) & 0x0F;
+ sample->medium = (flags >> 24) & 0x03;
+ sample->unk = (flags >> 22) & 0x01;
+ sample->size = flags;
+
+ auto loopAddr = entry.addr + reader.ReadUInt32();
+ YAML::Node loop;
+ loop["type"] = "NAUDIO:V1:ADPCM_LOOP";
+ loop["offset"] = loopAddr;
+ sample->loop = loopAddr;
+ Companion::Instance->AddAsset(loop);
+
+ auto bookAddr = entry.addr + reader.ReadUInt32();
+ YAML::Node book;
+ book["type"] = "NAUDIO:V1:ADPCM_BOOK";
+ book["offset"] = bookAddr;
+ sample->book = bookAddr;
+ Companion::Instance->AddAsset(book);
+
+ sample->sampleAddr = addr;
+ sample->sampleBankId = sampleBankId;
+
+ return sample;
+}
diff --git a/src/factories/naudio/v1/SampleFactory.h b/src/factories/naudio/v1/SampleFactory.h
new file mode 100644
index 0000000..3507188
--- /dev/null
+++ b/src/factories/naudio/v1/SampleFactory.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <factories/BaseFactory.h>
+#include "AudioContext.h"
+
+class NSampleData : public IParsedData {
+public:
+ uint32_t codec;
+ uint32_t medium;
+ uint32_t unk;
+ uint32_t isRelocated;
+ uint32_t size;
+ uint32_t sampleAddr;
+ uint32_t loop;
+ uint32_t book;
+ uint32_t sampleBankId;
+};
+
+class NSampleHeaderExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class NSampleBinaryExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class NSampleCodeExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class NSampleFactory : public BaseFactory {
+public:
+ std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
+ inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
+ return {
+ REGISTER(Header, NSampleHeaderExporter)
+ REGISTER(Binary, NSampleBinaryExporter)
+ REGISTER(Code, NSampleCodeExporter)
+ };
+ }
+};
diff --git a/src/factories/naudio/v1/SoundFontFactory.cpp b/src/factories/naudio/v1/SoundFontFactory.cpp
new file mode 100644
index 0000000..87870f8
--- /dev/null
+++ b/src/factories/naudio/v1/SoundFontFactory.cpp
@@ -0,0 +1,148 @@
+#include "SoundFontFactory.h"
+#include "AudioContext.h"
+#include "Companion.h"
+#include "spdlog/spdlog.h"
+#include "utils/Decompressor.h"
+
+ExportResult SoundFontHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ if(Companion::Instance->IsOTRMode()){
+ write << "static const ALIGN_ASSET(2) char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ write << "extern SoundFont " << symbol << ";\n";
+
+ return std::nullopt;
+}
+
+ExportResult SoundFontCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ // auto symbol = GetSafeNode(node, "symbol", entryName);
+ // auto offset = GetSafeNode<uint32_t>(node, "offset");
+ // auto data = std::static_pointer_cast<RawBuffer>(raw)->mBuffer;
+
+ // if(Companion::Instance->IsOTRMode()){
+ // write << "static const ALIGN_ASSET(2) char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ // return std::nullopt;
+ // }
+
+ // write << GetSafeNode<std::string>(node, "ctype", "u8") << " " << symbol << "[] = {\n" << tab_t;
+
+ // for (int i = 0; i < data.size(); i++) {
+ // if ((i % 15 == 0) && i != 0) {
+ // write << "\n" << tab_t;
+ // }
+
+ // write << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int) data[i] << ", ";
+ // }
+ // write << "\n};\n";
+
+ // if (Companion::Instance->IsDebug()) {
+ // write << "// size: 0x" << std::hex << std::uppercase << data.size() << "\n";
+ // }
+
+ // return offset + data.size();
+ return std::nullopt;
+}
+
+ExportResult SoundFontBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto writer = LUS::BinaryWriter();
+ auto data = std::static_pointer_cast<SoundFontData>(raw);
+
+ WriteHeader(writer, Torch::ResourceType::SoundFont, 0);
+ writer.Write(data->numInstruments);
+ writer.Write(data->numDrums);
+ writer.Write(data->sampleBankId1);
+ writer.Write(data->sampleBankId2);
+
+ for(auto& instrument : data->instruments){
+ auto crc = AudioContext::GetPathByAddr(instrument);
+ writer.Write(crc);
+ }
+
+ for(auto& drum : data->drums){
+ auto crc = AudioContext::GetPathByAddr(drum);
+ writer.Write(crc);
+ }
+
+ writer.Finish(write);
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> SoundFontFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
+ auto entry = AudioContext::tables[AudioTableType::FONT_TABLE].at(offset);
+ auto reader = AudioContext::MakeReader(AudioTableType::FONT_TABLE, entry.addr);
+ auto font = std::make_shared<SoundFontData>();
+
+ font->numInstruments = (entry.shortData2 >> 8) & 0xFFu;
+ font->numDrums = entry.shortData2 & 0xFFu;
+ font->sampleBankId1 = (entry.shortData1 >> 8) & 0xFFu;
+ font->sampleBankId2 = entry.shortData1 & 0xFFu;
+
+ uint32_t drumBaseAddr = reader.ReadUInt32();
+ uint32_t instBaseAddr = 4;
+
+ if(drumBaseAddr != 0){
+ reader.Seek(entry.addr + drumBaseAddr, LUS::SeekOffsetType::Start);
+ for(size_t i = 0; i < font->numDrums; i++){
+ uint32_t addr = reader.ReadUInt32();
+
+ if(addr == 0){
+ font->drums.push_back(0);
+ continue;
+ }
+
+ // SPDLOG_INFO("Found Drum[{}] 0x{:X}", i, addr);
+
+ YAML::Node drum;
+ drum["type"] = "NAUDIO:V1:DRUM";
+ drum["parent"] = entry.addr;
+ drum["offset"] = entry.addr + addr;
+ drum["sampleBankId"] = (uint32_t) font->sampleBankId1;
+
+ Companion::Instance->AddAsset(drum);
+ font->drums.push_back(entry.addr + addr);
+ }
+
+// YAML::Node table;
+// table["type"] = "ASSET_ARRAY";
+// table["assetType"] = "Drum";
+// table["factoryType"] = "NAUDIO:V1:DRUM";
+// table["offset"] = entry.addr + drumBaseAddr;
+// table["count"] = (uint32_t) font->numDrums;
+// Companion::Instance->AddAsset(table);
+ }
+
+ reader.Seek(entry.addr + instBaseAddr, LUS::SeekOffsetType::Start);
+ for(size_t i = 0; i < font->numInstruments; i++){
+ uint32_t addr = reader.ReadUInt32();
+
+ if(addr == 0){
+ font->instruments.push_back(0);
+ continue;
+ }
+
+ // SPDLOG_INFO("Found Instrument[{}] 0x{:X}", i, addr);
+
+ YAML::Node instrument;
+ instrument["type"] = "NAUDIO:V1:INSTRUMENT";
+ instrument["parent"] = entry.addr;
+ instrument["offset"] = entry.addr + addr;
+ instrument["sampleBankId"] = (uint32_t) font->sampleBankId1;
+ font->instruments.push_back(entry.addr + addr);
+
+ Companion::Instance->AddAsset(instrument);
+ }
+
+// YAML::Node table;
+// table["type"] = "ASSET_ARRAY";
+// table["assetType"] = "Instrument";
+// table["factoryType"] = "NAUDIO:V1:INSTRUMENT";
+// table["offset"] = entry.addr + instBaseAddr;
+// table["count"] = (uint32_t) font->numInstruments;
+// Companion::Instance->AddAsset(table);
+
+ return font;
+}
diff --git a/src/factories/naudio/v1/SoundFontFactory.h b/src/factories/naudio/v1/SoundFontFactory.h
new file mode 100644
index 0000000..8bb73e4
--- /dev/null
+++ b/src/factories/naudio/v1/SoundFontFactory.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <factories/BaseFactory.h>
+
+class SoundFontData : public IParsedData {
+public:
+ uint8_t numInstruments;
+ uint8_t numDrums;
+ uint8_t sampleBankId1;
+ uint8_t sampleBankId2;
+ std::vector<uint32_t> instruments;
+ std::vector<uint32_t> drums;
+};
+
+class SoundFontHeaderExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class SoundFontBinaryExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class SoundFontCodeExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class SoundFontFactory : public BaseFactory {
+public:
+ std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
+ inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
+ return {
+ REGISTER(Header, SoundFontHeaderExporter)
+ REGISTER(Binary, SoundFontBinaryExporter)
+ REGISTER(Code, SoundFontCodeExporter)
+ };
+ }
+};