multipcm: retrigger after writing to sample register if key is on (YMF278 also does this) [dink, hap]

This commit is contained in:
hap 2021-04-01 22:23:29 +02:00
parent 0d897d07e6
commit 289efafb39
4 changed files with 38 additions and 29 deletions

View File

@ -95,6 +95,21 @@ void multipcm_device::init_sample(sample_t *sample, uint32_t index)
sample->m_lfo_amplitude_reg = read_byte(address + 11) & 0xf;
}
void multipcm_device::retrigger_sample(slot_t &slot)
{
slot.m_offset = 0;
slot.m_prev_sample = 0;
slot.m_total_level = slot.m_dest_total_level << TL_SHIFT;
envelope_generator_calc(slot);
slot.m_envelope_gen.m_state = state_t::ATTACK;
slot.m_envelope_gen.m_volume = 0;
#if MULTIPCM_LOG_SAMPLES
dump_sample(slot);
#endif
}
int32_t multipcm_device::envelope_generator_update(slot_t &slot)
{
switch(slot.m_envelope_gen.m_state)
@ -334,15 +349,21 @@ void multipcm_device::write_slot(slot_t &slot, int32_t reg, uint8_t data)
case 1: // Sample
{
//according to YMF278 sample write causes some base params written to the regs (envelope+lfos)
//the game should never change the sample while playing.
sample_t sample;
init_sample(&sample, slot.m_regs[1] | ((slot.m_regs[2] & 1) << 8));
write_slot(slot, 6, sample.m_lfo_vibrato_reg);
write_slot(slot, 7, sample.m_lfo_amplitude_reg);
// according to YMF278 sample write causes some base params written to the regs (envelope+lfos)
init_sample(&slot.m_sample, slot.m_regs[1] | ((slot.m_regs[2] & 1) << 8));
write_slot(slot, 6, slot.m_sample.m_lfo_vibrato_reg);
write_slot(slot, 7, slot.m_sample.m_lfo_amplitude_reg);
slot.m_base = slot.m_sample.m_start;
slot.m_format = slot.m_sample.m_format;
// retrigger if key is on
if (slot.m_playing)
retrigger_sample(slot);
break;
}
case 2: //Pitch
case 2: // Pitch
case 3:
{
uint32_t oct = ((slot.m_regs[3] >> 4) - 1) & 0xf;
@ -359,24 +380,11 @@ void multipcm_device::write_slot(slot_t &slot, int32_t reg, uint8_t data)
slot.m_step = pitch / m_rate;
}
break;
case 4: //KeyOn/Off (and more?)
if (data & 0x80) //KeyOn
case 4: // KeyOn/Off
if (data & 0x80) // KeyOn
{
init_sample(&slot.m_sample, slot.m_regs[1] | ((slot.m_regs[2] & 1) << 8));
slot.m_playing = true;
slot.m_base = slot.m_sample.m_start;
slot.m_offset = 0;
slot.m_prev_sample = 0;
slot.m_total_level = slot.m_dest_total_level << TL_SHIFT;
slot.m_format = slot.m_sample.m_format;
envelope_generator_calc(slot);
slot.m_envelope_gen.m_state = state_t::ATTACK;
slot.m_envelope_gen.m_volume = 0;
#if MULTIPCM_LOG_SAMPLES
dump_sample(slot);
#endif
retrigger_sample(slot);
}
else
{
@ -395,7 +403,7 @@ void multipcm_device::write_slot(slot_t &slot, int32_t reg, uint8_t data)
break;
case 5: // TL + Interpolation
slot.m_dest_total_level = (data >> 1) & 0x7f;
if (!(data & 1)) //Interpolate TL
if (!(data & 1)) // Interpolate TL
{
if ((slot.m_total_level >> TL_SHIFT) > slot.m_dest_total_level)
{
@ -437,7 +445,7 @@ void multipcm_device::write(offs_t offset, uint8_t data)
{
switch(offset)
{
case 0: //Data write
case 0: // Data write
write_slot(m_slots[m_cur_slot], m_address, data);
break;
case 1:

View File

@ -123,6 +123,7 @@ private:
uint32_t value_to_fixed(const uint32_t bits, const float value);
void init_sample(sample_t *sample, uint32_t index);
void retrigger_sample(slot_t &slot);
// Internal LFO functions
void lfo_init();

View File

@ -459,7 +459,7 @@ void ymf278b_device::B_w(uint8_t reg, uint8_t data)
}
}
void ymf278b_device::retrigger_note(YMF278BSlot *slot)
void ymf278b_device::retrigger_sample(YMF278BSlot *slot)
{
// activate channel
if (slot->octave != 8)
@ -521,7 +521,7 @@ void ymf278b_device::C_w(uint8_t reg, uint8_t data)
// retrigger if key is on
if (slot->KEY_ON)
retrigger_note(slot);
retrigger_sample(slot);
else if (slot->active)
{
// deactivate channel
@ -589,7 +589,7 @@ void ymf278b_device::C_w(uint8_t reg, uint8_t data)
break;
}
retrigger_note(slot);
retrigger_sample(slot);
}
else if (slot->active)
{

View File

@ -83,7 +83,7 @@ private:
void irq_check();
void A_w(uint8_t reg, uint8_t data);
void B_w(uint8_t reg, uint8_t data);
void retrigger_note(YMF278BSlot *slot);
void retrigger_sample(YMF278BSlot *slot);
void C_w(uint8_t reg, uint8_t data);
void timer_busy_start(int is_pcm);
void precompute_rate_tables();