From 941c19f2c33a0d1af75a10a64fe0905387d1e440 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Wed, 1 Jun 2022 13:06:32 -0400 Subject: Audio decompiled and WIP custom sample support --- ZAPDTR/ZAPD/Main.cpp | 2 +- ZAPDTR/ZAPD/ZAPD.vcxproj | 3 + ZAPDTR/ZAPD/ZAPD.vcxproj.filters | 9 + ZAPDTR/ZAPD/ZAudio.cpp | 325 +++++++++++++++++++ ZAPDTR/ZAPD/ZAudio.h | 122 +++++++ ZAPDTR/ZAPD/ZAudioDecode.cpp | 669 +++++++++++++++++++++++++++++++++++++++ ZAPDTR/ZAPD/ZResource.h | 3 +- ZAPDTR/ZAPD/ZRom.cpp | 2 + 8 files changed, 1133 insertions(+), 2 deletions(-) create mode 100644 ZAPDTR/ZAPD/ZAudio.cpp create mode 100644 ZAPDTR/ZAPD/ZAudio.h create mode 100644 ZAPDTR/ZAPD/ZAudioDecode.cpp (limited to 'ZAPDTR') diff --git a/ZAPDTR/ZAPD/Main.cpp b/ZAPDTR/ZAPD/Main.cpp index 65a65fea6..a9f70eed5 100644 --- a/ZAPDTR/ZAPD/Main.cpp +++ b/ZAPDTR/ZAPD/Main.cpp @@ -39,7 +39,7 @@ extern "C" void Audio_SetGameVolume(int player_id, float volume) extern "C" int ResourceMgr_OTRSigCheck(char* imgData) { - + return 0; } void DebugConsole_SaveCVars() diff --git a/ZAPDTR/ZAPD/ZAPD.vcxproj b/ZAPDTR/ZAPD/ZAPD.vcxproj index 91ff515a2..940d3b2ed 100644 --- a/ZAPDTR/ZAPD/ZAPD.vcxproj +++ b/ZAPDTR/ZAPD/ZAPD.vcxproj @@ -195,6 +195,8 @@ + + @@ -288,6 +290,7 @@ + diff --git a/ZAPDTR/ZAPD/ZAPD.vcxproj.filters b/ZAPDTR/ZAPD/ZAPD.vcxproj.filters index c122b7e56..82fa8acb2 100644 --- a/ZAPDTR/ZAPD/ZAPD.vcxproj.filters +++ b/ZAPDTR/ZAPD/ZAPD.vcxproj.filters @@ -297,6 +297,12 @@ Source Files + + Source Files\Z64 + + + Source Files\Z64 + @@ -569,6 +575,9 @@ Header Files\Libraries + + Header Files\Z64 + diff --git a/ZAPDTR/ZAPD/ZAudio.cpp b/ZAPDTR/ZAPD/ZAudio.cpp new file mode 100644 index 000000000..1c24c824a --- /dev/null +++ b/ZAPDTR/ZAPD/ZAudio.cpp @@ -0,0 +1,325 @@ +#include "ZAudio.h" + +#include "Globals.h" +#include "Utils/BitConverter.h" +#include "Utils/File.h" +#include "Utils/Path.h" +#include "Utils/StringHelper.h" +#include "ZFile.h" + +REGISTER_ZFILENODE(Audio, ZAudio); + +ZAudio::ZAudio(ZFile* nParent) : ZResource(nParent) +{ + //RegisterRequiredAttribute("CodeOffset"); + //RegisterOptionalAttribute("LangOffset", "0"); +} + +void ZAudio::DecodeADPCMSample(SampleEntry* sample) +{ + int16_t buffer[1024 * 128]; + + int16_t* out = &buffer[0]; +} + +std::vector ZAudio::ParseEnvelopeData(std::vector audioBank, std::vector audioTable, int envelopeOffset, int baseOffset) +{ + std::vector result; + + //bool process = true; + + //for (int i = 0; i < 4; i++) + while (true) + { + AdsrEnvelope* env = new AdsrEnvelope(); + + env->delay = BitConverter::ToInt16BE(audioBank, envelopeOffset + 0); + env->arg = BitConverter::ToInt16BE(audioBank, envelopeOffset + 2); + + envelopeOffset += 4; + + result.push_back(env); + + if (env->delay < 0) + break; + } + + return result; +} + +SoundFontEntry* ZAudio::ParseSoundFontEntry(std::vector audioBank, + std::vector audioTable, + AudioTableEntry audioSampleBankEntry, + int soundFontOffset, + int baseOffset) +{ + SoundFontEntry* soundFont = new SoundFontEntry(); + soundFont->sampleEntry = ParseSampleEntry( + audioBank, audioTable, audioSampleBankEntry, + BitConverter::ToInt32BE(audioBank, soundFontOffset + 0) + baseOffset, baseOffset); + soundFont->tuning = BitConverter::ToFloatBE(audioBank, soundFontOffset + 4); + + return soundFont; +} + +SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, + std::vector audioTable, + AudioTableEntry audioSampleBankEntry, + int sampleOffset, + int baseOffset) +{ + int sampleDataOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 4) + audioSampleBankEntry.ptr; + + if (samples.find(sampleOffset) == samples.end()) + { + SampleEntry* sample = new SampleEntry(); + + int sampleSize = BitConverter::ToInt32BE(audioBank, sampleOffset + 0) & 0x00FFFFFF; + int loopOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 8) + baseOffset; + int bookOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 12) + baseOffset; + + char* sampleData = (char*)malloc(sampleSize); + memcpy(sampleData, audioTable.data() + sampleDataOffset, sampleSize); + sample->data = std::vector(sampleSize); + memcpy(sample->data.data(), sampleData, sampleSize); + + uint32_t origField = (BitConverter::ToUInt32BE(audioBank, sampleOffset + 0)); + sample->codec = (origField >> 28) & 0x0F; + sample->medium = (origField >> 24) & 0x03; + sample->unk_bit26 = (origField >> 22) & 0x01; + sample->unk_bit25 = (origField >> 21) & 0x01; + + sample->loop.start = BitConverter::ToInt32BE(audioBank, loopOffset + 0); + sample->loop.end = BitConverter::ToInt32BE(audioBank, loopOffset + 4); + sample->loop.count = BitConverter::ToInt32BE(audioBank, loopOffset + 8); + + if (sample->loop.count != 0xFFFFFFFF) + { + for (int i = 0; i < sample->loop.count; i++) + { + int16_t state = BitConverter::ToInt16BE(sample->data, loopOffset + 16 + (i * 2)); + sample->loop.states.push_back(state); + } + } + + sample->book.order = BitConverter::ToInt32BE(audioBank, bookOffset + 0); + sample->book.npredictors = BitConverter::ToInt32BE(audioBank, bookOffset + 4); + + for (int i = 0; i < sample->book.npredictors * sample->book.order * 8; i++) + { + sample->book.books.push_back( + BitConverter::ToInt16BE(audioBank, bookOffset + 8 + (i * 2))); + } + + samples[sampleOffset] = sample; + + return sample; + } + else + { + return samples[sampleOffset]; + } +} + +std::vector ZAudio::ParseAudioTable(std::vector codeData, int baseOffset) +{ + std::vector entries; + + int numEntries = BitConverter::ToInt16BE(codeData, baseOffset + 0); + int romAddr = BitConverter::ToInt16BE(codeData, baseOffset + 4); + + int currentOffset = baseOffset + 16; + + for (int i = 0; i < numEntries; i++) + { + AudioTableEntry entry; + + entry.ptr = BitConverter::ToInt32BE(codeData, currentOffset + 0); + entry.size = BitConverter::ToInt32BE(codeData, currentOffset + 4); + entry.medium = codeData[currentOffset + 8]; + entry.cachePolicy = codeData[currentOffset + 9]; + entry.data1 = BitConverter::ToInt16BE(codeData, currentOffset + 10); + entry.data2 = BitConverter::ToInt16BE(codeData, currentOffset + 12); + entry.data3 = BitConverter::ToInt16BE(codeData, currentOffset + 14); + + entries.push_back(entry); + + currentOffset += 16; + } + + return entries; +} + +void ZAudio::ParseSoundFont(std::vector codeData, std::vector audioTable, + std::vector audioSampleBank, + AudioTableEntry& entry) +{ + int ptr = entry.ptr; + int size = entry.size; + int sampleBankId1 = (entry.data1 >> 8) & 0xFF; + int sampleBankId2 = (entry.data1) & 0xFF; + int numInstruments = (entry.data2 >> 8) & 0xFF; + int numDrums = entry.data2 & 0xFF; + int numSfx = entry.data3; + + int currentOffset = BitConverter::ToInt32BE(codeData, ptr) + ptr; + for (int i = 0; i < numDrums; i++) + { + DrumEntry drum; + + int samplePtr = BitConverter::ToInt32BE(codeData, currentOffset); + + if (samplePtr != 0) + { + samplePtr += ptr; + + drum.sample = ParseSampleEntry(codeData, audioTable, audioSampleBank[sampleBankId1], + BitConverter::ToInt32BE(codeData, samplePtr + 4) + ptr, ptr); + + drum.releaseRate = codeData[samplePtr + 0]; + drum.pan = codeData[samplePtr + 1]; + drum.loaded = codeData[samplePtr + 2]; + drum.tuning = BitConverter::ToFloatBE(codeData, samplePtr + 8); + + //int sampleDefOffset = BitConverter::ToInt32BE(codeData, samplePtr + 4); + drum.env = ParseEnvelopeData(codeData, audioTable, BitConverter::ToInt32BE(codeData, samplePtr + 12) + ptr, ptr); + } + + entry.drums.push_back(drum); + + currentOffset += 4; + } + + currentOffset = BitConverter::ToInt32BE(codeData, ptr + 4) + ptr; + for (int i = 0; i < numSfx; i++) + { + SoundFontEntry* sfx; + sfx = ParseSoundFontEntry(codeData, audioTable, audioSampleBank[sampleBankId1], + currentOffset, ptr); + entry.soundEffects.push_back(sfx); + + currentOffset += 8; + } + + for (int i = 0; i < numInstruments; i++) + { + InstrumentEntry instrument; + + currentOffset = BitConverter::ToInt32BE(codeData, ptr + 8 + (i * 4)); + + instrument.isValidInstrument = currentOffset != 0; + + if (currentOffset != 0) + { + currentOffset += ptr; + + instrument.loaded = codeData[currentOffset + 0]; + instrument.normalRangeLo = codeData[currentOffset + 1]; + instrument.normalRangeHi = codeData[currentOffset + 2]; + instrument.releaseRate = codeData[currentOffset + 3]; + instrument.env = ParseEnvelopeData(codeData, audioTable, BitConverter::ToInt32BE(codeData, currentOffset + 4) + ptr, ptr); + + if (BitConverter::ToInt32BE(codeData, currentOffset + 8) != 0) + instrument.lowNotesSound = ParseSoundFontEntry( + codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 8, ptr); + + if (BitConverter::ToInt32BE(codeData, currentOffset + 16) != 0) + instrument.normalNotesSound = ParseSoundFontEntry( + codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 16, ptr); + + if (BitConverter::ToInt32BE(codeData, currentOffset + 24) != 0 && + instrument.normalRangeHi != 0x7F) + instrument.highNotesSound = ParseSoundFontEntry( + codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 24, ptr); + } + + entry.instruments.push_back(instrument); + } +} + +void ZAudio::ParseRawData() +{ + ZResource::ParseRawData(); + + std::vector codeData; + std::vector audioTableData; + std::vector audioBankData; + std::vector audioSeqData; + + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) + codeData = Globals::Instance->GetBaseromFile("code"); + else + codeData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "code"); + + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) + audioTableData = Globals::Instance->GetBaseromFile("Audiotable"); + else + audioTableData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiotable"); + + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) + audioBankData = Globals::Instance->GetBaseromFile("Audiobank"); + else + audioBankData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiobank"); + + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) + audioSeqData = Globals::Instance->GetBaseromFile("Audioseq"); + else + audioSeqData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + + "Audioseq"); + + // TABLE PARSING + //int gSoundFontTableOffset = 0x138270; // OTRTODO: Make this an XML Param + //int gSequenceTableOffset = 0x1386A0; // OTRTODO: Make this an XML Param + //int gSampleBankTableOffset = 0x138D90; // OTRTODO: Make this an XML Param + int gSoundFontTableOffset = 0x138290; // OTRTODO: Make this an XML Param + int gSequenceTableOffset = 0x1386C0; // OTRTODO: Make this an XML Param + int gSampleBankTableOffset = 0x138DB0; // OTRTODO: Make this an XML Param + soundFontTable = ParseAudioTable(codeData, gSoundFontTableOffset); + sequenceTable = ParseAudioTable(codeData, gSequenceTableOffset); + sampleBankTable = ParseAudioTable(codeData, gSampleBankTableOffset); + // int gSequenceFontTableOffset = 0x1384E0; // OTRTODO: Make this an XML Param + + + // SAMPLE/FONT PARSING + for (int i = 0; i < soundFontTable.size(); i++) + { + ParseSoundFont(audioBankData, audioTableData, sampleBankTable, soundFontTable[i]); + } + + + // SOUNDBANK PARSING + /*for (int i = 0; i < sampleBankTable.size(); i++) + { + + }*/ + + // SEQUENCE PARSING + for (int i = 0; i < sequenceTable.size(); i++) + { + int seqDestIdx = i; + + if (sequenceTable[i].size == 0) + seqDestIdx = sequenceTable[i].ptr; + + std::vector seqVec = std::vector(sequenceTable[seqDestIdx].size); + memcpy(seqVec.data(), audioSeqData.data() + sequenceTable[seqDestIdx].ptr, + sequenceTable[seqDestIdx].size); + + sequences.push_back(seqVec); + } +} + +std::string ZAudio::GetSourceTypeName() const +{ + return "u8"; +} + +size_t ZAudio::GetRawDataSize() const +{ + return 1; +} + +ZResourceType ZAudio::GetResourceType() const +{ + return ZResourceType::Audio; +} diff --git a/ZAPDTR/ZAPD/ZAudio.h b/ZAPDTR/ZAPD/ZAudio.h new file mode 100644 index 000000000..a7c88410f --- /dev/null +++ b/ZAPDTR/ZAPD/ZAudio.h @@ -0,0 +1,122 @@ +#pragma once + +#include "ZResource.h" +#include "tinyxml2.h" + +struct AdsrEnvelope +{ + int16_t delay; + int16_t arg; +}; + +struct AdpcmBook +{ + /* 0x00 */ int32_t order; + /* 0x04 */ int32_t npredictors; + /* 0x08 */ std::vector books; // size 8 * order * npredictors. 8-byte aligned +}; + +struct AdpcmLoop +{ + /* 0x00 */ uint32_t start; + /* 0x04 */ uint32_t end; + /* 0x08 */ uint32_t count; + ///* 0x10 */ int16_t state[16]; // only exists if count != 0. 8-byte aligned + /* 0x10 */ std::vector states; +}; + +struct SampleEntry +{ + uint8_t codec; + uint8_t medium; + uint8_t unk_bit26; + uint8_t unk_bit25; + + std::vector data; + AdpcmLoop loop; + AdpcmBook book; +}; + +struct SoundFontEntry +{ + SampleEntry* sampleEntry = nullptr; + float tuning; +}; + +struct DrumEntry +{ + uint8_t releaseRate; + uint8_t pan; + uint8_t loaded; + uint32_t offset; + float tuning; + std::vector env; + //AdsrEnvelope* env = nullptr; + SampleEntry* sample = nullptr; +}; + +struct InstrumentEntry +{ + bool isValidInstrument; + uint8_t loaded; + uint8_t normalRangeLo; + uint8_t normalRangeHi; + uint8_t releaseRate; + std::vector env; + //AdsrEnvelope* env = nullptr; + SoundFontEntry* lowNotesSound = nullptr; + SoundFontEntry* normalNotesSound = nullptr; + SoundFontEntry* highNotesSound = nullptr; +}; + +struct AudioTableEntry +{ + uint32_t ptr; + uint32_t size; + uint8_t medium; + uint8_t cachePolicy; + uint16_t data1; + uint16_t data2; + uint16_t data3; + + std::vector drums; + std::vector soundEffects; + std::vector instruments; +}; + +class ZAudio : public ZResource +{ +public: + std::vector soundFontTable; + std::vector sequenceTable; + std::vector sampleBankTable; + std::vector> sequences; + std::map samples; + + ZAudio(ZFile* nParent); + + void DecodeADPCMSample(SampleEntry* sample); + std::vector ParseEnvelopeData(std::vector audioBank, std::vector audioTable, + int envelopeOffset, int baseOffset); + + SoundFontEntry* ParseSoundFontEntry(std::vector audioBank, + std::vector audioTable, + AudioTableEntry audioSampleBankEntry, + int soundFontOffset, + int baseOffset); + + SampleEntry* ParseSampleEntry(std::vector audioBank, std::vector audioTable, + AudioTableEntry audioSampleBankEntry, + int sampleOffset, int baseOffset); + + std::vector ParseAudioTable(std::vector codeData, int baseOffset); + void ParseSoundFont(std::vector codeData, std::vector audioTable, + std::vector audioSampleBank, AudioTableEntry& entry); + + void ParseRawData() override; + + std::string GetSourceTypeName() const override; + ZResourceType GetResourceType() const override; + + size_t GetRawDataSize() const override; +}; diff --git a/ZAPDTR/ZAPD/ZAudioDecode.cpp b/ZAPDTR/ZAPD/ZAudioDecode.cpp new file mode 100644 index 000000000..b8b066474 --- /dev/null +++ b/ZAPDTR/ZAPD/ZAudioDecode.cpp @@ -0,0 +1,669 @@ +/** + * Bruteforcing decoder for converting ADPCM-encoded AIFC into AIFF, in a way + * that roundtrips with vadpcm_enc. + */ +#include +#include +#include +#include +#include +#include +//#include + +typedef signed char s8; +typedef short s16; +typedef int s32; +typedef long long s64; +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; +typedef float f32; +typedef double f64; + +#ifdef _MSC_VER +#define __builtin_bswap16 _byteswap_ushort +#define __builtin_bswap32 _byteswap_ulong +#endif + +#define bswap16(x) __builtin_bswap16(x) +#define bswap32(x) __builtin_bswap32(x) +#define BSWAP16(x) x = __builtin_bswap16(x) +#define BSWAP32(x) x = __builtin_bswap32(x) +#define BSWAP16_MANY(x, n) \ + for (s32 _i = 0; _i < n; _i++) \ + BSWAP16((x)[_i]) + +#define NORETURN __attribute__((noreturn)) +#define UNUSED __attribute__((unused)) + +typedef struct +{ + u32 ckID; + u32 ckSize; +} ChunkHeader; + +typedef struct +{ + u32 ckID; + u32 ckSize; + u32 formType; +} Chunk; + +typedef struct +{ + s16 numChannels; + u16 numFramesH; + u16 numFramesL; + s16 sampleSize; + s16 sampleRate[5]; // 80-bit float + u16 compressionTypeH; + u16 compressionTypeL; +} CommonChunk; + +typedef struct +{ + s16 MarkerID; + u16 positionH; + u16 positionL; +} Marker; + +typedef struct +{ + s16 playMode; + s16 beginLoop; + s16 endLoop; +} Loop; + +typedef struct +{ + s8 baseNote; + s8 detune; + s8 lowNote; + s8 highNote; + s8 lowVelocity; + s8 highVelocity; + s16 gain; + Loop sustainLoop; + Loop releaseLoop; +} InstrumentChunk; + +typedef struct +{ + s32 offset; + s32 blockSize; +} SoundDataChunk; + +typedef struct +{ + s16 version; + s16 order; + s16 nEntries; +} CodeChunk; + +typedef struct +{ + u32 start; + u32 end; + u32 count; + s16 state[16]; +} ALADPCMloop; + +static char usage[] = "input.aifc output.aiff"; +static const char *progname, *infilename; +static int framesize = 9; + +void fail_parse(const char* fmt, ...) +{ + char* formatted = NULL; + va_list ap; + va_start(ap, fmt); + int size = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + if (size >= 0) + { + size++; + formatted = (char*)malloc(size); + if (formatted != NULL) + { + va_start(ap, fmt); + size = vsnprintf(formatted, size, fmt, ap); + va_end(ap); + if (size < 0) + { + free(formatted); + formatted = NULL; + } + } + } + + if (formatted != NULL) + { + fprintf(stderr, "%s: %s [%s]\n", progname, formatted, infilename); + free(formatted); + } + exit(1); +} + + +s32 myrand() +{ + static u64 state = 1619236481962341ULL; + state *= 3123692312237ULL; + state += 1; + return state >> 33; +} + +s16 qsample(f32 x, s32 scale) +{ + if (x > 0.0f) + { + return (s16)((x / scale) + 0.4999999); + } + else + { + return (s16)((x / scale) - 0.4999999); + } +} + +void clamp_to_s16(f32* in, s32* out) +{ + f32 llevel = -0x8000; + f32 ulevel = 0x7fff; + + for (s32 i = 0; i < 16; i++) + { + if (in[i] > ulevel) + in[i] = ulevel; + if (in[i] < llevel) + in[i] = llevel; + + if (in[i] > 0.0f) + { + out[i] = (s32)(in[i] + 0.5); + } + else + { + out[i] = (s32)(in[i] - 0.5); + } + } +} + +s16 clamp_bits(s32 x, s32 bits) +{ + s32 lim = 1 << (bits - 1); + if (x < -lim) + return -lim; + if (x > lim - 1) + return lim - 1; + return x; +} + +s32 readaifccodebook(FILE* fhandle, s32**** table, s16* order, s16* npredictors) +{ + BSWAP16(*order); + BSWAP16(*npredictors); + *table = (s32***)malloc(*npredictors * sizeof(s32**)); + for (s32 i = 0; i < *npredictors; i++) + { + (*table)[i] = (s32**)malloc(8 * sizeof(s32*)); + for (s32 j = 0; j < 8; j++) + { + (*table)[i][j] = (s32*)malloc((*order + 8) * sizeof(s32)); + } + } + + for (s32 i = 0; i < *npredictors; i++) + { + s32** table_entry = (*table)[i]; + for (s32 j = 0; j < *order; j++) + { + for (s32 k = 0; k < 8; k++) + { + s16 ts = 0; + BSWAP16(ts); + table_entry[k][j] = ts; + } + } + + for (s32 k = 1; k < 8; k++) + { + table_entry[k][*order] = table_entry[k - 1][*order - 1]; + } + + table_entry[0][*order] = 1 << 11; + + for (s32 k = 1; k < 8; k++) + { + s32 j = 0; + for (; j < k; j++) + { + table_entry[j][k + *order] = 0; + } + + for (; j < 8; j++) + { + table_entry[j][k + *order] = table_entry[j - k][*order]; + } + } + } + return 0; +} + +ALADPCMloop* readlooppoints(FILE* ifile, s16* nloops) +{ + BSWAP16(*nloops); + ALADPCMloop* al = (ALADPCMloop*)malloc(*nloops * sizeof(ALADPCMloop)); + for (s32 i = 0; i < *nloops; i++) + { + BSWAP32(al[i].start); + BSWAP32(al[i].end); + BSWAP32(al[i].count); + BSWAP16_MANY(al[i].state, 16); + } + return al; +} + +s32 inner_product(s32 length, s32* v1, s32* v2) +{ + s32 out = 0; + for (s32 i = 0; i < length; i++) + { + out += v1[i] * v2[i]; + } + + // Compute "out / 2^11", rounded down. + s32 dout = out / (1 << 11); + s32 fiout = dout * (1 << 11); + return dout - (out - fiout < 0); +} + +void my_decodeframe(u8* frame, s32* decompressed, s32* state, s32 order, s32*** coefTable) +{ + s32 ix[16]; + + u8 header = frame[0]; + s32 scale = 1 << (header >> 4); + s32 optimalp = header & 0xf; + + if (framesize == 5) + { + for (s32 i = 0; i < 16; i += 4) + { + u8 c = frame[1 + i / 4]; + ix[i] = c >> 6; + ix[i + 1] = (c >> 4) & 0x3; + ix[i + 2] = (c >> 2) & 0x3; + ix[i + 3] = c & 0x3; + } + } + else + { + for (s32 i = 0; i < 16; i += 2) + { + u8 c = frame[1 + i / 2]; + ix[i] = c >> 4; + ix[i + 1] = c & 0xf; + } + } + + for (s32 i = 0; i < 16; i++) + { + if (framesize == 5) + { + if (ix[i] >= 2) + ix[i] -= 4; + } + else + { + if (ix[i] >= 8) + ix[i] -= 16; + } + decompressed[i] = ix[i]; + ix[i] *= scale; + } + + for (s32 j = 0; j < 2; j++) + { + s32 in_vec[16]; + if (j == 0) + { + for (s32 i = 0; i < order; i++) + { + in_vec[i] = state[16 - order + i]; + } + } + else + { + for (s32 i = 0; i < order; i++) + { + in_vec[i] = state[8 - order + i]; + } + } + + for (s32 i = 0; i < 8; i++) + { + s32 ind = j * 8 + i; + in_vec[order + i] = ix[ind]; + state[ind] = inner_product(order + i, coefTable[optimalp][i], in_vec) + ix[ind]; + } + } +} + +void get_bounds(s32* in, s32* decompressed, s32 scale, s32* minVals, s32* maxVals) +{ + s32 minv, maxv; + if (framesize == 9) + { + minv = -8; + maxv = 7; + } + else + { + minv = -2; + maxv = 1; + } + for (s32 i = 0; i < 16; i++) + { + s32 lo = in[i] - scale / 2; + s32 hi = in[i] + scale / 2; + lo -= scale; + hi += scale; + if (decompressed[i] == minv) + lo -= scale; + else if (decompressed[i] == maxv) + hi += scale; + minVals[i] = lo; + maxVals[i] = hi; + } +} + +void write_header(FILE* ofile, const char* id, s32 size) +{ + fwrite(id, 4, 1, ofile); + BSWAP32(size); + fwrite(&size, sizeof(s32), 1, ofile); +} + +char* OldMain(char* infilename) +{ + s16 order = -1; + s16 nloops = 0; + ALADPCMloop* aloops = NULL; + s16 npredictors = -1; + s32*** coefTable = NULL; + s32 state[16]; + s32 decompressed[16]; + s32 soundPointer = -1; + s32 currPos = 0; + s32 nSamples = 0; + Chunk FormChunk = Chunk(); + ChunkHeader Header = ChunkHeader(); + CommonChunk CommChunk = CommonChunk(); + InstrumentChunk InstChunk; + SoundDataChunk SndDChunk = SoundDataChunk(); + FILE* ifile = NULL; + FILE* ofile = NULL; + + if ((ifile = fopen(infilename, "rb")) == NULL) + { + fail_parse("AIFF-C file could not be opened"); + exit(1); + } + + memset(&InstChunk, 0, sizeof(InstChunk)); + + BSWAP32(FormChunk.ckID); + BSWAP32(FormChunk.formType); + if ((FormChunk.ckID != 0x464f524d) || (FormChunk.formType != 0x41494643)) + { // FORM, AIFC + fail_parse("not an AIFF-C file"); + } + + for (;;) + { + s32 num = fread(&Header, sizeof(Header), 1, ifile); + u32 ts = 0; + + if (num <= 0) + break; + + BSWAP32(Header.ckID); + BSWAP32(Header.ckSize); + + Header.ckSize++; + Header.ckSize &= ~1; + s32 offset = ftell(ifile); + + switch (Header.ckID) + { + case 0x434f4d4d: // COMM + { + BSWAP16(CommChunk.numChannels); + BSWAP16(CommChunk.numFramesH); + BSWAP16(CommChunk.numFramesL); + BSWAP16(CommChunk.sampleSize); + BSWAP16(CommChunk.compressionTypeH); + BSWAP16(CommChunk.compressionTypeL); + s32 cType = (CommChunk.compressionTypeH << 16) + CommChunk.compressionTypeL; + if (cType == 0x56415043 || cType == 0x41445039) + { // VAPC or ADP9 + framesize = 9; + } + else if (cType == 0x41445035) + { // ADP5 + framesize = 5; + } + else if (cType == 0x4850434d) + { // HPCM + framesize = 16; + } + else + { + char comprType[5] = { + CommChunk.compressionTypeH >> 8, CommChunk.compressionTypeH & 0xFF, + CommChunk.compressionTypeL >> 8, CommChunk.compressionTypeL & 0xFF, 0}; + fail_parse("file is of the wrong compression type [got %s (%08x)]", &comprType, + cType); + } + if (CommChunk.numChannels != 1) + { + fail_parse("file contains %d channels, only 1 channel supported", + CommChunk.numChannels); + } + if (CommChunk.sampleSize != 16) + { + fail_parse("file contains %d bit samples, only 16 bit samples supported", + CommChunk.sampleSize); + } + + nSamples = (CommChunk.numFramesH << 16) + CommChunk.numFramesL; + + // Allow broken input lengths + if (nSamples % 16) + { + nSamples -= (nSamples % 16); + } + + if (nSamples % 16 != 0) + { + fail_parse("number of chunks must be a multiple of 16, found %d with remainder %d", + nSamples, nSamples % 16); + } + } + break; + + case 0x53534e44: // SSND + BSWAP32(SndDChunk.offset); + BSWAP32(SndDChunk.blockSize); + assert(SndDChunk.offset == 0); + assert(SndDChunk.blockSize == 0); + soundPointer = ftell(ifile); + break; + + case 0x4150504c: // APPL + BSWAP32(ts); + if (ts == 0x73746f63) + { // stoc + u8 len = 0; + if (len == 11) + { + char ChunkName[12]; + s16 version; + ChunkName[11] = '\0'; + if (strcmp("VADPCMCODES", ChunkName) == 0) + { + BSWAP16(version); + if (version != 1) + { + fail_parse("Unknown codebook chunk version"); + } + readaifccodebook(ifile, &coefTable, &order, &npredictors); + } + else if (strcmp("VADPCMLOOPS", ChunkName) == 0) + { + BSWAP16(version); + if (version != 1) + { + fail_parse("Unknown loop chunk version"); + } + aloops = readlooppoints(ifile, &nloops); + if (nloops != 1) + { + fail_parse("Only a single loop supported"); + } + } + } + } + break; + } + + fseek(ifile, offset + Header.ckSize, SEEK_SET); + } + + if (coefTable == NULL) + { + fail_parse("Codebook missing from bitstream"); + } + + for (s32 i = 0; i < order; i++) + { + state[15 - i] = 0; + } + + u32 outputBytes = nSamples * sizeof(s16); + u8* outputBuf = (u8*)malloc(outputBytes); + + fseek(ifile, soundPointer, SEEK_SET); + s32 fails = 0; + while (currPos < nSamples) + { + u8 input[9]; + u8 encoded[9]; + s32 lastState[16]; + s32 decoded[16]; + s16 guess[16]; + s16 origGuess[16]; + + memcpy(lastState, state, sizeof(state)); + + // Decode for real + my_decodeframe(input, decompressed, state, order, coefTable); + memcpy(decoded, state, sizeof(state)); + + // Create a guess from that, by clamping to 16 bits + for (s32 i = 0; i < 16; i++) + { + origGuess[i] = clamp_bits(state[i], 16); + } + + memcpy(state, decoded, sizeof(state)); + memcpy(outputBuf + currPos * 2, decoded, sizeof(decoded)); + currPos += 16; + } + if (fails) + { + fprintf(stderr, "%s %d\n", infilename, fails); + } + + // Write an incomplete file header. We'll fill in the size later. + fwrite("FORM\0\0\0\0AIFF", 12, 1, ofile); + + // Subtract 4 from the COMM size to skip the compression field. + write_header(ofile, "COMM", sizeof(CommonChunk) - 4); + CommChunk.numFramesH = nSamples >> 16; + CommChunk.numFramesL = nSamples & 0xffff; + BSWAP16(CommChunk.numChannels); + BSWAP16(CommChunk.numFramesH); + BSWAP16(CommChunk.numFramesL); + BSWAP16(CommChunk.sampleSize); + fwrite(&CommChunk, sizeof(CommonChunk) - 4, 1, ofile); + + if (nloops > 0) + { + s32 startPos = aloops[0].start, endPos = aloops[0].end; + const char* markerNames[2] = {"start", "end"}; + Marker markers[2] = {{1, startPos >> 16, startPos & 0xffff}, + {2, endPos >> 16, endPos & 0xffff}}; + write_header(ofile, "MARK", 2 + 2 * sizeof(Marker) + 1 + 5 + 1 + 3); + s16 numMarkers = bswap16(2); + fwrite(&numMarkers, sizeof(s16), 1, ofile); + for (s32 i = 0; i < 2; i++) + { + u8 len = (u8)strlen(markerNames[i]); + BSWAP16(markers[i].MarkerID); + BSWAP16(markers[i].positionH); + BSWAP16(markers[i].positionL); + fwrite(&markers[i], sizeof(Marker), 1, ofile); + fwrite(&len, 1, 1, ofile); + fwrite(markerNames[i], len, 1, ofile); + } + + write_header(ofile, "INST", sizeof(InstrumentChunk)); + InstChunk.sustainLoop.playMode = bswap16(1); + InstChunk.sustainLoop.beginLoop = bswap16(1); + InstChunk.sustainLoop.endLoop = bswap16(2); + InstChunk.releaseLoop.playMode = 0; + InstChunk.releaseLoop.beginLoop = 0; + InstChunk.releaseLoop.endLoop = 0; + fwrite(&InstChunk, sizeof(InstrumentChunk), 1, ofile); + } + + // Save the coefficient table for use when encoding. Ideally this wouldn't + // be needed and "tabledesign -s 1" would generate the right table, but in + // practice it's difficult to adjust samples to make that happen. + write_header(ofile, "APPL", 4 + 12 + sizeof(CodeChunk) + npredictors * order * 8 * 2); + fwrite("stoc", 4, 1, ofile); + CodeChunk cChunk; + cChunk.version = bswap16(1); + cChunk.order = bswap16(order); + cChunk.nEntries = bswap16(npredictors); + fwrite("\x0bVADPCMCODES", 12, 1, ofile); + fwrite(&cChunk, sizeof(CodeChunk), 1, ofile); + for (s32 i = 0; i < npredictors; i++) + { + for (s32 j = 0; j < order; j++) + { + for (s32 k = 0; k < 8; k++) + { + s16 ts = bswap16(coefTable[i][k][j]); + fwrite(&ts, sizeof(s16), 1, ofile); + } + } + } + + write_header(ofile, "SSND", outputBytes + 8); + SndDChunk.offset = 0; + SndDChunk.blockSize = 0; + fwrite(&SndDChunk, sizeof(SoundDataChunk), 1, ofile); + fwrite(outputBuf, outputBytes, 1, ofile); + + // Fix the size in the header + s32 fileSize = bswap32(ftell(ofile) - 8); + fseek(ofile, 4, SEEK_SET); + fwrite(&fileSize, 4, 1, ofile); + + fclose(ifile); + fclose(ofile); + return 0; +} \ No newline at end of file diff --git a/ZAPDTR/ZAPD/ZResource.h b/ZAPDTR/ZAPD/ZResource.h index 82709aec0..8b1055a4b 100644 --- a/ZAPDTR/ZAPD/ZResource.h +++ b/ZAPDTR/ZAPD/ZResource.h @@ -50,7 +50,8 @@ enum class ZResourceType TextureAnimationParams, Vector, Vertex, - Text + Text, + Audio }; class ResourceAttribute diff --git a/ZAPDTR/ZAPD/ZRom.cpp b/ZAPDTR/ZAPD/ZRom.cpp index 2a1d3c8a1..a311714dd 100644 --- a/ZAPDTR/ZAPD/ZRom.cpp +++ b/ZAPDTR/ZAPD/ZRom.cpp @@ -191,6 +191,8 @@ ZRom::ZRom(std::string romPath) } else files[lines[i]] = outData; + + //File::WriteAllBytes(StringHelper::Sprintf("baserom/%s", lines[i]), files[lines[i]]); } int bp = 0; -- cgit v1.2.3 From b3e299dbdee829c12ada556a1c3aa1f109a0e05b Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Wed, 1 Jun 2022 16:05:05 -0400 Subject: Replaced StormLib .lib files with source code. Some modifications to handle backslashes and forward slashes, along with some optimizations to speed up OTR generation. --- ZAPDTR/ZAPD/ZAPD.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ZAPDTR') diff --git a/ZAPDTR/ZAPD/ZAPD.vcxproj b/ZAPDTR/ZAPD/ZAPD.vcxproj index 940d3b2ed..ad3c3e08c 100644 --- a/ZAPDTR/ZAPD/ZAPD.vcxproj +++ b/ZAPDTR/ZAPD/ZAPD.vcxproj @@ -72,15 +72,15 @@ - $(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\..\OTRExporter\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(ProjectDir)..\..\libultraship\libultraship\;$(LibraryPath) - $(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath) + $(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\..\OTRExporter\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(ProjectDir)..\..\libultraship\libultraship\;$(ProjectDir)..\..\StormLib\bin\StormLib\x64\DebugUS\;$(LibraryPath) + $(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(ProjectDir)..\..\StormLib\src\;$(IncludePath) MinimumRecommendedRules.ruleset - $(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath) - $(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\..\OTRExporter\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(ProjectDir)..\..\libultraship\libultraship\;$(LibraryPath) + $(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(ProjectDir)..\..\StormLib\src\;$(IncludePath) + $(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\..\OTRExporter\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(ProjectDir)..\..\libultraship\libultraship\;$(ProjectDir)..\..\StormLib\bin\StormLib\x64\ReleaseUS\;$(LibraryPath) false MinimumRecommendedRules.ruleset -- cgit v1.2.3 From c49cee352111acc5f2a831ba2f7a46a627785eff Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Fri, 10 Jun 2022 13:37:50 -0400 Subject: Audio support nearly complete. --- ZAPDTR/ZAPD/ZAudio.cpp | 125 +++++++++++++++++++++++++++++++++++++--------- ZAPDTR/ZAPD/ZAudio.h | 15 ++++-- ZAPDTR/ZAPD/ZResource.cpp | 12 +++-- 3 files changed, 118 insertions(+), 34 deletions(-) (limited to 'ZAPDTR') diff --git a/ZAPDTR/ZAPD/ZAudio.cpp b/ZAPDTR/ZAPD/ZAudio.cpp index 1c24c824a..63443de34 100644 --- a/ZAPDTR/ZAPD/ZAudio.cpp +++ b/ZAPDTR/ZAPD/ZAudio.cpp @@ -13,6 +13,54 @@ ZAudio::ZAudio(ZFile* nParent) : ZResource(nParent) { //RegisterRequiredAttribute("CodeOffset"); //RegisterOptionalAttribute("LangOffset", "0"); + +} + +void ZAudio::ParseXML(tinyxml2::XMLElement* reader) +{ + ZResource::ParseXML(reader); + + auto t = reader->Name(); + + auto child = reader->FirstChildElement(); + + while (child != nullptr) + { + int bp = 0; + if (std::string(child->Value()) == "Sequences") + { + auto seqChild = child->FirstChildElement(); + + while (seqChild != nullptr) + { + if (std::string(seqChild->Value()) == "Sequence") + { + seqNames.push_back(seqChild->Attribute("Name")); + } + + seqChild = seqChild->NextSiblingElement(); + } + } + + if (std::string(child->Value()) == "Samples") + { + int bankId = child->IntAttribute("Bank", 0); + auto sampChild = child->FirstChildElement(); + + while (sampChild != nullptr) + { + if (std::string(sampChild->Value()) == "Sample") + { + auto atStr = sampChild->FirstChildElement()->Attribute("At"); + sampleOffsets[bankId][StringHelper::StrToL(atStr, 16)] = sampChild->Attribute("Name"); + } + + sampChild = sampChild->NextSiblingElement(); + } + } + + child = child->NextSiblingElement(); + } } void ZAudio::DecodeADPCMSample(SampleEntry* sample) @@ -26,9 +74,6 @@ std::vector ZAudio::ParseEnvelopeData(std::vector audioB { std::vector result; - //bool process = true; - - //for (int i = 0; i < 4; i++) while (true) { AdsrEnvelope* env = new AdsrEnvelope(); @@ -49,13 +94,13 @@ std::vector ZAudio::ParseEnvelopeData(std::vector audioB SoundFontEntry* ZAudio::ParseSoundFontEntry(std::vector audioBank, std::vector audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int soundFontOffset, int baseOffset) { SoundFontEntry* soundFont = new SoundFontEntry(); soundFont->sampleEntry = ParseSampleEntry( - audioBank, audioTable, audioSampleBankEntry, + audioBank, audioTable, audioSampleBankEntry, bankIndex, BitConverter::ToInt32BE(audioBank, soundFontOffset + 0) + baseOffset, baseOffset); soundFont->tuning = BitConverter::ToFloatBE(audioBank, soundFontOffset + 4); @@ -64,7 +109,7 @@ SoundFontEntry* ZAudio::ParseSoundFontEntry(std::vector audioBank, SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, std::vector audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int sampleOffset, int baseOffset) { @@ -74,6 +119,8 @@ SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, { SampleEntry* sample = new SampleEntry(); + sample->bankId = bankIndex; + int sampleSize = BitConverter::ToInt32BE(audioBank, sampleOffset + 0) & 0x00FFFFFF; int loopOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 8) + baseOffset; int bookOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 12) + baseOffset; @@ -111,6 +158,9 @@ SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, BitConverter::ToInt16BE(audioBank, bookOffset + 8 + (i * 2))); } + sample->sampleDataOffset = sampleDataOffset; + sample->fileName = StringHelper::Sprintf("audio/samples/sample_%08X", sampleOffset); + samples[sampleOffset] = sample; return sample; @@ -173,15 +223,13 @@ void ZAudio::ParseSoundFont(std::vector codeData, std::vector { samplePtr += ptr; - drum.sample = ParseSampleEntry(codeData, audioTable, audioSampleBank[sampleBankId1], + drum.sample = ParseSampleEntry(codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, BitConverter::ToInt32BE(codeData, samplePtr + 4) + ptr, ptr); drum.releaseRate = codeData[samplePtr + 0]; drum.pan = codeData[samplePtr + 1]; drum.loaded = codeData[samplePtr + 2]; drum.tuning = BitConverter::ToFloatBE(codeData, samplePtr + 8); - - //int sampleDefOffset = BitConverter::ToInt32BE(codeData, samplePtr + 4); drum.env = ParseEnvelopeData(codeData, audioTable, BitConverter::ToInt32BE(codeData, samplePtr + 12) + ptr, ptr); } @@ -194,7 +242,7 @@ void ZAudio::ParseSoundFont(std::vector codeData, std::vector for (int i = 0; i < numSfx; i++) { SoundFontEntry* sfx; - sfx = ParseSoundFontEntry(codeData, audioTable, audioSampleBank[sampleBankId1], + sfx = ParseSoundFontEntry(codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset, ptr); entry.soundEffects.push_back(sfx); @@ -221,16 +269,16 @@ void ZAudio::ParseSoundFont(std::vector codeData, std::vector if (BitConverter::ToInt32BE(codeData, currentOffset + 8) != 0) instrument.lowNotesSound = ParseSoundFontEntry( - codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 8, ptr); + codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset + 8, ptr); if (BitConverter::ToInt32BE(codeData, currentOffset + 16) != 0) instrument.normalNotesSound = ParseSoundFontEntry( - codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 16, ptr); + codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset + 16, ptr); if (BitConverter::ToInt32BE(codeData, currentOffset + 24) != 0 && instrument.normalRangeHi != 0x7F) instrument.highNotesSound = ParseSoundFontEntry( - codeData, audioTable, audioSampleBank[sampleBankId1], currentOffset + 24, ptr); + codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset + 24, ptr); } entry.instruments.push_back(instrument); @@ -251,33 +299,69 @@ void ZAudio::ParseRawData() else codeData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "code"); + codeData = File::ReadAllBytes("baserom/code_ntsc"); + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) audioTableData = Globals::Instance->GetBaseromFile("Audiotable"); else audioTableData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiotable"); + audioTableData = File::ReadAllBytes("baserom/Audiotable_ntsc"); + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) audioBankData = Globals::Instance->GetBaseromFile("Audiobank"); else audioBankData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiobank"); + audioBankData = File::ReadAllBytes("baserom/Audiobank_ntsc"); + if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) audioSeqData = Globals::Instance->GetBaseromFile("Audioseq"); else audioSeqData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audioseq"); + audioSeqData = File::ReadAllBytes("baserom/Audioseq_ntsc"); + // TABLE PARSING + + // GC PAL //int gSoundFontTableOffset = 0x138270; // OTRTODO: Make this an XML Param //int gSequenceTableOffset = 0x1386A0; // OTRTODO: Make this an XML Param //int gSampleBankTableOffset = 0x138D90; // OTRTODO: Make this an XML Param - int gSoundFontTableOffset = 0x138290; // OTRTODO: Make this an XML Param - int gSequenceTableOffset = 0x1386C0; // OTRTODO: Make this an XML Param - int gSampleBankTableOffset = 0x138DB0; // OTRTODO: Make this an XML Param + // int gSequenceFontTableOffset = 0x1384E0; // OTRTODO: Make this an XML Param + + // NMQ DBG ROM + //int gSoundFontTableOffset = 0x138290; // OTRTODO: Make this an XML Param + //int gSequenceTableOffset = 0x1386C0; // OTRTODO: Make this an XML Param + //int gSampleBankTableOffset = 0x138DB0; // OTRTODO: Make this an XML Param + //int gSequenceFontTableOffset = 0x138500; // OTRTODO: Make this an XML Param + + // NTSC 1.0 + int gSoundFontTableOffset = 0x1026A0; // OTRTODO: Make this an XML Param + int gSequenceTableOffset = 0x102AD0; // OTRTODO: Make this an XML Param + int gSampleBankTableOffset = 0x1031C0; // OTRTODO: Make this an XML Param + int gSequenceFontTableOffset = 0x102910; // OTRTODO: Make this an XML Param + soundFontTable = ParseAudioTable(codeData, gSoundFontTableOffset); sequenceTable = ParseAudioTable(codeData, gSequenceTableOffset); sampleBankTable = ParseAudioTable(codeData, gSampleBankTableOffset); - // int gSequenceFontTableOffset = 0x1384E0; // OTRTODO: Make this an XML Param + + // SEQEUNCE FONT TABLE PARSING + for (int i = 0; i < sequenceTable.size(); i++) + { + uint16_t idx = BitConverter::ToUInt16BE(codeData, gSequenceFontTableOffset + (i * 2)); + uint8_t numFonts = codeData[gSequenceFontTableOffset + (idx++)]; + std::vector fontIds; + + for (int j = 0; j < numFonts; j++) + { + uint8_t fontId = codeData[gSequenceFontTableOffset + (idx++)]; + fontIds.push_back(fontId); + } + + fontIndices.push_back(fontIds); + } // SAMPLE/FONT PARSING @@ -286,13 +370,6 @@ void ZAudio::ParseRawData() ParseSoundFont(audioBankData, audioTableData, sampleBankTable, soundFontTable[i]); } - - // SOUNDBANK PARSING - /*for (int i = 0; i < sampleBankTable.size(); i++) - { - - }*/ - // SEQUENCE PARSING for (int i = 0; i < sequenceTable.size(); i++) { diff --git a/ZAPDTR/ZAPD/ZAudio.h b/ZAPDTR/ZAPD/ZAudio.h index a7c88410f..5d18c2e71 100644 --- a/ZAPDTR/ZAPD/ZAudio.h +++ b/ZAPDTR/ZAPD/ZAudio.h @@ -21,12 +21,14 @@ struct AdpcmLoop /* 0x00 */ uint32_t start; /* 0x04 */ uint32_t end; /* 0x08 */ uint32_t count; - ///* 0x10 */ int16_t state[16]; // only exists if count != 0. 8-byte aligned /* 0x10 */ std::vector states; }; struct SampleEntry { + std::string fileName; + uint8_t bankId; + uint32_t sampleDataOffset; uint8_t codec; uint8_t medium; uint8_t unk_bit26; @@ -51,7 +53,6 @@ struct DrumEntry uint32_t offset; float tuning; std::vector env; - //AdsrEnvelope* env = nullptr; SampleEntry* sample = nullptr; }; @@ -63,7 +64,6 @@ struct InstrumentEntry uint8_t normalRangeHi; uint8_t releaseRate; std::vector env; - //AdsrEnvelope* env = nullptr; SoundFontEntry* lowNotesSound = nullptr; SoundFontEntry* normalNotesSound = nullptr; SoundFontEntry* highNotesSound = nullptr; @@ -92,21 +92,26 @@ public: std::vector sampleBankTable; std::vector> sequences; std::map samples; + std::vector> fontIndices; + std::vector seqNames; + std::map> sampleOffsets; ZAudio(ZFile* nParent); + void ParseXML(tinyxml2::XMLElement* reader) override; + void DecodeADPCMSample(SampleEntry* sample); std::vector ParseEnvelopeData(std::vector audioBank, std::vector audioTable, int envelopeOffset, int baseOffset); SoundFontEntry* ParseSoundFontEntry(std::vector audioBank, std::vector audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int soundFontOffset, int baseOffset); SampleEntry* ParseSampleEntry(std::vector audioBank, std::vector audioTable, - AudioTableEntry audioSampleBankEntry, + AudioTableEntry audioSampleBankEntry, int bankIndex, int sampleOffset, int baseOffset); std::vector ParseAudioTable(std::vector codeData, int baseOffset); diff --git a/ZAPDTR/ZAPD/ZResource.cpp b/ZAPDTR/ZAPD/ZResource.cpp index c6efef073..550031ab4 100644 --- a/ZAPDTR/ZAPD/ZResource.cpp +++ b/ZAPDTR/ZAPD/ZResource.cpp @@ -100,11 +100,14 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader) attrs = attrs->Next(); } - if (!canHaveInner && !reader->NoChildren()) + if (!Globals::Instance->otrMode) { - std::string errorHeader = StringHelper::Sprintf( - "resource '%s' with inner element/child detected", reader->Name()); - HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, ""); + if (!canHaveInner && !reader->NoChildren()) + { + std::string errorHeader = StringHelper::Sprintf( + "resource '%s' with inner element/child detected", reader->Name()); + HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, ""); + } } for (const auto& attr : registeredAttributes) @@ -121,7 +124,6 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader) name = registeredAttributes.at("Name").value; - // Disable this check for OTR file generation for now since it takes up a considerable amount of CPU time if (!Globals::Instance->otrMode) { -- cgit v1.2.3 From ef2f4f799cd645d1edb4640c8d9a1f398e01f231 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Fri, 10 Jun 2022 13:50:16 -0400 Subject: Commented out NTSC test --- ZAPDTR/ZAPD/ZAudio.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'ZAPDTR') diff --git a/ZAPDTR/ZAPD/ZAudio.cpp b/ZAPDTR/ZAPD/ZAudio.cpp index 63443de34..d0df11f92 100644 --- a/ZAPDTR/ZAPD/ZAudio.cpp +++ b/ZAPDTR/ZAPD/ZAudio.cpp @@ -299,21 +299,16 @@ void ZAudio::ParseRawData() else codeData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "code"); - codeData = File::ReadAllBytes("baserom/code_ntsc"); - if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) audioTableData = Globals::Instance->GetBaseromFile("Audiotable"); else audioTableData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiotable"); - audioTableData = File::ReadAllBytes("baserom/Audiotable_ntsc"); - if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) audioBankData = Globals::Instance->GetBaseromFile("Audiobank"); else audioBankData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiobank"); - audioBankData = File::ReadAllBytes("baserom/Audiobank_ntsc"); if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) audioSeqData = Globals::Instance->GetBaseromFile("Audioseq"); @@ -321,7 +316,10 @@ void ZAudio::ParseRawData() audioSeqData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audioseq"); - audioSeqData = File::ReadAllBytes("baserom/Audioseq_ntsc"); + //codeData = File::ReadAllBytes("baserom/code_ntsc"); + //audioTableData = File::ReadAllBytes("baserom/Audiotable_ntsc"); + //audioSeqData = File::ReadAllBytes("baserom/Audioseq_ntsc"); + //audioBankData = File::ReadAllBytes("baserom/Audiobank_ntsc"); // TABLE PARSING -- cgit v1.2.3 From 28073fbb191ee13f8fade45b98eb6504c00df4c8 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Fri, 10 Jun 2022 13:53:03 -0400 Subject: Commented out additional test code --- ZAPDTR/ZAPD/ZAudio.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'ZAPDTR') diff --git a/ZAPDTR/ZAPD/ZAudio.cpp b/ZAPDTR/ZAPD/ZAudio.cpp index d0df11f92..8dd985701 100644 --- a/ZAPDTR/ZAPD/ZAudio.cpp +++ b/ZAPDTR/ZAPD/ZAudio.cpp @@ -327,19 +327,19 @@ void ZAudio::ParseRawData() //int gSoundFontTableOffset = 0x138270; // OTRTODO: Make this an XML Param //int gSequenceTableOffset = 0x1386A0; // OTRTODO: Make this an XML Param //int gSampleBankTableOffset = 0x138D90; // OTRTODO: Make this an XML Param - // int gSequenceFontTableOffset = 0x1384E0; // OTRTODO: Make this an XML Param + //int gSequenceFontTableOffset = 0x1384E0; // OTRTODO: Make this an XML Param // NMQ DBG ROM - //int gSoundFontTableOffset = 0x138290; // OTRTODO: Make this an XML Param - //int gSequenceTableOffset = 0x1386C0; // OTRTODO: Make this an XML Param - //int gSampleBankTableOffset = 0x138DB0; // OTRTODO: Make this an XML Param - //int gSequenceFontTableOffset = 0x138500; // OTRTODO: Make this an XML Param + int gSoundFontTableOffset = 0x138290; // OTRTODO: Make this an XML Param + int gSequenceTableOffset = 0x1386C0; // OTRTODO: Make this an XML Param + int gSampleBankTableOffset = 0x138DB0; // OTRTODO: Make this an XML Param + int gSequenceFontTableOffset = 0x138500; // OTRTODO: Make this an XML Param // NTSC 1.0 - int gSoundFontTableOffset = 0x1026A0; // OTRTODO: Make this an XML Param - int gSequenceTableOffset = 0x102AD0; // OTRTODO: Make this an XML Param - int gSampleBankTableOffset = 0x1031C0; // OTRTODO: Make this an XML Param - int gSequenceFontTableOffset = 0x102910; // OTRTODO: Make this an XML Param + //int gSoundFontTableOffset = 0x1026A0; // OTRTODO: Make this an XML Param + //int gSequenceTableOffset = 0x102AD0; // OTRTODO: Make this an XML Param + //int gSampleBankTableOffset = 0x1031C0; // OTRTODO: Make this an XML Param + //int gSequenceFontTableOffset = 0x102910; // OTRTODO: Make this an XML Param soundFontTable = ParseAudioTable(codeData, gSoundFontTableOffset); sequenceTable = ParseAudioTable(codeData, gSequenceTableOffset); -- cgit v1.2.3 From 0a629ea6e953d9b2d63d14c28525e7047de88984 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Mon, 13 Jun 2022 21:54:25 -0400 Subject: Fixed last remaining audio bugs --- ZAPDTR/ZAPD/ZAudio.cpp | 32 +++++++++++++++++++++++++++----- ZAPDTR/ZAPD/ZAudio.h | 8 +++++++- 2 files changed, 34 insertions(+), 6 deletions(-) (limited to 'ZAPDTR') diff --git a/ZAPDTR/ZAPD/ZAudio.cpp b/ZAPDTR/ZAPD/ZAudio.cpp index 8dd985701..976133513 100644 --- a/ZAPDTR/ZAPD/ZAudio.cpp +++ b/ZAPDTR/ZAPD/ZAudio.cpp @@ -26,7 +26,6 @@ void ZAudio::ParseXML(tinyxml2::XMLElement* reader) while (child != nullptr) { - int bp = 0; if (std::string(child->Value()) == "Sequences") { auto seqChild = child->FirstChildElement(); @@ -52,7 +51,17 @@ void ZAudio::ParseXML(tinyxml2::XMLElement* reader) if (std::string(sampChild->Value()) == "Sample") { auto atStr = sampChild->FirstChildElement()->Attribute("At"); - sampleOffsets[bankId][StringHelper::StrToL(atStr, 16)] = sampChild->Attribute("Name"); + auto loopStr = sampChild->FirstChildElement()->Attribute("LoopOffset"); + uint32_t loopOffset = 0xFFFFFFFF; + uint32_t atOffset = StringHelper::StrToL(atStr, 16); + + if (loopStr != NULL) + { + loopOffset = StringHelper::StrToL(loopStr, 16); + specialLoopSamples[loopOffset] = atOffset; + } + + sampleOffsets[bankId][loopOffset][atOffset] = sampChild->Attribute("Name"); } sampChild = sampChild->NextSiblingElement(); @@ -140,11 +149,20 @@ SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, sample->loop.end = BitConverter::ToInt32BE(audioBank, loopOffset + 4); sample->loop.count = BitConverter::ToInt32BE(audioBank, loopOffset + 8); - if (sample->loop.count != 0xFFFFFFFF) + if (sample->loop.start == 0x3ADB) + { + int bp = 0; + } + + if (/* sample->loop.count != 0xFFFFFFFF && */ sample->loop.count != 0) { - for (int i = 0; i < sample->loop.count; i++) + //for (int i = 0; i < sample->loop.count; i++) + for (int i = 0; i < 16; i++) { - int16_t state = BitConverter::ToInt16BE(sample->data, loopOffset + 16 + (i * 2)); + //if ((loopOffset + 16 + (i * 2)) >= audioBank.size()) + //break; + + int16_t state = BitConverter::ToInt16BE(audioBank, loopOffset + 16 + (i * 2)); sample->loop.states.push_back(state); } } @@ -159,6 +177,10 @@ SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, } sample->sampleDataOffset = sampleDataOffset; + + if (specialLoopSamples.find(loopOffset) != specialLoopSamples.end()) + sample->sampleLoopOffset = loopOffset; + sample->fileName = StringHelper::Sprintf("audio/samples/sample_%08X", sampleOffset); samples[sampleOffset] = sample; diff --git a/ZAPDTR/ZAPD/ZAudio.h b/ZAPDTR/ZAPD/ZAudio.h index 5d18c2e71..511ba5ed6 100644 --- a/ZAPDTR/ZAPD/ZAudio.h +++ b/ZAPDTR/ZAPD/ZAudio.h @@ -29,6 +29,7 @@ struct SampleEntry std::string fileName; uint8_t bankId; uint32_t sampleDataOffset; + uint32_t sampleLoopOffset = 0xFFFFFFFF; uint8_t codec; uint8_t medium; uint8_t unk_bit26; @@ -94,7 +95,12 @@ public: std::map samples; std::vector> fontIndices; std::vector seqNames; - std::map> sampleOffsets; + + // First Key = Bank ID, Sec Key = LoopDataOffset, Third Key = Sample Data Offset + std::map>> sampleOffsets; + + // Key = Loop Offset, Value = Sample Offset + std::map specialLoopSamples; ZAudio(ZFile* nParent); -- cgit v1.2.3 From c930bd0138a987223a854c4f4d54e6c9b4a48778 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Tue, 14 Jun 2022 00:59:31 -0400 Subject: Added names for the soundfonts. --- ZAPDTR/ZAPD/ZAudio.cpp | 13 ++++++++----- ZAPDTR/ZAPD/ZAudio.h | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'ZAPDTR') diff --git a/ZAPDTR/ZAPD/ZAudio.cpp b/ZAPDTR/ZAPD/ZAudio.cpp index 976133513..a502a0545 100644 --- a/ZAPDTR/ZAPD/ZAudio.cpp +++ b/ZAPDTR/ZAPD/ZAudio.cpp @@ -68,6 +68,13 @@ void ZAudio::ParseXML(tinyxml2::XMLElement* reader) } } + if (std::string(child->Value()) == "Soundfont") + { + auto name = child->Attribute("Name"); + auto index = child->IntAttribute("Index", 0); + soundFontNames[index] = name; + } + child = child->NextSiblingElement(); } } @@ -154,14 +161,10 @@ SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, int bp = 0; } - if (/* sample->loop.count != 0xFFFFFFFF && */ sample->loop.count != 0) + if (sample->loop.count != 0) { - //for (int i = 0; i < sample->loop.count; i++) for (int i = 0; i < 16; i++) { - //if ((loopOffset + 16 + (i * 2)) >= audioBank.size()) - //break; - int16_t state = BitConverter::ToInt16BE(audioBank, loopOffset + 16 + (i * 2)); sample->loop.states.push_back(state); } diff --git a/ZAPDTR/ZAPD/ZAudio.h b/ZAPDTR/ZAPD/ZAudio.h index 511ba5ed6..286c75c11 100644 --- a/ZAPDTR/ZAPD/ZAudio.h +++ b/ZAPDTR/ZAPD/ZAudio.h @@ -95,6 +95,7 @@ public: std::map samples; std::vector> fontIndices; std::vector seqNames; + std::map soundFontNames; // First Key = Bank ID, Sec Key = LoopDataOffset, Third Key = Sample Data Offset std::map>> sampleOffsets; -- cgit v1.2.3 From 3f10195c0e4aaa5ed94fd3bbae147a6570332eda Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Tue, 14 Jun 2022 01:29:52 -0400 Subject: Added XML attributes and fixed odd crash --- ZAPDTR/ZAPD/ZAudio.cpp | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'ZAPDTR') diff --git a/ZAPDTR/ZAPD/ZAudio.cpp b/ZAPDTR/ZAPD/ZAudio.cpp index a502a0545..a8b0f1fa1 100644 --- a/ZAPDTR/ZAPD/ZAudio.cpp +++ b/ZAPDTR/ZAPD/ZAudio.cpp @@ -11,9 +11,10 @@ REGISTER_ZFILENODE(Audio, ZAudio); ZAudio::ZAudio(ZFile* nParent) : ZResource(nParent) { - //RegisterRequiredAttribute("CodeOffset"); - //RegisterOptionalAttribute("LangOffset", "0"); - + RegisterRequiredAttribute("SoundFontTableOffset"); + RegisterRequiredAttribute("SequenceTableOffset"); + RegisterRequiredAttribute("SampleBankTableOffset"); + RegisterRequiredAttribute("SequenceFontTableOffset"); } void ZAudio::ParseXML(tinyxml2::XMLElement* reader) @@ -156,11 +157,6 @@ SampleEntry* ZAudio::ParseSampleEntry(std::vector audioBank, sample->loop.end = BitConverter::ToInt32BE(audioBank, loopOffset + 4); sample->loop.count = BitConverter::ToInt32BE(audioBank, loopOffset + 8); - if (sample->loop.start == 0x3ADB) - { - int bp = 0; - } - if (sample->loop.count != 0) { for (int i = 0; i < 16; i++) @@ -341,30 +337,30 @@ void ZAudio::ParseRawData() audioSeqData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audioseq"); - //codeData = File::ReadAllBytes("baserom/code_ntsc"); - //audioTableData = File::ReadAllBytes("baserom/Audiotable_ntsc"); - //audioSeqData = File::ReadAllBytes("baserom/Audioseq_ntsc"); - //audioBankData = File::ReadAllBytes("baserom/Audiobank_ntsc"); - // TABLE PARSING // GC PAL - //int gSoundFontTableOffset = 0x138270; // OTRTODO: Make this an XML Param - //int gSequenceTableOffset = 0x1386A0; // OTRTODO: Make this an XML Param - //int gSampleBankTableOffset = 0x138D90; // OTRTODO: Make this an XML Param - //int gSequenceFontTableOffset = 0x1384E0; // OTRTODO: Make this an XML Param + //int gSoundFontTableOffset = 0x138270; + //int gSequenceTableOffset = 0x1386A0; + //int gSampleBankTableOffset = 0x138D90; + //int gSequenceFontTableOffset = 0x1384E0; // NMQ DBG ROM - int gSoundFontTableOffset = 0x138290; // OTRTODO: Make this an XML Param - int gSequenceTableOffset = 0x1386C0; // OTRTODO: Make this an XML Param - int gSampleBankTableOffset = 0x138DB0; // OTRTODO: Make this an XML Param - int gSequenceFontTableOffset = 0x138500; // OTRTODO: Make this an XML Param + //int gSoundFontTableOffset = 0x138290; + //int gSequenceTableOffset = 0x1386C0; + //int gSampleBankTableOffset = 0x138DB0; + //int gSequenceFontTableOffset = 0x138500; // NTSC 1.0 - //int gSoundFontTableOffset = 0x1026A0; // OTRTODO: Make this an XML Param - //int gSequenceTableOffset = 0x102AD0; // OTRTODO: Make this an XML Param - //int gSampleBankTableOffset = 0x1031C0; // OTRTODO: Make this an XML Param - //int gSequenceFontTableOffset = 0x102910; // OTRTODO: Make this an XML Param + //int gSoundFontTableOffset = 0x1026A0; + //int gSequenceTableOffset = 0x102AD0; + //int gSampleBankTableOffset = 0x1031C0; + //int gSequenceFontTableOffset = 0x102910; + + int gSoundFontTableOffset = StringHelper::StrToL(registeredAttributes.at("SoundFontTableOffset").value, 16); + int gSequenceTableOffset = StringHelper::StrToL(registeredAttributes.at("SequenceTableOffset").value, 16); + int gSampleBankTableOffset = StringHelper::StrToL(registeredAttributes.at("SampleBankTableOffset").value, 16); + int gSequenceFontTableOffset = StringHelper::StrToL(registeredAttributes.at("SequenceFontTableOffset").value, 16); soundFontTable = ParseAudioTable(codeData, gSoundFontTableOffset); sequenceTable = ParseAudioTable(codeData, gSequenceTableOffset); -- cgit v1.2.3 From aeaaa54e0daa7482bdcdd0f26466b738b25fe4e3 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Tue, 14 Jun 2022 12:32:11 -0400 Subject: GC PAL Audio XML --- ZAPDTR/ZAPD/ZAudio.cpp | 8 +------- ZAPDTR/ZAPD/ZRom.cpp | 4 +--- 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'ZAPDTR') diff --git a/ZAPDTR/ZAPD/ZAudio.cpp b/ZAPDTR/ZAPD/ZAudio.cpp index a8b0f1fa1..2d92979aa 100644 --- a/ZAPDTR/ZAPD/ZAudio.cpp +++ b/ZAPDTR/ZAPD/ZAudio.cpp @@ -339,17 +339,11 @@ void ZAudio::ParseRawData() // TABLE PARSING - // GC PAL + // MQ DBG ROM //int gSoundFontTableOffset = 0x138270; //int gSequenceTableOffset = 0x1386A0; //int gSampleBankTableOffset = 0x138D90; //int gSequenceFontTableOffset = 0x1384E0; - - // NMQ DBG ROM - //int gSoundFontTableOffset = 0x138290; - //int gSequenceTableOffset = 0x1386C0; - //int gSampleBankTableOffset = 0x138DB0; - //int gSequenceFontTableOffset = 0x138500; // NTSC 1.0 //int gSoundFontTableOffset = 0x1026A0; diff --git a/ZAPDTR/ZAPD/ZRom.cpp b/ZAPDTR/ZAPD/ZRom.cpp index a311714dd..0a4944be0 100644 --- a/ZAPDTR/ZAPD/ZRom.cpp +++ b/ZAPDTR/ZAPD/ZRom.cpp @@ -192,10 +192,8 @@ ZRom::ZRom(std::string romPath) else files[lines[i]] = outData; - //File::WriteAllBytes(StringHelper::Sprintf("baserom/%s", lines[i]), files[lines[i]]); + //File::WriteAllBytes(StringHelper::Sprintf("baserom/%s", lines[i].c_str()), files[lines[i]]); } - - int bp = 0; } std::vector ZRom::GetFile(std::string fileName) -- cgit v1.2.3