Audio decompiled and WIP custom sample support
This commit is contained in:
@@ -142,7 +142,7 @@ namespace Ship {
|
||||
return FileToLoad;
|
||||
}
|
||||
|
||||
bool Archive::AddFile(const std::string& path, uintptr_t fileData, DWORD dwFileSize) {
|
||||
bool Archive::AddFile(const std::string& oPath, uintptr_t fileData, DWORD dwFileSize) {
|
||||
HANDLE hFile;
|
||||
#ifdef _WIN32
|
||||
SYSTEMTIME sysTime;
|
||||
@@ -154,6 +154,11 @@ namespace Ship {
|
||||
time_t stupidHack;
|
||||
time(&stupidHack);
|
||||
#endif
|
||||
|
||||
std::string path = oPath;
|
||||
|
||||
StringHelper::ReplaceOriginal(path, "\\", "/");
|
||||
|
||||
if (!SFileCreateFile(mainMPQ, path.c_str(), stupidHack, dwFileSize, 0, MPQ_FILE_COMPRESS, &hFile)) {
|
||||
SPDLOG_ERROR("({}) Failed to create file of {} bytes {} in archive {}", GetLastError(), dwFileSize, path.c_str(), MainPath.c_str());
|
||||
return false;
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace Ship
|
||||
TextureAnimationParams,
|
||||
Vector,
|
||||
Vertex,
|
||||
Audio
|
||||
};
|
||||
|
||||
class ArrayV0 : public ResourceFile
|
||||
|
||||
168
libultraship/libultraship/Audio.cpp
Normal file
168
libultraship/libultraship/Audio.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "Audio.h"
|
||||
|
||||
namespace Ship
|
||||
{
|
||||
void AudioSampleV1::ParseFileBinary(BinaryReader* reader, Resource* res)
|
||||
{
|
||||
AudioSample* entry = (AudioSample*)res;
|
||||
|
||||
ResourceFile::ParseFileBinary(reader, res);
|
||||
|
||||
entry->codec = reader->ReadByte();
|
||||
entry->medium = reader->ReadByte();
|
||||
entry->unk_bit26 = reader->ReadByte();
|
||||
entry->unk_bit25 = reader->ReadByte();
|
||||
|
||||
int dataSize = reader->ReadInt32();
|
||||
|
||||
for (size_t i = 0; i < dataSize; i++)
|
||||
entry->data.push_back(reader->ReadUByte());
|
||||
|
||||
entry->loop.start = reader->ReadUInt32();
|
||||
entry->loop.end = reader->ReadUInt32();
|
||||
entry->loop.count = reader->ReadUInt32();
|
||||
|
||||
int loopStateCnt = reader->ReadUInt32();
|
||||
|
||||
for (size_t i = 0; i < loopStateCnt; i++)
|
||||
entry->loop.states.push_back(reader->ReadInt16());
|
||||
|
||||
entry->book.order = reader->ReadInt32();
|
||||
entry->book.npredictors = reader->ReadInt32();
|
||||
|
||||
int bookSize = reader->ReadInt32();
|
||||
|
||||
for (size_t i = 0; i < bookSize; i++)
|
||||
entry->book.books.push_back(reader->ReadInt16());
|
||||
}
|
||||
|
||||
void AudioSoundFontV1::ParseFileBinary(BinaryReader* reader, Resource* res)
|
||||
{
|
||||
AudioSoundFont* soundFont = (AudioSoundFont*)res;
|
||||
|
||||
ResourceFile::ParseFileBinary(reader, res);
|
||||
|
||||
soundFont->medium = reader->ReadByte();
|
||||
soundFont->cachePolicy = reader->ReadByte();
|
||||
soundFont->data1 = reader->ReadInt16();
|
||||
soundFont->data2 = reader->ReadInt16();
|
||||
soundFont->data3 = reader->ReadInt16();
|
||||
|
||||
int drumCnt = reader->ReadInt32();
|
||||
int instrumentCnt = reader->ReadInt32();
|
||||
int sfxCnt = reader->ReadInt32();
|
||||
|
||||
for (int i = 0; i < drumCnt; i++)
|
||||
{
|
||||
DrumEntry drum;
|
||||
drum.releaseRate = reader->ReadUByte();
|
||||
drum.pan = reader->ReadUByte();
|
||||
drum.loaded = reader->ReadUByte();
|
||||
|
||||
drum.env = ReadEnvelopeData(reader);
|
||||
|
||||
bool hasSample = reader->ReadByte();
|
||||
drum.offset = reader->ReadInt32();
|
||||
drum.tuning = reader->ReadSingle();
|
||||
|
||||
soundFont->drums.push_back(drum);
|
||||
}
|
||||
|
||||
for (int i = 0; i < instrumentCnt; i++)
|
||||
{
|
||||
InstrumentEntry entry;
|
||||
|
||||
entry.isValidEntry = reader->ReadByte();
|
||||
entry.loaded = reader->ReadByte();
|
||||
entry.normalRangeLo = reader->ReadByte();
|
||||
entry.normalRangeHi = reader->ReadByte();
|
||||
entry.releaseRate = reader->ReadByte();
|
||||
|
||||
entry.env = ReadEnvelopeData(reader);
|
||||
|
||||
{
|
||||
bool hasSFEntry = reader->ReadByte();
|
||||
|
||||
if (hasSFEntry)
|
||||
{
|
||||
entry.lowNotesSound = new SoundFontEntry();
|
||||
bool hasSampleRef = reader->ReadByte();
|
||||
entry.lowNotesSound->sampleOffset = reader->ReadInt32();
|
||||
entry.lowNotesSound->tuning = reader->ReadSingle();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
bool hasSFEntry = reader->ReadByte();
|
||||
|
||||
if (hasSFEntry)
|
||||
{
|
||||
entry.normalNotesSound = new SoundFontEntry();
|
||||
bool hasSampleRef = reader->ReadByte();
|
||||
entry.normalNotesSound->sampleOffset = reader->ReadInt32();
|
||||
entry.normalNotesSound->tuning = reader->ReadSingle();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
bool hasSFEntry = reader->ReadByte();
|
||||
|
||||
if (hasSFEntry)
|
||||
{
|
||||
entry.highNotesSound = new SoundFontEntry();
|
||||
bool hasSampleRef = reader->ReadByte();
|
||||
entry.highNotesSound->sampleOffset = reader->ReadInt32();
|
||||
entry.highNotesSound->tuning = reader->ReadSingle();
|
||||
}
|
||||
}
|
||||
|
||||
soundFont->instruments.push_back(entry);
|
||||
}
|
||||
|
||||
for (int i = 0; i < sfxCnt; i++)
|
||||
{
|
||||
SoundFontEntry* entry = new SoundFontEntry();
|
||||
|
||||
bool hasSFEntry = reader->ReadByte();
|
||||
|
||||
if (hasSFEntry)
|
||||
{
|
||||
bool hasSampleRef = reader->ReadByte();
|
||||
entry->sampleOffset = reader->ReadInt32();
|
||||
entry->tuning = reader->ReadSingle();
|
||||
}
|
||||
|
||||
soundFont->soundEffects.push_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<AdsrEnvelope*> AudioSoundFontV1::ReadEnvelopeData(BinaryReader* reader)
|
||||
{
|
||||
std::vector<AdsrEnvelope*> envelopes;
|
||||
|
||||
int envelopeCnt = reader->ReadInt32();
|
||||
|
||||
for (int i = 0; i < envelopeCnt; i++)
|
||||
{
|
||||
AdsrEnvelope* env = new AdsrEnvelope();
|
||||
env->delay = reader->ReadInt16();
|
||||
env->arg = reader->ReadInt16();
|
||||
|
||||
envelopes.push_back(env);
|
||||
}
|
||||
|
||||
return envelopes;
|
||||
}
|
||||
|
||||
void AudioV1::ParseFileBinary(BinaryReader* reader, Resource* res)
|
||||
{
|
||||
Audio* audio = (Audio*)res;
|
||||
|
||||
ResourceFile::ParseFileBinary(reader, res);
|
||||
|
||||
//int sampleCnt = reader->ReadInt32();
|
||||
|
||||
//for (size_t i = 0; i < sampleCnt; i++)
|
||||
//audio->samples.push_back(ReadSampleEntry(reader));
|
||||
}
|
||||
}
|
||||
120
libultraship/libultraship/Audio.h
Normal file
120
libultraship/libultraship/Audio.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
|
||||
#include "Resource.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace Ship
|
||||
{
|
||||
struct AdsrEnvelope
|
||||
{
|
||||
int16_t delay;
|
||||
int16_t arg;
|
||||
};
|
||||
|
||||
struct AdpcmBook
|
||||
{
|
||||
/* 0x00 */ int32_t order;
|
||||
/* 0x04 */ int32_t npredictors;
|
||||
/* 0x08 */ std::vector<int16_t> 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<int16_t> states;
|
||||
};
|
||||
|
||||
struct SoundFontEntry
|
||||
{
|
||||
//SampleEntry* sampleEntry = nullptr;
|
||||
uint32_t sampleOffset;
|
||||
float tuning;
|
||||
};
|
||||
|
||||
struct DrumEntry
|
||||
{
|
||||
uint8_t releaseRate;
|
||||
uint8_t pan;
|
||||
uint8_t loaded;
|
||||
uint32_t offset;
|
||||
float tuning;
|
||||
std::vector<AdsrEnvelope*> env;
|
||||
//SampleEntry* sample = nullptr;
|
||||
};
|
||||
|
||||
struct InstrumentEntry
|
||||
{
|
||||
bool isValidEntry;
|
||||
uint8_t loaded;
|
||||
uint8_t normalRangeLo;
|
||||
uint8_t normalRangeHi;
|
||||
uint8_t releaseRate;
|
||||
std::vector<AdsrEnvelope*> env;
|
||||
SoundFontEntry* lowNotesSound = nullptr;
|
||||
SoundFontEntry* normalNotesSound = nullptr;
|
||||
SoundFontEntry* highNotesSound = nullptr;
|
||||
};
|
||||
|
||||
class AudioSoundFontV1 : public ResourceFile
|
||||
{
|
||||
public:
|
||||
void ParseFileBinary(BinaryReader* reader, Resource* res) override;
|
||||
static std::vector<AdsrEnvelope*> ReadEnvelopeData(BinaryReader* reader);
|
||||
};
|
||||
|
||||
class AudioSampleV1 : public ResourceFile
|
||||
{
|
||||
public:
|
||||
void ParseFileBinary(BinaryReader* reader, Resource* res) override;
|
||||
};
|
||||
|
||||
class AudioV1 : public ResourceFile
|
||||
{
|
||||
public:
|
||||
void ParseFileBinary(BinaryReader* reader, Resource* res) override;
|
||||
};
|
||||
|
||||
struct AudioSoundFont : public Resource
|
||||
{
|
||||
public:
|
||||
uint32_t ptr;
|
||||
uint32_t size;
|
||||
uint8_t medium;
|
||||
uint8_t cachePolicy;
|
||||
uint16_t data1;
|
||||
uint16_t data2;
|
||||
uint16_t data3;
|
||||
|
||||
std::vector<DrumEntry> drums;
|
||||
std::vector<SoundFontEntry*> soundEffects;
|
||||
std::vector<InstrumentEntry> instruments;
|
||||
};
|
||||
|
||||
class AudioSample : public Resource
|
||||
{
|
||||
public:
|
||||
uint8_t codec;
|
||||
uint8_t medium;
|
||||
uint8_t unk_bit26;
|
||||
uint8_t unk_bit25;
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
AdpcmLoop loop;
|
||||
AdpcmBook book;
|
||||
};
|
||||
|
||||
class Audio : public Resource
|
||||
{
|
||||
public:
|
||||
//std::vector<AudioTableEntry> soundFontTable;
|
||||
//std::vector<AudioTableEntry> sequenceTable;
|
||||
//std::vector<AudioTableEntry> sampleBankTable;
|
||||
//std::vector<char*> sequences;
|
||||
//std::vector<SampleEntry*> samples;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -16,6 +16,4 @@ void Ship::CutsceneV0::ParseFileBinary(BinaryReader* reader, Resource* res)
|
||||
|
||||
cs->commands.push_back(data);
|
||||
}
|
||||
|
||||
//int bp = 0;
|
||||
}
|
||||
|
||||
69
libultraship/libultraship/Factories/AudioFactory.cpp
Normal file
69
libultraship/libultraship/Factories/AudioFactory.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "AudioFactory.h"
|
||||
|
||||
namespace Ship
|
||||
{
|
||||
Audio* AudioFactory::ReadAudio(BinaryReader* reader)
|
||||
{
|
||||
Audio* audio = new Audio();
|
||||
Version version = (Version)reader->ReadUInt32();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case Version::Roy:
|
||||
{
|
||||
AudioV1 audioFac = AudioV1();
|
||||
audioFac.ParseFileBinary(reader, audio);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// VERSION NOT SUPPORTED
|
||||
break;
|
||||
}
|
||||
|
||||
return audio;
|
||||
}
|
||||
|
||||
AudioSample* AudioSampleFactory::ReadAudioSample(BinaryReader* reader)
|
||||
{
|
||||
AudioSample* audioSample = new AudioSample();
|
||||
Version version = (Version)reader->ReadUInt32();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case Version::Deckard: // OTRTODO: Remove this line after we merge in that refactor
|
||||
case Version::Roy:
|
||||
{
|
||||
AudioSampleV1 audioSampleFac = AudioSampleV1();
|
||||
audioSampleFac.ParseFileBinary(reader, audioSample);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// VERSION NOT SUPPORTED
|
||||
break;
|
||||
}
|
||||
|
||||
return audioSample;
|
||||
}
|
||||
|
||||
AudioSoundFont* AudioSoundFontFactory::ReadAudioSoundFont(BinaryReader* reader)
|
||||
{
|
||||
AudioSoundFont* audioSF = new AudioSoundFont();
|
||||
Version version = (Version)reader->ReadUInt32();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case Version::Deckard: // OTRTODO: Remove this line after we merge in that refactor
|
||||
case Version::Roy:
|
||||
{
|
||||
AudioSoundFontV1 audioSFFac = AudioSoundFontV1();
|
||||
audioSFFac.ParseFileBinary(reader, audioSF);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// VERSION NOT SUPPORTED
|
||||
break;
|
||||
}
|
||||
|
||||
return audioSF;
|
||||
}
|
||||
};
|
||||
23
libultraship/libultraship/Factories/AudioFactory.h
Normal file
23
libultraship/libultraship/Factories/AudioFactory.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "../Audio.h"
|
||||
#include "Utils/BinaryReader.h"
|
||||
|
||||
namespace Ship
|
||||
{
|
||||
class AudioFactory
|
||||
{
|
||||
public:
|
||||
static Audio* ReadAudio(BinaryReader* reader);
|
||||
};
|
||||
|
||||
class AudioSampleFactory
|
||||
{
|
||||
public:
|
||||
static AudioSample* ReadAudioSample(BinaryReader* reader);
|
||||
};
|
||||
|
||||
class AudioSoundFontFactory
|
||||
{
|
||||
public:
|
||||
static AudioSoundFont* ReadAudioSoundFont(BinaryReader* reader);
|
||||
};
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "TextureFactory.h"
|
||||
#include "BlobFactory.h"
|
||||
#include "MtxFactory.h"
|
||||
#include "AudioFactory.h"
|
||||
#include <Utils/MemoryStream.h>
|
||||
|
||||
namespace Ship
|
||||
@@ -84,6 +85,15 @@ namespace Ship
|
||||
case ResourceType::Matrix:
|
||||
result = MtxFactory::ReadMtx(reader.get());
|
||||
break;
|
||||
case ResourceType::Audio:
|
||||
result = AudioFactory::ReadAudio(reader.get());
|
||||
break;
|
||||
case ResourceType::AudioSample:
|
||||
result = AudioSampleFactory::ReadAudioSample(reader.get());
|
||||
break;
|
||||
case ResourceType::AudioSoundFont:
|
||||
result = AudioSoundFontFactory::ReadAudioSoundFont(reader.get());
|
||||
break;
|
||||
default:
|
||||
// RESOURCE TYPE NOT SUPPORTED
|
||||
break;
|
||||
|
||||
@@ -30,6 +30,9 @@ namespace Ship
|
||||
Array = 0x4F415252, // OARR
|
||||
Text = 0x4F545854, // OTXT
|
||||
Blob = 0x4F424C42, // OBLB
|
||||
Audio = 'OAUD',
|
||||
AudioSample = 'OSMP',
|
||||
AudioSoundFont = 'OSFT',
|
||||
};
|
||||
|
||||
enum class DataType
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -253,9 +253,11 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Audio.cpp" />
|
||||
<ClCompile Include="Blob.cpp" />
|
||||
<ClCompile Include="Cvar.cpp" />
|
||||
<ClCompile Include="Environment.cpp" />
|
||||
<ClCompile Include="Factories\AudioFactory.cpp" />
|
||||
<ClCompile Include="GameOverlay.cpp" />
|
||||
<ClCompile Include="GameSettings.cpp" />
|
||||
<ClCompile Include="Lib\ImGui\backends\imgui_impl_dx11.cpp" />
|
||||
@@ -340,10 +342,12 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="abi.h" />
|
||||
<ClInclude Include="Audio.h" />
|
||||
<ClInclude Include="AudioPlayer.h" />
|
||||
<ClInclude Include="Blob.h" />
|
||||
<ClInclude Include="Cvar.h" />
|
||||
<ClInclude Include="Environment.h" />
|
||||
<ClInclude Include="Factories\AudioFactory.h" />
|
||||
<ClInclude Include="GameOverlay.h" />
|
||||
<ClInclude Include="GameSettings.h" />
|
||||
<ClInclude Include="GameVersions.h" />
|
||||
|
||||
@@ -345,6 +345,12 @@
|
||||
<ClCompile Include="GameOverlay.cpp">
|
||||
<Filter>Source Files\CustomImpl\Overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Audio.cpp">
|
||||
<Filter>Source Files\Resources\Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Factories\AudioFactory.cpp">
|
||||
<Filter>Source Files\Resources\Factories</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Lib\tinyxml2\tinyxml2.h">
|
||||
@@ -638,5 +644,11 @@
|
||||
<ClInclude Include="GameOverlay.h">
|
||||
<Filter>Source Files\CustomImpl\Overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Audio.h">
|
||||
<Filter>Header Files\Resources\Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Factories\AudioFactory.h">
|
||||
<Filter>Header Files\Resources\Factories</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user