mirror of
https://github.com/AxioDL/amuse.git
synced 2025-12-08 21:17:49 +00:00
Lots of foundational work for Amuse editor
This commit is contained in:
@@ -1,548 +1,224 @@
|
||||
#include "amuse/AudioGroupProject.hpp"
|
||||
#include "amuse/AudioGroupData.hpp"
|
||||
#include "amuse/Common.hpp"
|
||||
#include <stdint.h>
|
||||
#include "athena/MemoryReader.hpp"
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
|
||||
enum class GroupType : uint16_t
|
||||
static bool AtEnd32(athena::io::IStreamReader& r)
|
||||
{
|
||||
Song,
|
||||
SFX
|
||||
};
|
||||
uint32_t v = r.readUint32Big();
|
||||
r.seek(-4, athena::Current);
|
||||
return v == 0xffffffff;
|
||||
}
|
||||
|
||||
struct GroupHeader
|
||||
static bool AtEnd16(athena::io::IStreamReader& r)
|
||||
{
|
||||
uint32_t groupEndOff;
|
||||
uint16_t groupId;
|
||||
GroupType type;
|
||||
uint32_t soundMacroIdsOff;
|
||||
uint32_t samplIdsOff;
|
||||
uint32_t tableIdsOff;
|
||||
uint32_t keymapIdsOff;
|
||||
uint32_t layerIdsOff;
|
||||
uint32_t pageTableOff;
|
||||
uint32_t drumTableOff;
|
||||
uint32_t midiSetupsOff;
|
||||
uint16_t v = r.readUint16Big();
|
||||
r.seek(-2, athena::Current);
|
||||
return v == 0xffff;
|
||||
}
|
||||
|
||||
void swapBig()
|
||||
AudioGroupProject::AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag)
|
||||
{
|
||||
while (!AtEnd32(r))
|
||||
{
|
||||
groupEndOff = SBig(groupEndOff);
|
||||
groupId = SBig(groupId);
|
||||
type = GroupType(SBig(uint16_t(type)));
|
||||
soundMacroIdsOff = SBig(soundMacroIdsOff);
|
||||
samplIdsOff = SBig(samplIdsOff);
|
||||
tableIdsOff = SBig(tableIdsOff);
|
||||
keymapIdsOff = SBig(keymapIdsOff);
|
||||
layerIdsOff = SBig(layerIdsOff);
|
||||
pageTableOff = SBig(pageTableOff);
|
||||
drumTableOff = SBig(drumTableOff);
|
||||
midiSetupsOff = SBig(midiSetupsOff);
|
||||
}
|
||||
};
|
||||
|
||||
AudioGroupProject::AudioGroupProject(const unsigned char* data, GCNDataTag)
|
||||
{
|
||||
const GroupHeader* group = reinterpret_cast<const GroupHeader*>(data);
|
||||
while (group->groupEndOff != 0xffffffff)
|
||||
{
|
||||
GroupHeader header = *group;
|
||||
header.swapBig();
|
||||
|
||||
AudioGroupIndex* bIdx = nullptr;
|
||||
GroupHeader<athena::Big> header;
|
||||
header.read(r);
|
||||
|
||||
if (header.type == GroupType::Song)
|
||||
{
|
||||
SongGroupIndex& idx = m_songGroups[header.groupId];
|
||||
bIdx = &idx;
|
||||
|
||||
/* Normal pages */
|
||||
const SongGroupIndex::PageEntry* normEntries =
|
||||
reinterpret_cast<const SongGroupIndex::PageEntry*>(data + header.pageTableOff);
|
||||
while (normEntries->objId != 0xffff)
|
||||
r.seek(header.pageTableOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
{
|
||||
idx.m_normPages[normEntries->programNo] = normEntries;
|
||||
++normEntries;
|
||||
SongGroupIndex::PageEntryDNA<athena::Big> entry;
|
||||
entry.read(r);
|
||||
idx.m_normPages[entry.programNo] = entry;
|
||||
}
|
||||
|
||||
/* Drum pages */
|
||||
const SongGroupIndex::PageEntry* drumEntries =
|
||||
reinterpret_cast<const SongGroupIndex::PageEntry*>(data + header.drumTableOff);
|
||||
while (drumEntries->objId != 0xffff)
|
||||
r.seek(header.drumTableOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
{
|
||||
idx.m_drumPages[drumEntries->programNo] = drumEntries;
|
||||
++drumEntries;
|
||||
SongGroupIndex::PageEntryDNA<athena::Big> entry;
|
||||
entry.read(r);
|
||||
idx.m_drumPages[entry.programNo] = entry;
|
||||
}
|
||||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = data + header.midiSetupsOff;
|
||||
const uint8_t* setupEnd = data + header.groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
r.seek(header.midiSetupsOff, athena::Begin);
|
||||
while (r.position() < header.groupEndOff)
|
||||
{
|
||||
uint16_t songId = SBig(*reinterpret_cast<const uint16_t*>(setupData));
|
||||
idx.m_midiSetups[songId] =
|
||||
reinterpret_cast<const std::array<SongGroupIndex::MIDISetup, 16>*>(setupData + 4);
|
||||
setupData += 5 * 16 + 4;
|
||||
uint16_t songId = r.readUint16Big();
|
||||
r.seek(2, athena::Current);
|
||||
std::array<SongGroupIndex::MIDISetup, 16>& setup = idx.m_midiSetups[songId];
|
||||
for (int i = 0; i < 16 ; ++i)
|
||||
setup[i].read(r);
|
||||
}
|
||||
}
|
||||
else if (header.type == GroupType::SFX)
|
||||
{
|
||||
SFXGroupIndex& idx = m_sfxGroups[header.groupId];
|
||||
bIdx = &idx;
|
||||
|
||||
/* SFX entries */
|
||||
uint16_t count = SBig(*reinterpret_cast<const uint16_t*>(data + header.pageTableOff));
|
||||
r.seek(header.pageTableOff, athena::Begin);
|
||||
uint16_t count = r.readUint16Big();
|
||||
r.seek(2, athena::Current);
|
||||
idx.m_sfxEntries.reserve(count);
|
||||
const SFXGroupIndex::SFXEntry* entries =
|
||||
reinterpret_cast<const SFXGroupIndex::SFXEntry*>(data + header.pageTableOff + 4);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
idx.m_sfxEntries[SBig(entries->defineId)] = entries;
|
||||
++entries;
|
||||
SFXGroupIndex::SFXEntryDNA<athena::Big> entry;
|
||||
entry.read(r);
|
||||
idx.m_sfxEntries[entry.defineId.id] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
if (bIdx)
|
||||
{
|
||||
bIdx->m_soundMacroIndex = reinterpret_cast<const uint16_t*>(data + header.soundMacroIdsOff);
|
||||
bIdx->m_tablesIndex = reinterpret_cast<const uint16_t*>(data + header.tableIdsOff);
|
||||
bIdx->m_keymapsIndex = reinterpret_cast<const uint16_t*>(data + header.keymapIdsOff);
|
||||
bIdx->m_layersIndex = reinterpret_cast<const uint16_t*>(data + header.layerIdsOff);
|
||||
}
|
||||
|
||||
group = reinterpret_cast<const GroupHeader*>(data + header.groupEndOff);
|
||||
r.seek(header.groupEndOff, athena::Begin);
|
||||
}
|
||||
}
|
||||
|
||||
struct MusyX1PageEntry
|
||||
template <athena::Endian DNAE>
|
||||
AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReader& r, bool absOffs)
|
||||
{
|
||||
ObjectId objId;
|
||||
uint8_t priority;
|
||||
uint8_t maxVoices;
|
||||
uint8_t unk;
|
||||
uint8_t programNo;
|
||||
uint8_t pad[2];
|
||||
AudioGroupProject ret;
|
||||
|
||||
void setIntoMusyX2(SongGroupIndex::PageEntry& ent) const
|
||||
while (!AtEnd32(r))
|
||||
{
|
||||
ent.objId = objId;
|
||||
ent.priority = priority;
|
||||
ent.maxVoices = maxVoices;
|
||||
ent.programNo = programNo;
|
||||
}
|
||||
};
|
||||
|
||||
struct MusyX1MIDISetup
|
||||
{
|
||||
uint8_t programNo;
|
||||
uint8_t volume;
|
||||
uint8_t panning;
|
||||
uint8_t reverb;
|
||||
uint8_t chorus;
|
||||
uint8_t pad[3];
|
||||
|
||||
void setIntoMusyX2(SongGroupIndex::MIDISetup& ent) const
|
||||
{
|
||||
ent.programNo = programNo;
|
||||
ent.volume = volume;
|
||||
ent.panning = panning;
|
||||
ent.reverb = reverb;
|
||||
ent.chorus = chorus;
|
||||
}
|
||||
};
|
||||
|
||||
void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, N64DataTag)
|
||||
{
|
||||
size_t normPageCount = 0;
|
||||
size_t drumPageCount = 0;
|
||||
size_t midiSetupCount = 0;
|
||||
|
||||
const GroupHeader* group = reinterpret_cast<const GroupHeader*>(data);
|
||||
while (group->groupEndOff != 0xffffffff)
|
||||
{
|
||||
const unsigned char* subData = data + 8;
|
||||
GroupHeader header = *group;
|
||||
header.swapBig();
|
||||
atInt64 groupBegin = r.position();
|
||||
atInt64 subDataOff = absOffs ? 0 : groupBegin + 8;
|
||||
GroupHeader<DNAE> header;
|
||||
header.read(r);
|
||||
|
||||
if (header.type == GroupType::Song)
|
||||
{
|
||||
/* Normal pages */
|
||||
const MusyX1PageEntry* normEntries =
|
||||
reinterpret_cast<const MusyX1PageEntry*>(subData + header.pageTableOff);
|
||||
while (normEntries->objId != 0xffff)
|
||||
{
|
||||
++normPageCount;
|
||||
++normEntries;
|
||||
}
|
||||
|
||||
/* Drum pages */
|
||||
const MusyX1PageEntry* drumEntries =
|
||||
reinterpret_cast<const MusyX1PageEntry*>(subData + header.drumTableOff);
|
||||
while (drumEntries->objId != 0xffff)
|
||||
{
|
||||
++drumPageCount;
|
||||
++drumEntries;
|
||||
}
|
||||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = subData + header.midiSetupsOff;
|
||||
const uint8_t* setupEnd = subData + header.groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
{
|
||||
++midiSetupCount;
|
||||
setupData += 8 * 16 + 4;
|
||||
}
|
||||
}
|
||||
|
||||
data += header.groupEndOff;
|
||||
group = reinterpret_cast<const GroupHeader*>(data);
|
||||
}
|
||||
|
||||
if (normPageCount)
|
||||
m_convNormalPages.reset(new SongGroupIndex::PageEntry[normPageCount]);
|
||||
if (drumPageCount)
|
||||
m_convDrumPages.reset(new SongGroupIndex::PageEntry[drumPageCount]);
|
||||
if (midiSetupCount)
|
||||
m_convMidiSetups.reset(new std::array<SongGroupIndex::MIDISetup, 16>[ midiSetupCount ]);
|
||||
}
|
||||
|
||||
AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N64DataTag)
|
||||
{
|
||||
if (!absOffs)
|
||||
_allocateConvBuffers(data, N64DataTag{});
|
||||
SongGroupIndex::PageEntry* normPagesBuf = m_convNormalPages.get();
|
||||
SongGroupIndex::PageEntry* drumPagesBuf = m_convDrumPages.get();
|
||||
std::array<SongGroupIndex::MIDISetup, 16>* midiSetupsBuf = m_convMidiSetups.get();
|
||||
|
||||
const GroupHeader* group = reinterpret_cast<const GroupHeader*>(data);
|
||||
while (group->groupEndOff != 0xffffffff)
|
||||
{
|
||||
const unsigned char* subData = absOffs ? data : data + 8;
|
||||
GroupHeader header = *group;
|
||||
header.swapBig();
|
||||
|
||||
AudioGroupIndex* bIdx = nullptr;
|
||||
|
||||
if (header.type == GroupType::Song)
|
||||
{
|
||||
SongGroupIndex& idx = m_songGroups[header.groupId];
|
||||
bIdx = &idx;
|
||||
SongGroupIndex& idx = ret.m_songGroups[header.groupId];
|
||||
|
||||
if (absOffs)
|
||||
{
|
||||
/* Normal pages */
|
||||
const SongGroupIndex::PageEntry* normEntries =
|
||||
reinterpret_cast<const SongGroupIndex::PageEntry*>(data + header.pageTableOff);
|
||||
while (normEntries->objId != 0xffff)
|
||||
r.seek(header.pageTableOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
{
|
||||
idx.m_normPages[normEntries->programNo] = normEntries;
|
||||
++normEntries;
|
||||
SongGroupIndex::PageEntryDNA<DNAE> entry;
|
||||
entry.read(r);
|
||||
idx.m_normPages[entry.programNo] = entry;
|
||||
}
|
||||
|
||||
/* Drum pages */
|
||||
const SongGroupIndex::PageEntry* drumEntries =
|
||||
reinterpret_cast<const SongGroupIndex::PageEntry*>(data + header.drumTableOff);
|
||||
while (drumEntries->objId != 0xffff)
|
||||
r.seek(header.drumTableOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
{
|
||||
idx.m_drumPages[drumEntries->programNo] = drumEntries;
|
||||
++drumEntries;
|
||||
SongGroupIndex::PageEntryDNA<DNAE> entry;
|
||||
entry.read(r);
|
||||
idx.m_drumPages[entry.programNo] = entry;
|
||||
}
|
||||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = data + header.midiSetupsOff;
|
||||
const uint8_t* setupEnd = data + header.groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
r.seek(header.midiSetupsOff, athena::Begin);
|
||||
while (r.position() < header.groupEndOff)
|
||||
{
|
||||
uint16_t songId = SBig(*reinterpret_cast<const uint16_t*>(setupData));
|
||||
idx.m_midiSetups[songId] =
|
||||
reinterpret_cast<const std::array<SongGroupIndex::MIDISetup, 16>*>(setupData + 4);
|
||||
setupData += 5 * 16 + 4;
|
||||
uint16_t songId = r.readUint16Big();
|
||||
r.seek(2, athena::Current);
|
||||
std::array<SongGroupIndex::MIDISetup, 16>& setup = idx.m_midiSetups[songId];
|
||||
for (int i = 0; i < 16 ; ++i)
|
||||
setup[i].read(r);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Normal pages */
|
||||
const MusyX1PageEntry* normEntries =
|
||||
reinterpret_cast<const MusyX1PageEntry*>(subData + header.pageTableOff);
|
||||
while (normEntries->objId != 0xffff)
|
||||
r.seek(subDataOff + header.pageTableOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
{
|
||||
normEntries->setIntoMusyX2(*normPagesBuf);
|
||||
idx.m_normPages[normEntries->programNo] = normPagesBuf;
|
||||
++normEntries;
|
||||
++normPagesBuf;
|
||||
SongGroupIndex::MusyX1PageEntryDNA<DNAE> entry;
|
||||
entry.read(r);
|
||||
idx.m_normPages[entry.programNo] = entry;
|
||||
}
|
||||
|
||||
/* Drum pages */
|
||||
const MusyX1PageEntry* drumEntries =
|
||||
reinterpret_cast<const MusyX1PageEntry*>(subData + header.drumTableOff);
|
||||
while (drumEntries->objId != 0xffff)
|
||||
r.seek(subDataOff + header.drumTableOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
{
|
||||
drumEntries->setIntoMusyX2(*drumPagesBuf);
|
||||
idx.m_drumPages[drumEntries->programNo] = drumPagesBuf;
|
||||
++drumEntries;
|
||||
++drumPagesBuf;
|
||||
SongGroupIndex::MusyX1PageEntryDNA<DNAE> entry;
|
||||
entry.read(r);
|
||||
idx.m_drumPages[entry.programNo] = entry;
|
||||
}
|
||||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = subData + header.midiSetupsOff;
|
||||
const uint8_t* setupEnd = subData + header.groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
r.seek(subDataOff + header.midiSetupsOff, athena::Begin);
|
||||
while (r.position() < groupBegin + header.groupEndOff)
|
||||
{
|
||||
uint16_t songId = SBig(*reinterpret_cast<const uint16_t*>(setupData));
|
||||
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
||||
reinterpret_cast<const std::array<MusyX1MIDISetup, 16>*>(setupData + 4);
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
(*midiSetups)[i].setIntoMusyX2((*midiSetupsBuf)[i]);
|
||||
|
||||
idx.m_midiSetups[songId] = midiSetupsBuf;
|
||||
setupData += 8 * 16 + 4;
|
||||
++midiSetupsBuf;
|
||||
uint16_t songId = r.readUint16Big();
|
||||
r.seek(2, athena::Current);
|
||||
std::array<SongGroupIndex::MIDISetup, 16>& setup = idx.m_midiSetups[songId];
|
||||
for (int i = 0; i < 16 ; ++i)
|
||||
{
|
||||
SongGroupIndex::MusyX1MIDISetup ent;
|
||||
ent.read(r);
|
||||
setup[i] = ent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (header.type == GroupType::SFX)
|
||||
{
|
||||
SFXGroupIndex& idx = m_sfxGroups[header.groupId];
|
||||
bIdx = &idx;
|
||||
SFXGroupIndex& idx = ret.m_sfxGroups[header.groupId];
|
||||
|
||||
/* SFX entries */
|
||||
uint16_t count = SBig(*reinterpret_cast<const uint16_t*>(subData + header.pageTableOff));
|
||||
r.seek(subDataOff + header.pageTableOff, athena::Begin);
|
||||
uint16_t count = r.readUint16Big();
|
||||
r.seek(2, athena::Current);
|
||||
idx.m_sfxEntries.reserve(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
const SFXGroupIndex::SFXEntry* entries =
|
||||
reinterpret_cast<const SFXGroupIndex::SFXEntry*>(subData + header.pageTableOff + 4 + i * 12);
|
||||
idx.m_sfxEntries[SBig(entries->defineId)] = entries;
|
||||
SFXGroupIndex::SFXEntryDNA<DNAE> entry;
|
||||
entry.read(r);
|
||||
r.seek(2, athena::Current);
|
||||
idx.m_sfxEntries[entry.defineId.id] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
if (bIdx)
|
||||
{
|
||||
bIdx->m_soundMacroIndex = reinterpret_cast<const uint16_t*>(subData + header.soundMacroIdsOff);
|
||||
bIdx->m_tablesIndex = reinterpret_cast<const uint16_t*>(subData + header.tableIdsOff);
|
||||
bIdx->m_keymapsIndex = reinterpret_cast<const uint16_t*>(subData + header.keymapIdsOff);
|
||||
bIdx->m_layersIndex = reinterpret_cast<const uint16_t*>(subData + header.layerIdsOff);
|
||||
}
|
||||
|
||||
if (absOffs)
|
||||
group = reinterpret_cast<const GroupHeader*>(data + header.groupEndOff);
|
||||
r.seek(header.groupEndOff, athena::Begin);
|
||||
else
|
||||
{
|
||||
data += header.groupEndOff;
|
||||
group = reinterpret_cast<const GroupHeader*>(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, PCDataTag)
|
||||
{
|
||||
size_t normPageCount = 0;
|
||||
size_t drumPageCount = 0;
|
||||
size_t midiSetupCount = 0;
|
||||
|
||||
const GroupHeader* group = reinterpret_cast<const GroupHeader*>(data);
|
||||
while (group->groupEndOff != 0xffffffff)
|
||||
{
|
||||
const unsigned char* subData = data + 8;
|
||||
|
||||
if (group->type == GroupType::Song)
|
||||
{
|
||||
/* Normal pages */
|
||||
const MusyX1PageEntry* normEntries =
|
||||
reinterpret_cast<const MusyX1PageEntry*>(subData + group->pageTableOff);
|
||||
while (normEntries->objId != 0xffff)
|
||||
{
|
||||
++normPageCount;
|
||||
++normEntries;
|
||||
}
|
||||
|
||||
/* Drum pages */
|
||||
const MusyX1PageEntry* drumEntries =
|
||||
reinterpret_cast<const MusyX1PageEntry*>(subData + group->drumTableOff);
|
||||
while (drumEntries->objId != 0xffff)
|
||||
{
|
||||
++drumPageCount;
|
||||
++drumEntries;
|
||||
}
|
||||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = subData + group->midiSetupsOff;
|
||||
const uint8_t* setupEnd = subData + group->groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
{
|
||||
++midiSetupCount;
|
||||
setupData += 8 * 16 + 4;
|
||||
}
|
||||
}
|
||||
|
||||
data += group->groupEndOff;
|
||||
group = reinterpret_cast<const GroupHeader*>(data);
|
||||
r.seek(groupBegin + header.groupEndOff, athena::Begin);
|
||||
}
|
||||
|
||||
if (normPageCount)
|
||||
m_convNormalPages.reset(new SongGroupIndex::PageEntry[normPageCount]);
|
||||
if (drumPageCount)
|
||||
m_convDrumPages.reset(new SongGroupIndex::PageEntry[drumPageCount]);
|
||||
if (midiSetupCount)
|
||||
m_convMidiSetups.reset(new std::array<SongGroupIndex::MIDISetup, 16>[ midiSetupCount ]);
|
||||
}
|
||||
|
||||
AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, PCDataTag)
|
||||
{
|
||||
if (!absOffs)
|
||||
_allocateConvBuffers(data, PCDataTag{});
|
||||
SongGroupIndex::PageEntry* normPagesBuf = m_convNormalPages.get();
|
||||
SongGroupIndex::PageEntry* drumPagesBuf = m_convDrumPages.get();
|
||||
std::array<SongGroupIndex::MIDISetup, 16>* midiSetupsBuf = m_convMidiSetups.get();
|
||||
|
||||
const GroupHeader* group = reinterpret_cast<const GroupHeader*>(data);
|
||||
while (group->groupEndOff != 0xffffffff)
|
||||
{
|
||||
const unsigned char* subData = absOffs ? data : data + 8;
|
||||
|
||||
AudioGroupIndex* bIdx = nullptr;
|
||||
|
||||
if (group->type == GroupType::Song)
|
||||
{
|
||||
SongGroupIndex& idx = m_songGroups[group->groupId];
|
||||
bIdx = &idx;
|
||||
|
||||
if (absOffs)
|
||||
{
|
||||
/* Normal pages */
|
||||
const SongGroupIndex::PageEntry* normEntries =
|
||||
reinterpret_cast<const SongGroupIndex::PageEntry*>(data + group->pageTableOff);
|
||||
while (normEntries->objId != 0xffff)
|
||||
{
|
||||
idx.m_normPages[normEntries->programNo] = normEntries;
|
||||
++normEntries;
|
||||
}
|
||||
|
||||
/* Drum pages */
|
||||
const SongGroupIndex::PageEntry* drumEntries =
|
||||
reinterpret_cast<const SongGroupIndex::PageEntry*>(data + group->drumTableOff);
|
||||
while (drumEntries->objId != 0xffff)
|
||||
{
|
||||
idx.m_drumPages[drumEntries->programNo] = drumEntries;
|
||||
++drumEntries;
|
||||
}
|
||||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = data + group->midiSetupsOff;
|
||||
const uint8_t* setupEnd = data + group->groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
{
|
||||
uint16_t songId = *reinterpret_cast<const uint16_t*>(setupData);
|
||||
idx.m_midiSetups[songId] =
|
||||
reinterpret_cast<const std::array<SongGroupIndex::MIDISetup, 16>*>(setupData + 4);
|
||||
setupData += 5 * 16 + 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Normal pages */
|
||||
const MusyX1PageEntry* normEntries =
|
||||
reinterpret_cast<const MusyX1PageEntry*>(subData + group->pageTableOff);
|
||||
while (normEntries->objId != 0xffff)
|
||||
{
|
||||
normEntries->setIntoMusyX2(*normPagesBuf);
|
||||
idx.m_normPages[normEntries->programNo] = normPagesBuf;
|
||||
++normEntries;
|
||||
++normPagesBuf;
|
||||
}
|
||||
|
||||
/* Drum pages */
|
||||
const MusyX1PageEntry* drumEntries =
|
||||
reinterpret_cast<const MusyX1PageEntry*>(subData + group->drumTableOff);
|
||||
while (drumEntries->objId != 0xffff)
|
||||
{
|
||||
drumEntries->setIntoMusyX2(*drumPagesBuf);
|
||||
idx.m_drumPages[drumEntries->programNo] = drumPagesBuf;
|
||||
++drumEntries;
|
||||
++drumPagesBuf;
|
||||
}
|
||||
|
||||
/* MIDI setups */
|
||||
const uint8_t* setupData = subData + group->midiSetupsOff;
|
||||
const uint8_t* setupEnd = subData + group->groupEndOff;
|
||||
while (setupData < setupEnd)
|
||||
{
|
||||
uint16_t songId = *reinterpret_cast<const uint16_t*>(setupData);
|
||||
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
||||
reinterpret_cast<const std::array<MusyX1MIDISetup, 16>*>(setupData + 4);
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
(*midiSetups)[i].setIntoMusyX2((*midiSetupsBuf)[i]);
|
||||
|
||||
idx.m_midiSetups[songId] = midiSetupsBuf;
|
||||
setupData += 8 * 16 + 4;
|
||||
++midiSetupsBuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (group->type == GroupType::SFX)
|
||||
{
|
||||
SFXGroupIndex& idx = m_sfxGroups[group->groupId];
|
||||
bIdx = &idx;
|
||||
|
||||
/* SFX entries */
|
||||
uint16_t count = *reinterpret_cast<const uint16_t*>(subData + group->pageTableOff);
|
||||
idx.m_sfxEntries.reserve(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
const SFXGroupIndex::SFXEntry* entries =
|
||||
reinterpret_cast<const SFXGroupIndex::SFXEntry*>(subData + group->pageTableOff + 4 + i * 12);
|
||||
idx.m_sfxEntries[entries->defineId] = entries;
|
||||
}
|
||||
}
|
||||
|
||||
if (bIdx)
|
||||
{
|
||||
bIdx->m_soundMacroIndex = reinterpret_cast<const uint16_t*>(subData + group->soundMacroIdsOff);
|
||||
bIdx->m_tablesIndex = reinterpret_cast<const uint16_t*>(subData + group->tableIdsOff);
|
||||
bIdx->m_keymapsIndex = reinterpret_cast<const uint16_t*>(subData + group->keymapIdsOff);
|
||||
bIdx->m_layersIndex = reinterpret_cast<const uint16_t*>(subData + group->layerIdsOff);
|
||||
}
|
||||
|
||||
if (absOffs)
|
||||
group = reinterpret_cast<const GroupHeader*>(data + group->groupEndOff);
|
||||
else
|
||||
{
|
||||
data += group->groupEndOff;
|
||||
group = reinterpret_cast<const GroupHeader*>(data);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupData& data)
|
||||
{
|
||||
athena::io::MemoryReader r(data.getProj(), data.getProjSize());
|
||||
switch (data.getDataFormat())
|
||||
{
|
||||
case DataFormat::GCN:
|
||||
default:
|
||||
return AudioGroupProject(data.getProj(), GCNDataTag{});
|
||||
return AudioGroupProject(r, GCNDataTag{});
|
||||
case DataFormat::N64:
|
||||
return AudioGroupProject(data.getProj(), data.getAbsoluteProjOffsets(), N64DataTag{});
|
||||
return _AudioGroupProject<athena::Big>(r, data.getAbsoluteProjOffsets());
|
||||
case DataFormat::PC:
|
||||
return AudioGroupProject(data.getProj(), data.getAbsoluteProjOffsets(), PCDataTag{});
|
||||
return _AudioGroupProject<athena::Little>(r, data.getAbsoluteProjOffsets());
|
||||
}
|
||||
}
|
||||
|
||||
const SongGroupIndex* AudioGroupProject::getSongGroupIndex(int groupId) const
|
||||
{
|
||||
auto search = m_songGroups.find(groupId);
|
||||
if (search == m_songGroups.cend())
|
||||
return nullptr;
|
||||
return &search->second;
|
||||
if (search != m_songGroups.cend())
|
||||
return &search->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SFXGroupIndex* AudioGroupProject::getSFXGroupIndex(int groupId) const
|
||||
{
|
||||
auto search = m_sfxGroups.find(groupId);
|
||||
if (search == m_sfxGroups.cend())
|
||||
return nullptr;
|
||||
return &search->second;
|
||||
if (search != m_sfxGroups.cend())
|
||||
return &search->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user