mirror of
https://github.com/izzy2lost/Torch.git
synced 2026-07-06 00:18:35 -07:00
[WIP] Audio Extractor
This commit is contained in:
+8
-2
@@ -525,8 +525,6 @@
|
||||
"actors/yoshi_egg/yoshi_egg_5_unused.rgba16.png": [32,32,2048,{"jp":[1215456,32696],"us":[1222624,32696],"eu":[1094592,32696],"sh":[1071104,32696]}],
|
||||
"actors/yoshi_egg/yoshi_egg_6_unused.rgba16.png": [32,32,2048,{"jp":[1215456,34744],"us":[1222624,34744],"eu":[1094592,34744],"sh":[1071104,34744]}],
|
||||
"actors/yoshi_egg/yoshi_egg_7_unused.rgba16.png": [32,32,2048,{"jp":[1215456,36792],"us":[1222624,36792],"eu":[1094592,36792],"sh":[1071104,36792]}],
|
||||
"sound/sequences.aud": [114432, { "us": [8063072] }],
|
||||
"sound/bank_sets.aud": [159, { "us": [8177185] }],
|
||||
"assets/demos/bbh.bin": [988,{"jp":[5733368],"us":[5741664],"eu":[5620584],"sh":[5589632]}],
|
||||
"assets/demos/bitdw.bin": [1412,{"us":[5747100],"sh":[5595068]}],
|
||||
"assets/demos/ccm.bin": [1320,{"jp":[5734356],"us":[5742652],"eu":[5621572],"sh":[5590620]}],
|
||||
@@ -1088,6 +1086,7 @@
|
||||
"sound/sequences/sh/20_cutscene_ending.m64": [1887,{"sh":[7981824]}],
|
||||
"sound/sequences/sh/21_menu_file_select.m64": [786,{"sh":[7983712]}],
|
||||
"sound/sequences/sh/22_cutscene_lakitu.m64": [317,{"sh":[7984512]}],
|
||||
"sound/sequences/us/00_sound_player.m64": [13452,{"us":[8063360]}],
|
||||
"sound/sequences/us/01_cutscene_collect_star.m64": [619,{"us":[8076816]}],
|
||||
"sound/sequences/us/02_menu_title_screen.m64": [8254,{"us":[8077440]}],
|
||||
"sound/sequences/us/03_level_grass.m64": [5122,{"us":[8085696]}],
|
||||
@@ -1122,6 +1121,13 @@
|
||||
"sound/sequences/us/20_cutscene_ending.m64": [1882,{"us":[8174192]}],
|
||||
"sound/sequences/us/21_menu_file_select.m64": [781,{"us":[8176080]}],
|
||||
"sound/sequences/us/22_cutscene_lakitu.m64": [313,{"us":[8176864]}],
|
||||
"@sound.aiff": {
|
||||
"us": {
|
||||
"bank_sets": [8177184, 160],
|
||||
"sound_ctl": [5748512, 97856],
|
||||
"sound_tbl": [5846368, 2216704]
|
||||
}
|
||||
},
|
||||
"textures/cave/hmc_textures.00000.rgba16.png": [32,64,4096,{"jp":[3432432,0],"us":[3439184,0],"eu":[3312784,0],"sh":[3287152,0]}],
|
||||
"textures/cave/hmc_textures.01000.rgba16.png": [32,32,2048,{"jp":[3432432,4096],"us":[3439184,4096],"eu":[3312784,4096],"sh":[3287152,4096]}],
|
||||
"textures/cave/hmc_textures.01800.rgba16.png": [32,64,4096,{"jp":[3432432,6144],"us":[3439184,6144],"eu":[3312784,6144],"sh":[3287152,6144]}],
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
#include "align_asset_macro.h"
|
||||
|
||||
#define dgSequence01 "__OTR__sound/sequences/01_cutscene_collect_star.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence01[] = dgSequence01;
|
||||
|
||||
#define dgSequence02 "__OTR__sound/sequences/02_menu_title_screen.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence02[] = dgSequence02;
|
||||
|
||||
#define dgSequence03 "__OTR__sound/sequences/03_level_grass.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence03[] = dgSequence03;
|
||||
|
||||
#define dgSequence04 "__OTR__sound/sequences/04_level_inside_castle.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence04[] = dgSequence04;
|
||||
|
||||
#define dgSequence05 "__OTR__sound/sequences/05_level_water.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence05[] = dgSequence05;
|
||||
|
||||
#define dgSequence06 "__OTR__sound/sequences/06_level_hot.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence06[] = dgSequence06;
|
||||
|
||||
#define dgSequence07 "__OTR__sound/sequences/07_level_boss_koopa.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence07[] = dgSequence07;
|
||||
|
||||
#define dgSequence08 "__OTR__sound/sequences/08_level_snow.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence08[] = dgSequence08;
|
||||
|
||||
#define dgSequence09 "__OTR__sound/sequences/09_level_slide.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence09[] = dgSequence09;
|
||||
|
||||
#define dgSequence0A "__OTR__sound/sequences/0A_level_spooky.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence0A[] = dgSequence0A;
|
||||
|
||||
#define dgSequence0B "__OTR__sound/sequences/0B_event_piranha_plant.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence0B[] = dgSequence0B;
|
||||
|
||||
#define dgSequence0C "__OTR__sound/sequences/0C_level_underground.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence0C[] = dgSequence0C;
|
||||
|
||||
#define dgSequence0D "__OTR__sound/sequences/0D_menu_star_select.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence0D[] = dgSequence0D;
|
||||
|
||||
#define dgSequence0E "__OTR__sound/sequences/0E_event_powerup.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence0E[] = dgSequence0E;
|
||||
|
||||
#define dgSequence0F "__OTR__sound/sequences/0F_event_metal_cap.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence0F[] = dgSequence0F;
|
||||
|
||||
#define dgSequence10 "__OTR__sound/sequences/10_event_koopa_message.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence10[] = dgSequence10;
|
||||
|
||||
#define dgSequence11 "__OTR__sound/sequences/11_level_koopa_road.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence11[] = dgSequence11;
|
||||
|
||||
#define dgSequence12 "__OTR__sound/sequences/12_event_high_score.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence12[] = dgSequence12;
|
||||
|
||||
#define dgSequence13 "__OTR__sound/sequences/13_event_merry_go_round.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence13[] = dgSequence13;
|
||||
|
||||
#define dgSequence14 "__OTR__sound/sequences/14_event_race.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence14[] = dgSequence14;
|
||||
|
||||
#define dgSequence15 "__OTR__sound/sequences/15_cutscene_star_spawn.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence15[] = dgSequence15;
|
||||
|
||||
#define dgSequence16 "__OTR__sound/sequences/16_event_boss.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence16[] = dgSequence16;
|
||||
|
||||
#define dgSequence17 "__OTR__sound/sequences/17_cutscene_collect_key.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence17[] = dgSequence17;
|
||||
|
||||
#define dgSequence18 "__OTR__sound/sequences/18_event_endless_stairs.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence18[] = dgSequence18;
|
||||
|
||||
#define dgSequence19 "__OTR__sound/sequences/19_level_boss_koopa_final.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence19[] = dgSequence19;
|
||||
|
||||
#define dgSequence1A "__OTR__sound/sequences/1A_cutscene_credits.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence1A[] = dgSequence1A;
|
||||
|
||||
#define dgSequence1B "__OTR__sound/sequences/1B_event_solve_puzzle.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence1B[] = dgSequence1B;
|
||||
|
||||
#define dgSequence1C "__OTR__sound/sequences/1C_event_toad_message.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence1C[] = dgSequence1C;
|
||||
|
||||
#define dgSequence1D "__OTR__sound/sequences/1D_event_peach_message.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence1D[] = dgSequence1D;
|
||||
|
||||
#define dgSequence1E "__OTR__sound/sequences/1E_cutscene_intro.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence1E[] = dgSequence1E;
|
||||
|
||||
#define dgSequence1F "__OTR__sound/sequences/1F_cutscene_victory.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence1F[] = dgSequence1F;
|
||||
|
||||
#define dgSequence20 "__OTR__sound/sequences/20_cutscene_ending.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence20[] = dgSequence20;
|
||||
|
||||
#define dgSequence21 "__OTR__sound/sequences/21_menu_file_select.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence21[] = dgSequence21;
|
||||
|
||||
#define dgSequence22 "__OTR__sound/sequences/22_cutscene_lakitu.m64"
|
||||
static const ALIGN_ASSET(2) char gSequence22[] = dgSequence22;
|
||||
|
||||
static const char* gSequenceTable[] = {
|
||||
gSequence01,
|
||||
gSequence02,
|
||||
gSequence03,
|
||||
gSequence04,
|
||||
gSequence05,
|
||||
gSequence06,
|
||||
gSequence07,
|
||||
gSequence08,
|
||||
gSequence09,
|
||||
gSequence0A,
|
||||
gSequence0B,
|
||||
gSequence0C,
|
||||
gSequence0D,
|
||||
gSequence0E,
|
||||
gSequence0F,
|
||||
gSequence10,
|
||||
gSequence11,
|
||||
gSequence12,
|
||||
gSequence13,
|
||||
gSequence14,
|
||||
gSequence15,
|
||||
gSequence16,
|
||||
gSequence17,
|
||||
gSequence18,
|
||||
gSequence19,
|
||||
gSequence1A,
|
||||
gSequence1B,
|
||||
gSequence1C,
|
||||
gSequence1D,
|
||||
gSequence1E,
|
||||
gSequence1F,
|
||||
gSequence20,
|
||||
gSequence21,
|
||||
gSequence22,
|
||||
};
|
||||
+9
-5
@@ -4,6 +4,7 @@
|
||||
#include "utils/MIODecoder.h"
|
||||
#include "factories/RawFactory.h"
|
||||
#include "factories/BlobFactory.h"
|
||||
#include "factories/AudioFactory.h"
|
||||
#include "factories/TextureFactory.h"
|
||||
#include "factories/AnimFactory.h"
|
||||
|
||||
@@ -18,9 +19,10 @@ namespace fs = std::filesystem;
|
||||
static const std::unordered_map<std::string, RawFactory*> gFactories = {
|
||||
{ ".png", new TextureFactory() },
|
||||
{ ".anim", new AnimFactory() },
|
||||
{ ".aiff", new AudioFactory() },
|
||||
{ ".bin", new BlobFactory(LUS::ResourceType::Blob) },
|
||||
{ ".m64", new BlobFactory(LUS::ResourceType::Blob) },
|
||||
{ ".sbox", new BlobFactory(LUS::ResourceType::Blob, true) },
|
||||
{ ".aud", new BlobFactory(LUS::ResourceType::Blob, false) },
|
||||
};
|
||||
|
||||
void Companion::Start() {
|
||||
@@ -45,7 +47,7 @@ void Companion::ProcessAssets() {
|
||||
for( auto& [asset, data] : assets.items() ) {
|
||||
std::string extension = fs::path(asset).extension().string();
|
||||
if( gFactories.find(extension) == gFactories.end() ) {
|
||||
std::cout << "No factory found for " << asset << '\n';
|
||||
// std::cout << "No factory found for " << asset << '\n';
|
||||
continue;
|
||||
}
|
||||
LUS::BinaryWriter write = LUS::BinaryWriter();
|
||||
@@ -57,7 +59,7 @@ void Companion::ProcessAssets() {
|
||||
RawFactory* factory = gFactories.at(extension);
|
||||
|
||||
if(!factory->process(&write, entry, this->gRomData)){
|
||||
std::cout << "Failed to process " << asset << '\n';
|
||||
// std::cout << "Failed to process " << asset << '\n';
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -70,13 +72,15 @@ void Companion::ProcessAssets() {
|
||||
if(!isTexture) {
|
||||
// Write to file too
|
||||
std::string dpath = "debug/" + path;
|
||||
fs::create_directories(fs::path(dpath).parent_path());
|
||||
if(!fs::exists(fs::path(dpath).parent_path())){
|
||||
fs::create_directories(fs::path(dpath).parent_path());
|
||||
}
|
||||
std::ofstream output(dpath, std::ios::binary);
|
||||
output.write((char*)buffer.data(), buffer.size());
|
||||
output.close();
|
||||
}
|
||||
|
||||
std::cout << "Processed " << path << std::endl;
|
||||
// std::cout << "Processed " << path << std::endl;
|
||||
|
||||
write.Close();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
#include "AudioFactory.h"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
#include "Companion.h"
|
||||
#include "utils/MIODecoder.h"
|
||||
#include "binarytools/BinaryReader.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
#define NONE 0xFFFF
|
||||
|
||||
std::unordered_map<std::string, uint32_t> nameTable;
|
||||
|
||||
struct ALSeqData {
|
||||
uint8_t *offset;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
struct Entry {
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
struct SampleBank {
|
||||
std::string name;
|
||||
uint32_t offset;
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
struct TBLFile {
|
||||
std::vector<SampleBank> banks;
|
||||
std::vector<std::string> tbls;
|
||||
std::unordered_map<std::string, uint32_t> map;
|
||||
};
|
||||
|
||||
struct CTLHeader {
|
||||
uint32_t instruments;
|
||||
uint32_t numDrums;
|
||||
uint32_t shared;
|
||||
};
|
||||
|
||||
struct Sound {
|
||||
int32_t offset;
|
||||
float tuning;
|
||||
};
|
||||
|
||||
struct Bank {
|
||||
std::string name;
|
||||
SampleBank sampleBank;
|
||||
};
|
||||
|
||||
struct Inst {
|
||||
std::string name;
|
||||
uint32_t offset;
|
||||
uint8_t releaseRate;
|
||||
uint8_t normalRangeLo;
|
||||
uint8_t normalRangeHi;
|
||||
int32_t envelope;
|
||||
std::optional<Sound> soundLo;
|
||||
std::optional<Sound> soundMed;
|
||||
std::optional<Sound> soundHi;
|
||||
};
|
||||
|
||||
struct Drum {
|
||||
std::string name;
|
||||
uint32_t offset;
|
||||
uint8_t releaseRate;
|
||||
uint8_t pan;
|
||||
int32_t envelope;
|
||||
Sound sound;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> slice(std::vector<T> const &v, uint32_t m, uint32_t n) {
|
||||
auto first = v.cbegin() + m;
|
||||
auto last = v.cbegin() + n;
|
||||
|
||||
std::vector<T> vec(first, last);
|
||||
return vec;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> range(uint32_t start, uint32_t end) {
|
||||
std::vector<uint32_t> result;
|
||||
for (uint32_t i = start; i < end; ++i) {
|
||||
result.push_back(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
std::vector<std::tuple<size_t, T2, T3>> zip(const std::vector<T1>& container1, const std::vector<T2>& container2, const std::vector<T3>& container3) {
|
||||
std::vector<std::tuple<size_t, T2, T3>> result;
|
||||
|
||||
size_t minSize = std::min({container1.size(), container2.size(), container3.size()});
|
||||
|
||||
for (size_t i = 0; i < minSize; ++i) {
|
||||
result.emplace_back(container1[i], container2[i], container3[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Entry> parseSeqFile(std::vector<uint8_t>& buffer, int32_t offset){
|
||||
std::vector<Entry> entries;
|
||||
LUS::BinaryReader reader((char*) buffer.data(), buffer.size());
|
||||
reader.SetEndianness(LUS::Endianness::Big);
|
||||
reader.Seek(offset, LUS::SeekOffsetType::Start);
|
||||
|
||||
uint16_t magic = reader.ReadUInt16();
|
||||
uint16_t num_entries = reader.ReadUInt16();
|
||||
|
||||
for (int i = 0; i < num_entries; ++i) {
|
||||
reader.Seek((offset + 4) + (i * 8), LUS::SeekOffsetType::Start);
|
||||
entries.push_back({reader.ReadUInt32(), reader.ReadUInt32()});
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
return entries;
|
||||
}
|
||||
|
||||
CTLHeader parseCTLHeader(std::vector<uint8_t>& data){
|
||||
LUS::BinaryReader reader((char*) data.data(), data.size());
|
||||
reader.SetEndianness(LUS::Endianness::Big);
|
||||
|
||||
CTLHeader header = { reader.ReadUInt32(), reader.ReadUInt32(), reader.ReadUInt32() };
|
||||
|
||||
reader.Close();
|
||||
return header;
|
||||
}
|
||||
|
||||
std::string gen_name(const std::string& prefix){
|
||||
if(!nameTable.contains(prefix)){
|
||||
nameTable[prefix] = 0;
|
||||
}
|
||||
nameTable[prefix] += 1;
|
||||
return prefix + "-" + std::to_string(nameTable[prefix]);
|
||||
}
|
||||
|
||||
std::optional<Sound> parseSound(std::vector<uint8_t> data) {
|
||||
LUS::BinaryReader reader((char*) data.data(), data.size());
|
||||
reader.SetEndianness(LUS::Endianness::Big);
|
||||
|
||||
int32_t addr = reader.ReadInt32();
|
||||
float tuning = reader.ReadFloat();
|
||||
|
||||
if(addr == 0){
|
||||
assert(tuning == 0.0f);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Sound sound = { addr, tuning };
|
||||
|
||||
reader.Close();
|
||||
return sound;
|
||||
}
|
||||
|
||||
Drum parseDrum(std::vector<uint8_t>& data, uint32_t addr) {
|
||||
LUS::BinaryReader reader((char*) data.data(), data.size());
|
||||
reader.SetEndianness(LUS::Endianness::Big);
|
||||
std::string name = gen_name("drum");
|
||||
|
||||
uint8_t releaseRate = reader.ReadInt8();
|
||||
uint8_t pan = reader.ReadInt8();
|
||||
|
||||
reader.Seek(12, LUS::SeekOffsetType::Start);
|
||||
Sound sound = parseSound(slice(data, 4, 12)).value();
|
||||
int32_t envOffset = reader.ReadInt32();
|
||||
assert(envOffset != 0);
|
||||
|
||||
Drum drum = { name, addr, releaseRate, pan, envOffset, sound };
|
||||
|
||||
return drum;
|
||||
}
|
||||
|
||||
Inst parseInst(std::vector<uint8_t>& data, uint32_t addr) {
|
||||
std::string name = gen_name("inst");
|
||||
char* rawData = (char*) data.data();
|
||||
uint8_t normalRangeLo = data[1];
|
||||
uint8_t normalRangeHi = data[2];
|
||||
uint8_t releaseRate = data[3];
|
||||
|
||||
int32_t envAddr;
|
||||
memcpy(&envAddr, rawData + 4, 4);
|
||||
envAddr = BSWAP32(envAddr);
|
||||
|
||||
auto soundLo = parseSound(slice(data, 8, 16));
|
||||
auto soundMed = parseSound(slice(data, 16, 24));
|
||||
auto soundHi = parseSound(slice(data, 24, 32));
|
||||
|
||||
if (soundLo == std::nullopt) {
|
||||
assert(normalRangeLo == 0);
|
||||
}
|
||||
if (soundHi == std::nullopt) {
|
||||
assert(normalRangeHi == 127);
|
||||
}
|
||||
|
||||
Inst inst = { name, addr, releaseRate, normalRangeLo, normalRangeHi, envAddr, soundLo, soundMed, soundHi };
|
||||
return inst;
|
||||
}
|
||||
|
||||
void parseCTL(CTLHeader header, std::vector<uint8_t>& data, SampleBank bank, uint32_t index) {
|
||||
nameTable.clear();
|
||||
std::ostringstream ss;
|
||||
ss << std::hex << std::setw(2) << std::setfill('0') << index;
|
||||
std::string name = ss.str();
|
||||
uint32_t numInstruments = header.instruments;
|
||||
uint32_t numDrums = header.numDrums;
|
||||
char* rawData = (char*) data.data();
|
||||
|
||||
uint32_t drumBaseAddr;
|
||||
memcpy(&drumBaseAddr, rawData, 4);
|
||||
drumBaseAddr = BSWAP32(drumBaseAddr);
|
||||
|
||||
std::vector<uint32_t> drumOffsets;
|
||||
|
||||
if(numDrums != 0){
|
||||
for (size_t i = 0; i < numDrums; ++i) {
|
||||
uint32_t drumOffset;
|
||||
memcpy(&drumOffset, rawData + drumBaseAddr + (i * 4), 4);
|
||||
drumOffsets.push_back(BSWAP32(drumOffset));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if(instOffset == 0){
|
||||
instrumentList.push_back(NONE);
|
||||
} else {
|
||||
instrumentOffsets.push_back(instOffset);
|
||||
instrumentList.push_back(instOffset);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(instrumentOffsets.begin(), instrumentOffsets.end());
|
||||
|
||||
std::vector<Inst> insts;
|
||||
for(auto &offset : instrumentOffsets){
|
||||
auto rInst = slice(data, offset, offset + 32);
|
||||
Inst inst = parseInst(rInst, offset);
|
||||
insts.push_back(inst);
|
||||
}
|
||||
|
||||
std::vector<Drum> drums;
|
||||
for(auto &offset : drumOffsets){
|
||||
auto rDrum = slice(data, offset, offset + 16);
|
||||
Drum drum = parseDrum(rDrum, offset);
|
||||
drums.push_back(drum);
|
||||
}
|
||||
}
|
||||
|
||||
TBLFile parseTBL(std::vector<uint8_t>& data, std::vector<Entry>& entries) {
|
||||
TBLFile tbl;
|
||||
std::unordered_map<uint32_t, std::string> cache;
|
||||
for(auto &entry : entries){
|
||||
if(!cache.contains(entry.offset)){
|
||||
std::string name = gen_name("sample_bank");
|
||||
tbl.banks.push_back({name, entry.offset, slice(data, entry.offset, entry.offset + entry.length)});
|
||||
tbl.map[name] = tbl.banks.size() - 1;
|
||||
cache[entry.offset] = name;
|
||||
}
|
||||
tbl.tbls.push_back(cache[entry.offset]);
|
||||
}
|
||||
cache.clear();
|
||||
return tbl;
|
||||
}
|
||||
|
||||
bool AudioFactory::process(LUS::BinaryWriter* writer, nlohmann::json& data, std::vector<uint8_t>& buffer) {
|
||||
auto metadata = data["offsets"];
|
||||
std::string path = data["path"];
|
||||
|
||||
if(path.find("@sound") != std::string::npos){
|
||||
auto offsets = metadata["us"];
|
||||
std::vector<Entry> tbl = parseSeqFile(buffer, offsets["sound_tbl"][0]);
|
||||
std::vector<Entry> ctl = parseSeqFile(buffer, offsets["sound_ctl"][0]);
|
||||
|
||||
std::cout << "Table entries: " << tbl.size() << std::endl;
|
||||
std::cout << "Control entries: " << ctl.size() << std::endl;
|
||||
|
||||
std::vector<uint8_t> tblData = slice(buffer, offsets["sound_tbl"][0], (size_t) offsets["sound_tbl"][0] + (size_t) offsets["sound_tbl"][1]);
|
||||
std::vector<uint8_t> ctlData = slice(buffer, offsets["sound_ctl"][0], (size_t) offsets["sound_ctl"][0] + (size_t) offsets["sound_ctl"][1]);
|
||||
TBLFile tblFile = parseTBL(tblData, tbl);
|
||||
|
||||
std::cout << "TBLs: " << tblFile.tbls.size() << std::endl;
|
||||
std::cout << "Banks: " << tblFile.banks.size() << std::endl;
|
||||
std::cout << "Map: " << tblFile.map.size() << std::endl;
|
||||
|
||||
auto zipped = zip(range(0, ctl.size()), ctl, tblFile.tbls);
|
||||
|
||||
for (const auto& item : zipped) {
|
||||
auto [index, ctrl, sample_bank_name] = item;
|
||||
auto sample_bank = tblFile.map[sample_bank_name];
|
||||
auto entry = slice(ctlData, ctrl.offset, ctrl.offset + ctrl.length);
|
||||
auto headerRaw = slice(entry, 0, 16);
|
||||
auto header = parseCTLHeader(headerRaw);
|
||||
std::cout << "Instruments: " << header.instruments << std::endl;
|
||||
std::cout << "Drums: " << header.numDrums << std::endl;
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(path.find("bank_sets") != std::string::npos){
|
||||
WRITE_HEADER(LUS::ResourceType::Blob, 0);
|
||||
char* raw = (char*) (buffer.data() + metadata[1]["us"][0]);
|
||||
WRITE_U32(metadata[0]);
|
||||
for(int i = 0; i < 0x23; i++){
|
||||
int16_t value;
|
||||
memcpy(&value, raw + (i * 2), 2);
|
||||
WRITE_I16(BSWAP16(value));
|
||||
}
|
||||
writer->Write(raw + 0x46, 0x5A);
|
||||
}
|
||||
|
||||
if(path.find("sound_tbl") != std::string::npos){
|
||||
// WRITE_HEADER(LUS::ResourceType::Blob, 0);
|
||||
// std::vector<Entry> entries = parseSeqFile(buffer, metadata[1]["us"][0]);
|
||||
// for(auto & entry : entries){
|
||||
// std::cout << "Offset: " << entrie.offset << std::endl;
|
||||
// std::cout << "Len: " << entrie.length << std::endl;
|
||||
// }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "RawFactory.h"
|
||||
|
||||
class AudioFactory : public RawFactory {
|
||||
public:
|
||||
AudioFactory() = default;
|
||||
bool process(LUS::BinaryWriter* write, nlohmann::json& data, std::vector<uint8_t>& buffer) override;
|
||||
};
|
||||
@@ -13,11 +13,7 @@ bool BlobFactory::process(LUS::BinaryWriter* writer, nlohmann::json& data, std::
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this->bigEndian){
|
||||
WRITE_BHEADER(this->type, 0);
|
||||
} else {
|
||||
WRITE_HEADER(this->type, 0);
|
||||
}
|
||||
WRITE_HEADER(this->type, 0);
|
||||
|
||||
size_t size = metadata[0];
|
||||
auto offsets = metadata[1]["us"];
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define WRITE_U16(value) writer->Write((uint16_t) value)
|
||||
#define WRITE_U32(value) writer->Write((uint32_t) value)
|
||||
#define WRITE_U64(value) writer->Write((uint64_t) value)
|
||||
#define WRITE_I8(value) writer->Write((int8_t) value)
|
||||
#define WRITE_I16(value) writer->Write((int16_t) value)
|
||||
#define WRITE_DATA(vec) writer->Write((char*) vec.data(), data.size())
|
||||
#define WRITE_ARRAY(data, size) writer->Write((char*) data, size)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const bytes = fs.readFileSync('./baserom.us.z64');
|
||||
const bpath = '../sound/sequences/us/'
|
||||
const header = [
|
||||
'#pragma once',
|
||||
'#include "align_asset_macro.h"',
|
||||
'',
|
||||
]
|
||||
const sequences = []
|
||||
|
||||
fs.readdirSync(bpath).forEach(seq => {
|
||||
const seqData = fs.readFileSync(bpath+seq);
|
||||
const seqOffset = bytes.indexOf(seqData);
|
||||
const output = `sound/sequences/${seq}`
|
||||
const seqId = seq.split("_")[0]
|
||||
console.log(`"${output}": ${JSON.stringify([
|
||||
seqData.length,
|
||||
{ "us": [ seqOffset ]}
|
||||
])},`);
|
||||
sequences.push(`gSequence${seqId}`);
|
||||
header.push(`#define dgSequence${seqId} "__OTR__${output}"`);
|
||||
header.push(`static const ALIGN_ASSET(2) char gSequence${seqId}[] = dgSequence${seqId};\n`);
|
||||
});
|
||||
|
||||
header.push('static const char* gSequenceTable[] = {');
|
||||
for (const seq of sequences.sort((a, b) => b.localeCompare(a))) {
|
||||
header.push(` ${seq},`);
|
||||
}
|
||||
header.push('};\n');
|
||||
|
||||
fs.writeFileSync('./sequences_table.h', header.join('\n'));
|
||||
Reference in New Issue
Block a user