4 Commits
v1.12 ... v1.13

Author SHA1 Message Date
Jack Andersen
055e73183a Add standalone bootstrap script 2016-07-18 13:18:15 -10:00
Jack Andersen
a048605011 Support for loading revised Factor5 N64 ROMs 2016-07-18 12:38:28 -10:00
Jack Andersen
260ec5bb93 Add standalone bootstrap script 2016-07-18 07:52:17 -10:00
Jack Andersen
2a2a16fd17 Typing refinements for song events 2016-07-17 11:23:29 -10:00
9 changed files with 324 additions and 386 deletions

View File

@@ -1,7 +1,14 @@
cmake_minimum_required(VERSION 3.0)
project(amuse) project(amuse)
if(EXISTS boo) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/boo AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/athena)
message(STATUS "Preparing standalone build")
if (NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wno-narrowing")
endif()
add_subdirectory(boo) add_subdirectory(boo)
add_subdirectory(athena)
include_directories(athena/include)
endif() endif()
set(SOURCES set(SOURCES

View File

@@ -76,8 +76,8 @@ class AudioGroupProject
std::unique_ptr<SongGroupIndex::PageEntry[]> m_convNormalPages; std::unique_ptr<SongGroupIndex::PageEntry[]> m_convNormalPages;
std::unique_ptr<SongGroupIndex::PageEntry[]> m_convDrumPages; std::unique_ptr<SongGroupIndex::PageEntry[]> m_convDrumPages;
std::unique_ptr<std::array<SongGroupIndex::MIDISetup, 16>[]> m_convMidiSetups; std::unique_ptr<std::array<SongGroupIndex::MIDISetup, 16>[]> m_convMidiSetups;
void _allocateConvBuffers(const unsigned char* data, bool absOffs, N64DataTag); void _allocateConvBuffers(const unsigned char* data, N64DataTag);
void _allocateConvBuffers(const unsigned char* data, bool absOffs, PCDataTag); void _allocateConvBuffers(const unsigned char* data, PCDataTag);
public: public:
AudioGroupProject(const unsigned char* data, GCNDataTag); AudioGroupProject(const unsigned char* data, GCNDataTag);

View File

@@ -21,8 +21,7 @@ public:
MetroidPrime2, MetroidPrime2,
RogueSquadronPC, RogueSquadronPC,
RogueSquadronN64, RogueSquadronN64,
BattleForNabooPC, Factor5N64Rev,
BattleForNabooN64,
RogueSquadron2, RogueSquadron2,
RogueSquadron3 RogueSquadron3
}; };

View File

@@ -22,10 +22,10 @@ public:
private: private:
State m_phase = State::Attack; /**< Current envelope state */ State m_phase = State::Attack; /**< Current envelope state */
double m_attackTime = 0.0; /**< Time of attack in seconds */ double m_attackTime = 0.01; /**< Time of attack in seconds */
double m_decayTime = 0.0; /**< Time of decay in seconds */ double m_decayTime = 0.0; /**< Time of decay in seconds */
double m_sustainFactor = 1.0; /**< Evaluated sustain percentage */ double m_sustainFactor = 1.0; /**< Evaluated sustain percentage */
double m_releaseTime = 0.0; /**< Time of release in seconds */ double m_releaseTime = 0.01; /**< Time of release in seconds */
double m_releaseStartFactor = 0.0; /**< Level at whenever release event occurs */ double m_releaseStartFactor = 0.0; /**< Level at whenever release event occurs */
double m_curTime = 0.0; /**< Current time of envelope stage in seconds */ double m_curTime = 0.0; /**< Current time of envelope stage in seconds */
bool m_adsrSet = false; bool m_adsrSet = false;

View File

@@ -152,7 +152,7 @@ struct MusyX1MIDISetup
} }
}; };
void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool absOffs, N64DataTag) void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, N64DataTag)
{ {
size_t normPageCount = 0; size_t normPageCount = 0;
size_t drumPageCount = 0; size_t drumPageCount = 0;
@@ -161,7 +161,7 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool abs
const GroupHeader* group = reinterpret_cast<const GroupHeader*>(data); const GroupHeader* group = reinterpret_cast<const GroupHeader*>(data);
while (group->groupEndOff != 0xffffffff) while (group->groupEndOff != 0xffffffff)
{ {
const unsigned char* subData = absOffs ? data : data + 8; const unsigned char* subData = data + 8;
GroupHeader header = *group; GroupHeader header = *group;
header.swapBig(); header.swapBig();
@@ -187,21 +187,17 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool abs
/* MIDI setups */ /* MIDI setups */
const uint8_t* setupData = subData + header.midiSetupsOff; const uint8_t* setupData = subData + header.midiSetupsOff;
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff) const uint8_t* setupEnd = subData + header.groupEndOff;
while (setupData < setupEnd)
{ {
++midiSetupCount; ++midiSetupCount;
setupData += 8 * 16 + 4; setupData += 8 * 16 + 4;
} }
} }
if (absOffs)
group = reinterpret_cast<const GroupHeader*>(data + header.groupEndOff);
else
{
data += header.groupEndOff; data += header.groupEndOff;
group = reinterpret_cast<const GroupHeader*>(data); group = reinterpret_cast<const GroupHeader*>(data);
} }
}
if (normPageCount) if (normPageCount)
m_convNormalPages.reset(new SongGroupIndex::PageEntry[normPageCount]); m_convNormalPages.reset(new SongGroupIndex::PageEntry[normPageCount]);
@@ -213,7 +209,8 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool abs
AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N64DataTag) AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N64DataTag)
{ {
_allocateConvBuffers(data, absOffs, N64DataTag{}); if (!absOffs)
_allocateConvBuffers(data, N64DataTag{});
SongGroupIndex::PageEntry* normPagesBuf = m_convNormalPages.get(); SongGroupIndex::PageEntry* normPagesBuf = m_convNormalPages.get();
SongGroupIndex::PageEntry* drumPagesBuf = m_convDrumPages.get(); SongGroupIndex::PageEntry* drumPagesBuf = m_convDrumPages.get();
std::array<SongGroupIndex::MIDISetup, 16>* midiSetupsBuf = m_convMidiSetups.get(); std::array<SongGroupIndex::MIDISetup, 16>* midiSetupsBuf = m_convMidiSetups.get();
@@ -232,6 +229,39 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N6
SongGroupIndex& idx = m_songGroups[header.groupId]; SongGroupIndex& idx = m_songGroups[header.groupId];
bIdx = &idx; bIdx = &idx;
if (absOffs)
{
/* Normal pages */
const SongGroupIndex::PageEntry* normEntries =
reinterpret_cast<const SongGroupIndex::PageEntry*>(data + header.pageTableOff);
while (normEntries->objId != 0xffff)
{
idx.m_normPages[normEntries->programNo] = normEntries;
++normEntries;
}
/* Drum pages */
const SongGroupIndex::PageEntry* drumEntries =
reinterpret_cast<const SongGroupIndex::PageEntry*>(data + header.drumTableOff);
while (drumEntries->objId != 0xffff)
{
idx.m_drumPages[drumEntries->programNo] = drumEntries;
++drumEntries;
}
/* MIDI setups */
const uint8_t* setupData = data + header.midiSetupsOff;
const uint8_t* setupEnd = data + header.groupEndOff;
while (setupData < setupEnd)
{
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;
}
}
else
{
/* Normal pages */ /* Normal pages */
const MusyX1PageEntry* normEntries = const MusyX1PageEntry* normEntries =
reinterpret_cast<const MusyX1PageEntry*>(subData + header.pageTableOff); reinterpret_cast<const MusyX1PageEntry*>(subData + header.pageTableOff);
@@ -256,7 +286,8 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N6
/* MIDI setups */ /* MIDI setups */
const uint8_t* setupData = subData + header.midiSetupsOff; const uint8_t* setupData = subData + header.midiSetupsOff;
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff) const uint8_t* setupEnd = subData + header.groupEndOff;
while (setupData < setupEnd)
{ {
uint16_t songId = SBig(*reinterpret_cast<const uint16_t*>(setupData)); uint16_t songId = SBig(*reinterpret_cast<const uint16_t*>(setupData));
const std::array<MusyX1MIDISetup, 16>* midiSetups = const std::array<MusyX1MIDISetup, 16>* midiSetups =
@@ -270,6 +301,7 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N6
++midiSetupsBuf; ++midiSetupsBuf;
} }
} }
}
else if (header.type == GroupType::SFX) else if (header.type == GroupType::SFX)
{ {
SFXGroupIndex& idx = m_sfxGroups[header.groupId]; SFXGroupIndex& idx = m_sfxGroups[header.groupId];
@@ -304,7 +336,7 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N6
} }
} }
void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool absOffs, PCDataTag) void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, PCDataTag)
{ {
size_t normPageCount = 0; size_t normPageCount = 0;
size_t drumPageCount = 0; size_t drumPageCount = 0;
@@ -313,7 +345,7 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool abs
const GroupHeader* group = reinterpret_cast<const GroupHeader*>(data); const GroupHeader* group = reinterpret_cast<const GroupHeader*>(data);
while (group->groupEndOff != 0xffffffff) while (group->groupEndOff != 0xffffffff)
{ {
const unsigned char* subData = absOffs ? data : data + 8; const unsigned char* subData = data + 8;
if (group->type == GroupType::Song) if (group->type == GroupType::Song)
{ {
@@ -337,21 +369,17 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool abs
/* MIDI setups */ /* MIDI setups */
const uint8_t* setupData = subData + group->midiSetupsOff; const uint8_t* setupData = subData + group->midiSetupsOff;
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff) const uint8_t* setupEnd = subData + group->groupEndOff;
while (setupData < setupEnd)
{ {
++midiSetupCount; ++midiSetupCount;
setupData += 8 * 16 + 4; setupData += 8 * 16 + 4;
} }
} }
if (absOffs)
group = reinterpret_cast<const GroupHeader*>(data + group->groupEndOff);
else
{
data += group->groupEndOff; data += group->groupEndOff;
group = reinterpret_cast<const GroupHeader*>(data); group = reinterpret_cast<const GroupHeader*>(data);
} }
}
if (normPageCount) if (normPageCount)
m_convNormalPages.reset(new SongGroupIndex::PageEntry[normPageCount]); m_convNormalPages.reset(new SongGroupIndex::PageEntry[normPageCount]);
@@ -363,7 +391,8 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool abs
AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, PCDataTag) AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, PCDataTag)
{ {
_allocateConvBuffers(data, absOffs, PCDataTag{}); if (!absOffs)
_allocateConvBuffers(data, PCDataTag{});
SongGroupIndex::PageEntry* normPagesBuf = m_convNormalPages.get(); SongGroupIndex::PageEntry* normPagesBuf = m_convNormalPages.get();
SongGroupIndex::PageEntry* drumPagesBuf = m_convDrumPages.get(); SongGroupIndex::PageEntry* drumPagesBuf = m_convDrumPages.get();
std::array<SongGroupIndex::MIDISetup, 16>* midiSetupsBuf = m_convMidiSetups.get(); std::array<SongGroupIndex::MIDISetup, 16>* midiSetupsBuf = m_convMidiSetups.get();
@@ -380,6 +409,39 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, PC
SongGroupIndex& idx = m_songGroups[group->groupId]; SongGroupIndex& idx = m_songGroups[group->groupId];
bIdx = &idx; 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 */ /* Normal pages */
const MusyX1PageEntry* normEntries = const MusyX1PageEntry* normEntries =
reinterpret_cast<const MusyX1PageEntry*>(subData + group->pageTableOff); reinterpret_cast<const MusyX1PageEntry*>(subData + group->pageTableOff);
@@ -404,7 +466,8 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, PC
/* MIDI setups */ /* MIDI setups */
const uint8_t* setupData = subData + group->midiSetupsOff; const uint8_t* setupData = subData + group->midiSetupsOff;
while (*reinterpret_cast<const uint32_t*>(setupData) != 0xffffffff) const uint8_t* setupEnd = subData + group->groupEndOff;
while (setupData < setupEnd)
{ {
uint16_t songId = *reinterpret_cast<const uint16_t*>(setupData); uint16_t songId = *reinterpret_cast<const uint16_t*>(setupData);
const std::array<MusyX1MIDISetup, 16>* midiSetups = const std::array<MusyX1MIDISetup, 16>* midiSetups =
@@ -418,6 +481,7 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, PC
++midiSetupsBuf; ++midiSetupsBuf;
} }
} }
}
else if (group->type == GroupType::SFX) else if (group->type == GroupType::SFX)
{ {
SFXGroupIndex& idx = m_sfxGroups[group->groupId]; SFXGroupIndex& idx = m_sfxGroups[group->groupId];

View File

@@ -69,10 +69,8 @@ const SystemChar* ContainerRegistry::TypeToName(Type tp)
return _S("Star Wars - Rogue Squadron (PC)"); return _S("Star Wars - Rogue Squadron (PC)");
case Type::RogueSquadronN64: case Type::RogueSquadronN64:
return _S("Star Wars - Rogue Squadron (N64)"); return _S("Star Wars - Rogue Squadron (N64)");
case Type::BattleForNabooPC: case Type::Factor5N64Rev:
return _S("Star Wars Episode I - Battle for Naboo (PC)"); return _S("Factor5 Revision ROM (N64)");
case Type::BattleForNabooN64:
return _S("Star Wars Episode I - Battle for Naboo (N64)");
case Type::RogueSquadron2: case Type::RogueSquadron2:
return _S("Star Wars - Rogue Squadron 2 (GCN)"); return _S("Star Wars - Rogue Squadron 2 (GCN)");
case Type::RogueSquadron3: case Type::RogueSquadron3:
@@ -610,111 +608,111 @@ static void SwapN64Rom32(void* data, size_t size)
words[i] = SBig(words[i]); words[i] = SBig(words[i]);
} }
struct RS1SongMapping static const struct RS1SongMapping
{ {
const char* name; const char* name;
int songId; int songId;
} RS1Mappings[] = } RS1Mappings[] =
{ {
{"logo1_SNG", 0}, {"logo1_SNG", 0},
{"roguetitle_SNG", 1}, {"roguetitle_SNG", 1},
{"roguetheme_SNG", 1}, {"roguetheme_SNG", 1},
{"title_SNG", 2}, {"title_SNG", 2},
{"hangar1_SNG", 3}, {"hangar1_SNG", 3},
{"hangar2_SNG", 3}, {"hangar2_SNG", 3},
{"hangar3_SNG", 3}, {"hangar3_SNG", 3},
{"jingle01_SNG", 4}, {"jingle01_SNG", 4},
{"jingle02_SNG", 4}, {"jingle02_SNG", 4},
{"jingle03_SNG", 4}, {"jingle03_SNG", 4},
{"jingle04_SNG", 4}, {"jingle04_SNG", 4},
{"jingle05_SNG", 4}, {"jingle05_SNG", 4},
{"jingle06_SNG", 4}, {"jingle06_SNG", 4},
{"jingle07_SNG", 4}, {"jingle07_SNG", 4},
{"jingle08_SNG", 4}, {"jingle08_SNG", 4},
{"c1l1_theme_SNG", 4}, {"c1l1_theme_SNG", 4},
{"c1l1_prob1_SNG", 4}, {"c1l1_prob1_SNG", 4},
{"c1l1_prob2_SNG", 4}, {"c1l1_prob2_SNG", 4},
{"c1l1_spc01_SNG", 4}, {"c1l1_spc01_SNG", 4},
{"c1l1_spc02_SNG", 4}, {"c1l1_spc02_SNG", 4},
{"c1l2_theme_SNG", 5}, {"c1l2_theme_SNG", 5},
{"c1l2_spc01_SNG", 5}, {"c1l2_spc01_SNG", 5},
{"c1l3_spc01_SNG", 6}, {"c1l3_spc01_SNG", 6},
{"c1l3_theme_SNG", 6}, {"c1l3_theme_SNG", 6},
{"c1l4_spc01_SNG", 7}, {"c1l4_spc01_SNG", 7},
{"c1l4_theme_SNG", 7}, {"c1l4_theme_SNG", 7},
{"action1_SNG", 7}, {"action1_SNG", 7},
{"action1b_SNG", 7}, {"action1b_SNG", 7},
{"action2_SNG", 7}, {"action2_SNG", 7},
{"action4_SNG", 7}, {"action4_SNG", 7},
{"action5_SNG", 7}, {"action5_SNG", 7},
{"action6_SNG", 7}, {"action6_SNG", 7},
{"action7_SNG", 7}, {"action7_SNG", 7},
{"c1l5_act01_SNG", 8}, {"c1l5_act01_SNG", 8},
{"c1l5_act02_SNG", 8}, {"c1l5_act02_SNG", 8},
{"c1l5_theme_SNG", 8}, {"c1l5_theme_SNG", 8},
{"c1l5_spc01_SNG", 8}, {"c1l5_spc01_SNG", 8},
{"c2l1_theme_SNG", 9}, {"c2l1_theme_SNG", 9},
{"c2l1_spc01_SNG", 9}, {"c2l1_spc01_SNG", 9},
{"imperial_SNG", 10}, {"imperial_SNG", 10},
{"c2l2_theme_SNG", 10}, {"c2l2_theme_SNG", 10},
{"c2l2_spc01_SNG", 10}, {"c2l2_spc01_SNG", 10},
{"c3l5_theme_SNG", 10}, {"c3l5_theme_SNG", 10},
{"c2l3_theme_SNG", 11}, {"c2l3_theme_SNG", 11},
{"c2l3_spc01_SNG", 11}, {"c2l3_spc01_SNG", 11},
{"c2l5_theme_SNG", 12}, {"c2l5_theme_SNG", 12},
{"c2l5_spc01_SNG", 12}, {"c2l5_spc01_SNG", 12},
{"c5l1_start_SNG", 12}, {"c5l1_start_SNG", 12},
{"c4l1_theme_SNG", 12}, {"c4l1_theme_SNG", 12},
{"c5l1_1_SNG", 12}, {"c5l1_1_SNG", 12},
{"c5l1_2_SNG", 12}, {"c5l1_2_SNG", 12},
{"c5l1_3_SNG", 12}, {"c5l1_3_SNG", 12},
{"c3l1_theme_SNG", 13}, {"c3l1_theme_SNG", 13},
{"c5l2_theme_SNG", 13}, {"c5l2_theme_SNG", 13},
{"c5l2_spc01_SNG", 13}, {"c5l2_spc01_SNG", 13},
{"c5l3_theme_SNG", 13}, {"c5l3_theme_SNG", 13},
{"c3l2_theme_SNG", 14}, {"c3l2_theme_SNG", 14},
{"silent01_SNG", 14}, {"silent01_SNG", 14},
{"silent02_SNG", 14}, {"silent02_SNG", 14},
{"c3l5_spc01_SNG", 14}, {"c3l5_spc01_SNG", 14},
{"c3l4_theme_SNG", 14}, {"c3l4_theme_SNG", 14},
{"c3l4_spc01_SNG", 14}, {"c3l4_spc01_SNG", 14},
{"credits_SNG", 20}, {"credits_SNG", 20},
{"c1l1_cut1_SNG", 30}, {"c1l1_cut1_SNG", 30},
{"c1l2_cut1_SNG", 30}, {"c1l2_cut1_SNG", 30},
{"c1l3_cut1_SNG", 30}, {"c1l3_cut1_SNG", 30},
{"c1l4_cut1_SNG", 30}, {"c1l4_cut1_SNG", 30},
{"c1l5_cut1_SNG", 30}, {"c1l5_cut1_SNG", 30},
{"c2l1_cut1_SNG", 30}, {"c2l1_cut1_SNG", 30},
{"c2l2_cut1_SNG", 30}, {"c2l2_cut1_SNG", 30},
{"c2l3_cut1_SNG", 30}, {"c2l3_cut1_SNG", 30},
{"c2l5_cut1_SNG", 30}, {"c2l5_cut1_SNG", 30},
{"c2l6_cut1_SNG", 30}, {"c2l6_cut1_SNG", 30},
{"c3l1_cut1_SNG", 30}, {"c3l1_cut1_SNG", 30},
{"c3l2_cut1_SNG", 30}, {"c3l2_cut1_SNG", 30},
{"c3l3_cut1_SNG", 30}, {"c3l3_cut1_SNG", 30},
{"c3l4_cut1_SNG", 30}, {"c3l4_cut1_SNG", 30},
{"c3l5_cut1_SNG", 30}, {"c3l5_cut1_SNG", 30},
{"c4l1_cut1_SNG", 30}, {"c4l1_cut1_SNG", 30},
{"c5l1_cut1_SNG", 30}, {"c5l1_cut1_SNG", 30},
{"c5l2_cut1_SNG", 30}, {"c5l2_cut1_SNG", 30},
{"c5l3_cut1_SNG", 30}, {"c5l3_cut1_SNG", 30},
{"extr_cut1_SNG", 30}, {"extr_cut1_SNG", 30},
{"cut_jing1_SNG", 30}, {"cut_jing1_SNG", 30},
{"cut_jing2_SNG", 30}, {"cut_jing2_SNG", 30},
{"cut_seq1_SNG", 30}, {"cut_seq1_SNG", 30},
{"cut_seq2_SNG", 30}, {"cut_seq2_SNG", 30},
{"cut_seq3_SNG", 30}, {"cut_seq3_SNG", 30},
{"cut_seq4_SNG", 30}, {"cut_seq4_SNG", 30},
{"cut_seq5_SNG", 30}, {"cut_seq5_SNG", 30},
{"cut_seq6_SNG", 30}, {"cut_seq6_SNG", 30},
{"cut_seq7_SNG", 30}, {"cut_seq7_SNG", 30},
{"cut_seq8_SNG", 30}, {"cut_seq8_SNG", 30},
{} {}
}; };
static int LookupRS1SongId(const char* name) static int LookupRS1SongId(const char* name)
{ {
RS1SongMapping* map = RS1Mappings; const RS1SongMapping* map = RS1Mappings;
while (map->name) while (map->name)
{ {
if (!strcmp(name, map->name)) if (!strcmp(name, map->name))
@@ -1087,148 +1085,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadRS1
return ret; return ret;
} }
static bool ValidateBFNPC(FILE* fp) static bool ValidateFactor5N64Rev(FILE* fp)
{
size_t endPos = FileLength(fp);
if (endPos > 100 * 1024 * 1024)
return false;
uint32_t fstOff;
uint32_t fstSz;
if (fread(&fstOff, 1, 4, fp) == 4 && fread(&fstSz, 1, 4, fp) == 4)
{
if (fstOff + fstSz <= endPos)
{
FSeek(fp, fstOff, SEEK_SET);
uint32_t elemCount = fstSz / 32;
std::unique_ptr<RS1FSTEntry[]> entries(new RS1FSTEntry[elemCount]);
fread(entries.get(), fstSz, 1, fp);
uint8_t foundComps = 0;
for (uint32_t i = 0; i < elemCount; ++i)
{
RS1FSTEntry& entry = entries[i];
if (!strncmp("proj", entry.name, 16))
foundComps |= 1;
else if (!strncmp("pool", entry.name, 16))
foundComps |= 2;
else if (!strncmp("sdir", entry.name, 16))
foundComps |= 4;
else if (!strncmp("samp", entry.name, 16))
foundComps |= 8;
}
if (foundComps == 0xf)
return true;
}
}
return false;
}
static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadBFNPC(FILE* fp)
{
std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> ret;
size_t endPos = FileLength(fp);
uint32_t fstOff;
uint32_t fstSz;
if (fread(&fstOff, 1, 4, fp) == 4 && fread(&fstSz, 1, 4, fp) == 4)
{
if (fstOff + fstSz <= endPos)
{
FSeek(fp, fstOff, SEEK_SET);
uint32_t elemCount = fstSz / 32;
std::unique_ptr<RS1FSTEntry[]> entries(new RS1FSTEntry[elemCount]);
fread(entries.get(), fstSz, 1, fp);
std::unique_ptr<uint8_t[]> proj;
size_t projSz = 0;
std::unique_ptr<uint8_t[]> pool;
size_t poolSz = 0;
std::unique_ptr<uint8_t[]> sdir;
size_t sdirSz = 0;
std::unique_ptr<uint8_t[]> samp;
size_t sampSz = 0;
for (uint32_t i = 0; i < elemCount; ++i)
{
RS1FSTEntry& entry = entries[i];
if (!strncmp("proj", entry.name, 16))
{
proj.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(proj.get(), 1, entry.decompSz, fp);
projSz = entry.decompSz;
}
else if (!strncmp("pool", entry.name, 16))
{
pool.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(pool.get(), 1, entry.decompSz, fp);
poolSz = entry.decompSz;
}
else if (!strncmp("sdir", entry.name, 16))
{
sdir.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(sdir.get(), 1, entry.decompSz, fp);
sdirSz = entry.decompSz;
}
else if (!strncmp("samp", entry.name, 16))
{
samp.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(samp.get(), 1, entry.decompSz, fp);
sampSz = entry.decompSz;
}
}
ret.emplace_back(_S("Group"),
IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, sdir.release(),
sdirSz, samp.release(), sampSz, true, PCDataTag{}});
}
}
return ret;
}
static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadBFNPCSongs(FILE* fp)
{
std::vector<std::pair<SystemString, ContainerRegistry::SongData>> ret;
size_t endPos = FileLength(fp);
uint32_t fstOff;
uint32_t fstSz;
if (fread(&fstOff, 1, 4, fp) == 4 && fread(&fstSz, 1, 4, fp) == 4)
{
if (fstOff + fstSz <= endPos)
{
FSeek(fp, fstOff, SEEK_SET);
uint32_t elemCount = fstSz / 32;
std::unique_ptr<RS1FSTEntry[]> entries(new RS1FSTEntry[elemCount]);
fread(entries.get(), fstSz, 1, fp);
for (uint32_t i = 0; i < elemCount; ++i)
{
RS1FSTEntry& entry = entries[i];
if (!strncmp(entry.name, "s_", 2))
{
std::unique_ptr<uint8_t[]> song(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(song.get(), 1, entry.decompSz, fp);
SystemString name = StrToSys(entry.name);
ret.emplace_back(name, ContainerRegistry::SongData(std::move(song), entry.decompSz, -1, -1));
}
}
}
}
return ret;
}
static bool ValidateBFNN64(FILE* fp)
{ {
size_t endPos = FileLength(fp); size_t endPos = FileLength(fp);
if (endPos > 32 * 1024 * 1024) if (endPos > 32 * 1024 * 1024)
@@ -1282,7 +1139,7 @@ static bool ValidateBFNN64(FILE* fp)
return false; return false;
} }
static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadBFNN64(FILE* fp) static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadFactor5N64Rev(FILE* fp)
{ {
std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> ret; std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> ret;
size_t endPos = FileLength(fp); size_t endPos = FileLength(fp);
@@ -1393,7 +1250,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadBFNN64(
return ret; return ret;
} }
static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadBFNN64Songs(FILE* fp) static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadFactor5N64RevSongs(FILE* fp)
{ {
std::vector<std::pair<SystemString, ContainerRegistry::SongData>> ret; std::vector<std::pair<SystemString, ContainerRegistry::SongData>> ret;
size_t endPos = FileLength(fp); size_t endPos = FileLength(fp);
@@ -1427,6 +1284,8 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadBFN
if (!strncmp(ent.name, "s_", 2)) if (!strncmp(ent.name, "s_", 2))
{ {
long idx = strtol(ent.name + 2, nullptr, 10);
std::unique_ptr<uint8_t[]> song(new uint8_t[ent.decompSz]); std::unique_ptr<uint8_t[]> song(new uint8_t[ent.decompSz]);
if (ent.compSz == 0xffffffff) if (ent.compSz == 0xffffffff)
@@ -1440,7 +1299,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadBFN
} }
SystemString name = StrToSys(ent.name); SystemString name = StrToSys(ent.name);
ret.emplace_back(name, ContainerRegistry::SongData(std::move(song), ent.decompSz, -1, -1)); ret.emplace_back(name, ContainerRegistry::SongData(std::move(song), ent.decompSz, -1, idx));
} }
} }
} }
@@ -2011,16 +1870,10 @@ ContainerRegistry::Type ContainerRegistry::DetectContainerType(const SystemChar*
return Type::RogueSquadronN64; return Type::RogueSquadronN64;
} }
if (ValidateBFNPC(fp)) if (ValidateFactor5N64Rev(fp))
{ {
fclose(fp); fclose(fp);
return Type::BattleForNabooPC; return Type::Factor5N64Rev;
}
if (ValidateBFNN64(fp))
{
fclose(fp);
return Type::BattleForNabooN64;
} }
if (ValidateRS2(fp)) if (ValidateRS2(fp))
@@ -2195,19 +2048,11 @@ std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> ContainerRegistry:
return ret; return ret;
} }
if (ValidateBFNPC(fp)) if (ValidateFactor5N64Rev(fp))
{ {
auto ret = LoadBFNPC(fp); auto ret = LoadFactor5N64Rev(fp);
fclose(fp); fclose(fp);
typeOut = Type::BattleForNabooPC; typeOut = Type::Factor5N64Rev;
return ret;
}
if (ValidateBFNN64(fp))
{
auto ret = LoadBFNN64(fp);
fclose(fp);
typeOut = Type::BattleForNabooN64;
return ret; return ret;
} }
@@ -2282,16 +2127,9 @@ std::vector<std::pair<SystemString, ContainerRegistry::SongData>> ContainerRegis
return ret; return ret;
} }
if (ValidateBFNPC(fp)) if (ValidateFactor5N64Rev(fp))
{ {
auto ret = LoadBFNPCSongs(fp); auto ret = LoadFactor5N64RevSongs(fp);
fclose(fp);
return ret;
}
if (ValidateBFNN64(fp))
{
auto ret = LoadBFNN64Songs(fp);
fclose(fp); fclose(fp);
return ret; return ret;
} }

View File

@@ -49,32 +49,35 @@ struct PitchEvent
/* Intermediate event */ /* Intermediate event */
struct Event struct Event
{ {
enum class Type : uint8_t
{
Note,
Control,
Program,
Pitch
} m_type;
bool endEvent = false; bool endEvent = false;
bool isNote = false;
bool isControlChange = false;
bool isProgChange = false;
uint8_t channel; uint8_t channel;
uint8_t noteOrCtrl; uint8_t noteOrCtrl;
uint8_t velOrVal; uint8_t velOrVal;
uint8_t program; uint8_t program;
uint16_t length; uint16_t length;
bool isPitchBend = false;
int pitchBend; int pitchBend;
Event(NoteEvent, uint8_t chan, uint8_t note, uint8_t vel, uint16_t len) Event(NoteEvent, uint8_t chan, uint8_t note, uint8_t vel, uint16_t len)
: isNote(true), channel(chan), noteOrCtrl(note), velOrVal(vel), length(len) : m_type(Type::Note), channel(chan), noteOrCtrl(note), velOrVal(vel), length(len)
{ {
} }
Event(CtrlEvent, uint8_t chan, uint8_t note, uint8_t vel, uint16_t len) Event(CtrlEvent, uint8_t chan, uint8_t note, uint8_t vel, uint16_t len)
: isControlChange(true), channel(chan), noteOrCtrl(note), velOrVal(vel), length(len) : m_type(Type::Control), channel(chan), noteOrCtrl(note), velOrVal(vel), length(len)
{ {
} }
Event(ProgEvent, uint8_t chan, uint8_t prog) : isProgChange(true), channel(chan), program(prog) {} Event(ProgEvent, uint8_t chan, uint8_t prog) : m_type(Type::Program), channel(chan), program(prog) {}
Event(PitchEvent, uint8_t chan, int pBend) : isPitchBend(true), channel(chan), pitchBend(pBend) {} Event(PitchEvent, uint8_t chan, int pBend) : m_type(Type::Pitch), channel(chan), pitchBend(pBend) {}
}; };
class MIDIDecoder class MIDIDecoder
@@ -864,7 +867,7 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
/* Resolve key-off events */ /* Resolve key-off events */
for (auto& pair : events) for (auto& pair : events)
{ {
if (pair.second.isNote) if (pair.second.m_type == Event::Type::Note)
{ {
auto it = allEvents.emplace(pair.first + pair.second.length, pair.second); auto it = allEvents.emplace(pair.first + pair.second.length, pair.second);
it->second.endEvent = true; it->second.endEvent = true;
@@ -879,24 +882,23 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
encoder._sendContinuedValue(pair.first - lastTime); encoder._sendContinuedValue(pair.first - lastTime);
lastTime = pair.first; lastTime = pair.first;
if (pair.second.isControlChange) switch (pair.second.m_type)
{ {
case Event::Type::Control:
encoder.controlChange(pair.second.channel, pair.second.noteOrCtrl, pair.second.velOrVal); encoder.controlChange(pair.second.channel, pair.second.noteOrCtrl, pair.second.velOrVal);
} break;
else if (pair.second.isProgChange) case Event::Type::Program:
{
encoder.programChange(trk->m_midiChan, pair.second.program); encoder.programChange(trk->m_midiChan, pair.second.program);
} break;
else if (pair.second.isPitchBend) case Event::Type::Pitch:
{
encoder.pitchBend(trk->m_midiChan, pair.second.pitchBend); encoder.pitchBend(trk->m_midiChan, pair.second.pitchBend);
} break;
else if (pair.second.isNote) case Event::Type::Note:
{
if (pair.second.endEvent) if (pair.second.endEvent)
encoder.noteOff(pair.second.channel, pair.second.noteOrCtrl, pair.second.velOrVal); encoder.noteOff(pair.second.channel, pair.second.noteOrCtrl, pair.second.velOrVal);
else else
encoder.noteOn(pair.second.channel, pair.second.noteOrCtrl, pair.second.velOrVal); encoder.noteOn(pair.second.channel, pair.second.noteOrCtrl, pair.second.velOrVal);
break;
} }
} }
@@ -1080,7 +1082,9 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
lastModVal = 0; lastModVal = 0;
} }
if (event.second.isControlChange) switch (event.second.m_type)
{
case Event::Type::Control:
{ {
if (event.second.noteOrCtrl == 1) if (event.second.noteOrCtrl == 1)
{ {
@@ -1119,8 +1123,9 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
} }
} }
} }
break;
} }
else if (event.second.isProgChange) case Event::Type::Program:
{ {
if (version == 1) if (version == 1)
{ {
@@ -1148,16 +1153,18 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
region.eventBuf.push_back(0); region.eventBuf.push_back(0);
} }
} }
break;
} }
else if (event.second.isPitchBend) case Event::Type::Pitch:
{ {
EncodeRLE(region.pitchBuf, uint32_t(eventTick - lastPitchTick)); EncodeRLE(region.pitchBuf, uint32_t(eventTick - lastPitchTick));
lastPitchTick = eventTick; lastPitchTick = eventTick;
int newPitch = (event.second.pitchBend - 0x2000) * 2; int newPitch = (event.second.pitchBend - 0x2000) * 2;
EncodeContinuousRLE(region.pitchBuf, newPitch - lastPitchVal); EncodeContinuousRLE(region.pitchBuf, newPitch - lastPitchVal);
lastPitchVal = newPitch; lastPitchVal = newPitch;
break;
} }
else if (event.second.isNote) case Event::Type::Note:
{ {
if (version == 1) if (version == 1)
{ {
@@ -1194,6 +1201,8 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
region.eventBuf.push_back(event.second.velOrVal); region.eventBuf.push_back(event.second.velOrVal);
} }
} }
break;
}
} }
} }
} }

10
standalone_bootstrap.bat Normal file
View File

@@ -0,0 +1,10 @@
@echo off
git clone https://github.com/AxioDL/boo.git
pushd boo
git submodule update --recursive --init
popd
git clone https://github.com/libAthena/athena.git
pushd athena
git submodule update --recursive --init
popd

11
standalone_bootstrap.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/sh
git clone https://github.com/AxioDL/boo.git
pushd boo
git submodule update --recursive --init
popd
git clone https://github.com/libAthena/athena.git
pushd athena
git submodule update --recursive --init
popd