diff options
| author | KiritoDv <kiritodev01@gmail.com> | 2023-08-30 21:26:38 -0600 |
|---|---|---|
| committer | KiritoDv <kiritodev01@gmail.com> | 2023-08-30 21:26:38 -0600 |
| commit | 3bb2a8a13c4ff3b637bf02b9c01d632585b269bb (patch) | |
| tree | 398fb7b62ccd5f703a61507723d8f79936174396 | |
| parent | f5cbd0056d601e4adaf5ed9006192dd510226ee3 (diff) | |
[WIP] Audio Extractor
| -rw-r--r-- | assets.json | 10 | ||||
| -rw-r--r-- | sequences_table.h | 141 | ||||
| -rw-r--r-- | src/Companion.cpp | 14 | ||||
| -rw-r--r-- | src/factories/AudioFactory.cpp | 333 | ||||
| -rw-r--r-- | src/factories/AudioFactory.h | 9 | ||||
| -rw-r--r-- | src/factories/BlobFactory.cpp | 6 | ||||
| -rw-r--r-- | src/factories/RawFactory.h | 1 | ||||
| -rw-r--r-- | tools/m64test.js | 32 |
8 files changed, 534 insertions, 12 deletions
diff --git a/assets.json b/assets.json index 2db3c3b..7ee9491 100644 --- a/assets.json +++ b/assets.json @@ -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]}], diff --git a/sequences_table.h b/sequences_table.h new file mode 100644 index 0000000..f252b20 --- /dev/null +++ b/sequences_table.h @@ -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, +}; diff --git a/src/Companion.cpp b/src/Companion.cpp index 16d6c11..218f018 100644 --- a/src/Companion.cpp +++ b/src/Companion.cpp @@ -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(); } diff --git a/src/factories/AudioFactory.cpp b/src/factories/AudioFactory.cpp new file mode 100644 index 0000000..62ff3d3 --- /dev/null +++ b/src/factories/AudioFactory.cpp @@ -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; +} diff --git a/src/factories/AudioFactory.h b/src/factories/AudioFactory.h new file mode 100644 index 0000000..fdfdb9c --- /dev/null +++ b/src/factories/AudioFactory.h @@ -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; +};
\ No newline at end of file diff --git a/src/factories/BlobFactory.cpp b/src/factories/BlobFactory.cpp index 7071a45..30714b1 100644 --- a/src/factories/BlobFactory.cpp +++ b/src/factories/BlobFactory.cpp @@ -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"]; diff --git a/src/factories/RawFactory.h b/src/factories/RawFactory.h index 7057740..fe6ec98 100644 --- a/src/factories/RawFactory.h +++ b/src/factories/RawFactory.h @@ -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) diff --git a/tools/m64test.js b/tools/m64test.js new file mode 100644 index 0000000..0e4a6f3 --- /dev/null +++ b/tools/m64test.js @@ -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'));
\ No newline at end of file |
