2024-03-05 22:11:52 -05:00
|
|
|
// Copyright: 2021 - 2024, Ziemas
|
2022-05-19 16:54:36 -04:00
|
|
|
// SPDX-License-Identifier: ISC
|
|
|
|
#include "ame_handler.h"
|
2022-06-22 23:37:46 -04:00
|
|
|
|
2022-10-01 11:58:36 -04:00
|
|
|
#include "common/log/log.h"
|
|
|
|
|
2022-06-22 23:37:46 -04:00
|
|
|
#include "game/sound/989snd/blocksound_handler.h"
|
2022-05-19 16:54:36 -04:00
|
|
|
|
|
|
|
namespace snd {
|
|
|
|
|
2022-06-04 14:53:49 -04:00
|
|
|
// added!
|
|
|
|
u64 SoundFlavaHack = 0;
|
2023-01-01 21:02:38 -05:00
|
|
|
u8 GlobalExcite = 0;
|
2022-06-04 14:53:49 -04:00
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
AmeHandler::AmeHandler(MultiMidi* block,
|
2023-12-09 18:11:24 -05:00
|
|
|
VoiceManager& vm,
|
|
|
|
MusicBank::MIDISound& sound,
|
|
|
|
s32 vol,
|
|
|
|
s32 pan,
|
|
|
|
SoundBank& bank)
|
2023-12-07 20:22:54 -05:00
|
|
|
: m_sound(sound), m_bank(bank), m_header(block), m_vm(vm), m_repeats(sound.Repeats) {
|
2022-05-19 16:54:36 -04:00
|
|
|
if (vol == VOLUME_DONT_CHANGE) {
|
|
|
|
vol = 1024;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_vol = (vol * m_sound.Vol) >> 10;
|
|
|
|
|
|
|
|
if (m_vol >= 128) {
|
|
|
|
m_vol = 127;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pan == PAN_DONT_CHANGE || pan == PAN_RESET) {
|
|
|
|
m_pan = m_sound.Pan;
|
|
|
|
} else {
|
|
|
|
m_pan = pan;
|
|
|
|
}
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
StartSegment(0);
|
2022-05-19 16:54:36 -04:00
|
|
|
};
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
bool AmeHandler::Tick() {
|
2022-05-19 16:54:36 -04:00
|
|
|
for (auto it = m_midis.begin(); it != m_midis.end();) {
|
2023-12-07 20:22:54 -05:00
|
|
|
bool done = it->second->Tick();
|
2022-05-19 16:54:36 -04:00
|
|
|
if (done) {
|
|
|
|
it = m_midis.erase(it);
|
|
|
|
} else {
|
|
|
|
it++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_midis.empty();
|
|
|
|
};
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
void AmeHandler::StartSegment(u32 id) {
|
2023-01-02 09:40:30 -05:00
|
|
|
if (m_midis.find(id) == m_midis.end()) {
|
2023-12-07 20:22:54 -05:00
|
|
|
auto& midi = m_header->midi[id];
|
2023-01-02 09:40:30 -05:00
|
|
|
|
|
|
|
// Skip adding if not midi type
|
2023-12-07 20:22:54 -05:00
|
|
|
u32 type = (midi.SoundHandle >> 24) & 0xf;
|
2023-01-02 09:40:30 -05:00
|
|
|
if (type == 1 || type == 3) {
|
2023-12-07 20:22:54 -05:00
|
|
|
m_midis.emplace(id, std::make_unique<MidiHandler>(static_cast<Midi*>(&midi), m_vm, m_sound,
|
2023-12-09 18:11:24 -05:00
|
|
|
m_vol, m_pan, m_bank, this));
|
2023-01-02 09:40:30 -05:00
|
|
|
}
|
|
|
|
}
|
2022-05-19 16:54:36 -04:00
|
|
|
}
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
void AmeHandler::Stop() {
|
2022-05-19 16:54:36 -04:00
|
|
|
for (auto it = m_midis.begin(); it != m_midis.end();) {
|
2023-12-07 20:22:54 -05:00
|
|
|
it->second->Stop();
|
2022-05-19 16:54:36 -04:00
|
|
|
it = m_midis.erase(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
void AmeHandler::StopSegment(u32 id) {
|
2022-05-19 16:54:36 -04:00
|
|
|
auto m = m_midis.find(id);
|
|
|
|
if (m == m_midis.end())
|
|
|
|
return;
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
m->second->Stop();
|
2022-05-19 16:54:36 -04:00
|
|
|
}
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
void AmeHandler::Pause() {
|
2022-05-19 16:54:36 -04:00
|
|
|
for (auto& m : m_midis) {
|
2023-12-07 20:22:54 -05:00
|
|
|
m.second->Pause();
|
2022-05-19 16:54:36 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
void AmeHandler::Unpause() {
|
2022-05-19 16:54:36 -04:00
|
|
|
for (auto& m : m_midis) {
|
2023-12-07 20:22:54 -05:00
|
|
|
m.second->Unpause();
|
2022-05-19 16:54:36 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
void AmeHandler::SetVolPan(s32 vol, s32 pan) {
|
2022-05-19 16:54:36 -04:00
|
|
|
if (vol >= 0) {
|
|
|
|
if (vol != VOLUME_DONT_CHANGE) {
|
|
|
|
m_vol = (m_sound.Vol * vol) >> 10;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m_vol = -vol;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_vol >= 128) {
|
|
|
|
m_vol = 127;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pan == PAN_RESET) {
|
|
|
|
m_pan = m_sound.Pan;
|
|
|
|
} else if (pan != PAN_DONT_CHANGE) {
|
|
|
|
m_pan = pan;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& m : m_midis) {
|
2023-12-07 20:22:54 -05:00
|
|
|
m.second->SetVolPan(vol, pan);
|
2022-05-19 16:54:36 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
void AmeHandler::SetPMod(s32 mod) {
|
2022-12-02 18:08:44 -05:00
|
|
|
for (auto& m : m_midis) {
|
2023-12-07 20:22:54 -05:00
|
|
|
m.second->SetPMod(mod);
|
2022-12-02 18:08:44 -05:00
|
|
|
}
|
2022-05-19 16:54:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#define AME_BEGIN(op) \
|
|
|
|
if (skip) { \
|
|
|
|
if (skip == 1) { \
|
|
|
|
skip = 0; \
|
|
|
|
} \
|
|
|
|
} else \
|
|
|
|
do {
|
|
|
|
#define AME_END(x) \
|
|
|
|
} \
|
|
|
|
while (0) \
|
|
|
|
; \
|
|
|
|
stream += (x);
|
|
|
|
|
2023-12-07 20:22:54 -05:00
|
|
|
std::pair<bool, u8*> AmeHandler::RunAME(MidiHandler& midi, u8* stream) {
|
2022-05-19 16:54:36 -04:00
|
|
|
int skip = 0;
|
|
|
|
bool done = false;
|
|
|
|
bool cont = true;
|
|
|
|
|
2023-01-01 21:02:38 -05:00
|
|
|
// fmt::print("AME SCRIPT ----\n");
|
|
|
|
// u8* dbgstream = stream;
|
|
|
|
// while (!done) {
|
|
|
|
// fmt::print("{:02x} ", *dbgstream);
|
|
|
|
// dbgstream++;
|
|
|
|
|
|
|
|
// if (*dbgstream == 0xf7) {
|
|
|
|
// dbgstream++;
|
|
|
|
// done = true;
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
// done = false;
|
|
|
|
// fmt::print("\n -------\n");
|
|
|
|
|
2022-05-19 16:54:36 -04:00
|
|
|
while (!done) {
|
|
|
|
auto op = static_cast<u8>(*stream++);
|
|
|
|
switch (op) {
|
|
|
|
case 0x0: {
|
|
|
|
AME_BEGIN(op)
|
2023-01-01 21:02:38 -05:00
|
|
|
if (GlobalExcite <= (stream[0] + 1)) {
|
2022-05-19 16:54:36 -04:00
|
|
|
skip = 1;
|
|
|
|
}
|
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0x1: {
|
|
|
|
AME_BEGIN(op)
|
2023-01-01 21:02:38 -05:00
|
|
|
if (GlobalExcite != (stream[0] + 1)) {
|
2022-05-19 16:54:36 -04:00
|
|
|
skip = 1;
|
|
|
|
}
|
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0x2: {
|
|
|
|
AME_BEGIN(op)
|
2023-01-01 21:02:38 -05:00
|
|
|
if (GlobalExcite > (stream[0] + 1)) {
|
2022-05-19 16:54:36 -04:00
|
|
|
skip = 1;
|
|
|
|
}
|
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0x3: {
|
|
|
|
AME_BEGIN(op)
|
2023-12-07 20:22:54 -05:00
|
|
|
StopSegment(stream[0]);
|
2022-05-19 16:54:36 -04:00
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0x4: {
|
|
|
|
// fmt::print("ame trace 4\n");
|
|
|
|
if (skip == 1) {
|
|
|
|
skip = 2;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 0x5: {
|
|
|
|
// fmt::print("ame trace 5\n");
|
|
|
|
if (skip == 2) {
|
|
|
|
skip = 0;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 0x6: {
|
|
|
|
AME_BEGIN(op)
|
|
|
|
if (m_register[stream[0]] > (stream[1] - 1)) {
|
|
|
|
skip = 1;
|
|
|
|
}
|
|
|
|
AME_END(2)
|
|
|
|
} break;
|
|
|
|
case 0x7: {
|
|
|
|
AME_BEGIN(op)
|
|
|
|
if (m_register[stream[0]] < (stream[1] + 1)) {
|
|
|
|
skip = 1;
|
|
|
|
}
|
|
|
|
AME_END(2)
|
|
|
|
} break;
|
|
|
|
case 0xB: {
|
|
|
|
// fmt::print("ame trace b\n");
|
|
|
|
m_macro[stream[0]] = &stream[1];
|
|
|
|
while (*stream != 0xf7) {
|
|
|
|
stream++;
|
|
|
|
}
|
|
|
|
stream++;
|
|
|
|
} break;
|
|
|
|
case 0xc: {
|
|
|
|
AME_BEGIN(op)
|
2023-12-07 20:22:54 -05:00
|
|
|
auto [sub_cont, ptr] = RunAME(midi, m_macro[stream[0]]);
|
2022-05-19 16:54:36 -04:00
|
|
|
if (!sub_cont) {
|
|
|
|
cont = false;
|
|
|
|
done = true;
|
|
|
|
}
|
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0xd: {
|
|
|
|
AME_BEGIN(op)
|
|
|
|
cont = false;
|
|
|
|
done = true;
|
2023-12-07 20:22:54 -05:00
|
|
|
StartSegment(m_register[stream[0]] - 1);
|
2022-05-19 16:54:36 -04:00
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0xe: {
|
|
|
|
AME_BEGIN(op)
|
2023-12-07 20:22:54 -05:00
|
|
|
StartSegment(m_register[stream[0]] - 1);
|
2022-05-19 16:54:36 -04:00
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0xf: {
|
|
|
|
// fmt::print("ame trace f\n");
|
|
|
|
if (skip) {
|
|
|
|
while (*stream != 0x7f) {
|
|
|
|
stream++;
|
|
|
|
}
|
|
|
|
stream++;
|
|
|
|
if (skip == 1)
|
|
|
|
skip = 0;
|
|
|
|
} else {
|
|
|
|
auto group = *stream++;
|
|
|
|
m_groups[group].basis = *stream++;
|
|
|
|
u8 channel = 0;
|
|
|
|
while (*stream != 0xf7) {
|
|
|
|
m_groups[group].channel[channel] = *stream++;
|
|
|
|
m_groups[group].excite_min[channel] = *stream++;
|
|
|
|
m_groups[group].excite_max[channel] = *stream++;
|
|
|
|
channel++;
|
|
|
|
}
|
|
|
|
m_groups[group].num_channels = channel;
|
|
|
|
stream++;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 0x10: {
|
|
|
|
AME_BEGIN(op)
|
|
|
|
u8 group = stream[0];
|
|
|
|
u8 comp = 0;
|
|
|
|
if (m_groups[group].basis == 0) {
|
2023-01-01 21:02:38 -05:00
|
|
|
comp = GlobalExcite;
|
2022-05-19 16:54:36 -04:00
|
|
|
} else {
|
|
|
|
comp = m_register[m_groups[group].basis - 1];
|
|
|
|
}
|
2022-06-04 14:53:49 -04:00
|
|
|
// fmt::print("group: {} basis: {} excite: {}\n", group, m_groups[group].basis, comp);
|
2022-05-19 16:54:36 -04:00
|
|
|
for (int i = 0; i < m_groups[group].num_channels; i++) {
|
2022-06-04 14:53:49 -04:00
|
|
|
// auto xmin = m_groups[group].excite_min[i];
|
|
|
|
// auto xmax = m_groups[group].excite_max[i];
|
|
|
|
// fmt::print("chan {} excite: {}-{}\n", i, xmin, xmax);
|
2023-08-16 12:53:38 -04:00
|
|
|
|
2022-06-04 14:53:49 -04:00
|
|
|
// note : added hack here! :-)
|
|
|
|
if (!SoundFlavaHack &&
|
|
|
|
(comp < m_groups[group].excite_min[i] || comp > m_groups[group].excite_max[i])) {
|
2023-12-07 20:22:54 -05:00
|
|
|
midi.MuteChannel(m_groups[group].channel[i]);
|
2022-05-19 16:54:36 -04:00
|
|
|
} else {
|
2023-12-07 20:22:54 -05:00
|
|
|
midi.UnmuteChannel(m_groups[group].channel[i]);
|
2022-05-19 16:54:36 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0x11: {
|
|
|
|
AME_BEGIN(op)
|
|
|
|
done = true;
|
|
|
|
cont = false;
|
2023-12-07 20:22:54 -05:00
|
|
|
StartSegment(stream[0]);
|
2022-05-19 16:54:36 -04:00
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0x12: {
|
|
|
|
AME_BEGIN(op)
|
2023-12-07 20:22:54 -05:00
|
|
|
StartSegment(stream[0]);
|
2022-05-19 16:54:36 -04:00
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0x13: {
|
|
|
|
AME_BEGIN(op)
|
|
|
|
m_register[stream[0]] = stream[1];
|
|
|
|
AME_END(2)
|
|
|
|
} break;
|
|
|
|
case 0x14: {
|
|
|
|
AME_BEGIN(op)
|
|
|
|
if (m_register[stream[0]] < 0x7f) {
|
|
|
|
m_register[stream[0]]++;
|
|
|
|
}
|
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0x15: {
|
|
|
|
AME_BEGIN(op)
|
|
|
|
if (m_register[stream[0]] > 0) {
|
|
|
|
m_register[stream[0]]--;
|
|
|
|
}
|
|
|
|
AME_END(1)
|
|
|
|
} break;
|
|
|
|
case 0x16: {
|
|
|
|
AME_BEGIN(op)
|
|
|
|
if (m_register[stream[0]] != stream[1]) {
|
2023-08-16 12:53:38 -04:00
|
|
|
// if (stream[0] == 3) {
|
|
|
|
// fmt::print("AME x16 reg[{}] == {}\n", stream[0], stream[1]);
|
|
|
|
// }
|
2022-05-19 16:54:36 -04:00
|
|
|
skip = 1;
|
|
|
|
}
|
|
|
|
AME_END(2)
|
|
|
|
} break;
|
|
|
|
default: {
|
2023-12-07 20:22:54 -05:00
|
|
|
throw AMEError(fmt::format("Unhandled AME event {:02x}", (u8)op));
|
2022-05-19 16:54:36 -04:00
|
|
|
} break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*stream == 0xf7) {
|
|
|
|
// fmt::print("ame done\n");
|
|
|
|
stream++;
|
|
|
|
done = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return {cont, stream};
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace snd
|
|
|
|
#undef AME_BEGIN
|
|
|
|
#undef AME_END
|