mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
ymz774: add sequencer, blind work based on KOF98UM rom data, not tested at all (nw)
This commit is contained in:
parent
475cf95575
commit
f24f509165
@ -102,9 +102,11 @@ void ymz770_device::device_start()
|
||||
}
|
||||
for (int ch = 0; ch < 8; ch++)
|
||||
{
|
||||
save_item(NAME(m_sequences[ch].sequence), ch);
|
||||
save_item(NAME(m_sequences[ch].control), ch);
|
||||
save_item(NAME(m_sequences[ch].delay), ch);
|
||||
save_item(NAME(m_sequences[ch].sequence), ch);
|
||||
save_item(NAME(m_sequences[ch].timer), ch);
|
||||
save_item(NAME(m_sequences[ch].stopchan), ch);
|
||||
save_item(NAME(m_sequences[ch].loop), ch);
|
||||
save_item(NAME(m_sequences[ch].is_playing), ch);
|
||||
}
|
||||
}
|
||||
@ -133,9 +135,11 @@ void ymz770_device::device_reset()
|
||||
}
|
||||
for (auto & sequence : m_sequences)
|
||||
{
|
||||
sequence.sequence = 0;
|
||||
sequence.control = 0;
|
||||
sequence.delay = 0;
|
||||
sequence.sequence = 0;
|
||||
sequence.timer = 0;
|
||||
sequence.stopchan = 0;
|
||||
sequence.loop = 0;
|
||||
sequence.is_playing = false;
|
||||
}
|
||||
}
|
||||
@ -268,7 +272,7 @@ void ymz770_device::sequencer()
|
||||
switch (reg)
|
||||
{
|
||||
case 0x0f:
|
||||
if (sequence.control & 1)
|
||||
if (sequence.loop)
|
||||
{
|
||||
// loop sequence
|
||||
uint8_t sqn = sequence.sequence;
|
||||
@ -401,7 +405,7 @@ void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data)
|
||||
m_sequences[ch].is_playing = false;
|
||||
}
|
||||
|
||||
m_sequences[ch].control = data;
|
||||
m_sequences[ch].loop = data & 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -503,9 +507,65 @@ void ymz774_device::internal_reg_write(uint8_t reg, uint8_t data)
|
||||
}
|
||||
else if (reg < 0xd0)
|
||||
{
|
||||
if (m_bank == 0) // Sequencer, in PGM2 games not used at all
|
||||
if (m_bank == 0)
|
||||
{
|
||||
if (data) logerror("sequencer unimplemented %02X %02X\n", reg, data);
|
||||
if (reg < 0xb0)
|
||||
{
|
||||
int sq = reg & 7;
|
||||
switch (reg & 0xf8)
|
||||
{
|
||||
case 0x60: // sequence num H and L
|
||||
case 0x68:
|
||||
sq = (reg >> 1) & 7;
|
||||
if (sq & 1)
|
||||
m_sequences[sq].sequence = (m_sequences[sq].sequence & 0xff00) | data;
|
||||
else
|
||||
m_sequences[sq].sequence = (m_sequences[sq].sequence & 0x00ff) | ((data & 0x0f) << 8); // TODO check if total number really upto 0x1000
|
||||
break;
|
||||
case 0x70: // Start / Stop
|
||||
if (data)
|
||||
{
|
||||
uint32_t pptr = get_seq_offs(m_sequences[sq].sequence);
|
||||
m_sequences[sq].data = &m_rom[pptr];
|
||||
m_sequences[sq].delay = 0;
|
||||
m_sequences[sq].is_playing = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sequences[sq].is_playing = false;
|
||||
}
|
||||
break;
|
||||
case 0x78: // Pause / Resume
|
||||
if (data) logerror("SEQ pause/resume unimplemented %02X %02X\n", reg, data);
|
||||
break;
|
||||
case 0x80: // Loop count, 0 = off, 255 - infinite
|
||||
m_sequences[sq].loop = data;
|
||||
break;
|
||||
case 0x88: // timer H and L
|
||||
case 0x90:
|
||||
sq = (reg >> 1) & 7;
|
||||
if (sq & 1)
|
||||
m_sequences[sq].timer = (m_sequences[sq].timer & 0xff00) | data;
|
||||
else
|
||||
m_sequences[sq].timer = (m_sequences[sq].timer & 0x00ff) | (data << 8);
|
||||
break;
|
||||
case 0x98: // Off trigger, bit4 = on/off, bits0-3 channel (end sequence when channel playback ends)
|
||||
if (data) logerror("SEQ Off trigger unimplemented %02X %02X\n", reg, data);
|
||||
break;
|
||||
case 0xa0: // stop channel mask H and L, what it for ? stop chanels immediatelly or when sequence ends (so far assuming later) ?
|
||||
case 0xa8:
|
||||
sq = (reg >> 1) & 7;
|
||||
if (sq & 1)
|
||||
m_sequences[sq].stopchan = (m_sequences[sq].stopchan & 0xff00) | data;
|
||||
else
|
||||
m_sequences[sq].stopchan = (m_sequences[sq].stopchan & 0x00ff) | (data << 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data) logerror("SQC unimplemented %02X %02X\n", reg, data);
|
||||
}
|
||||
}
|
||||
// else bank1 - Equalizer control
|
||||
}
|
||||
@ -529,3 +589,56 @@ void ymz774_device::internal_reg_write(uint8_t reg, uint8_t data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ymz774_device::sequencer()
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
auto & sequence = m_sequences[i];
|
||||
if (sequence.is_playing)
|
||||
{
|
||||
if (sequence.delay > 0)
|
||||
{
|
||||
--sequence.delay;
|
||||
}
|
||||
else
|
||||
{
|
||||
int reg = *sequence.data++;
|
||||
uint8_t data = *sequence.data++;
|
||||
switch (reg)
|
||||
{
|
||||
case 0xff: // end
|
||||
for (int ch = 0; ch < 16; ch++) // check this
|
||||
if (sequence.stopchan & (1 << ch))
|
||||
m_channels[ch].is_playing = false;
|
||||
if (sequence.loop)
|
||||
{
|
||||
if (sequence.loop != 255)
|
||||
--sequence.loop;
|
||||
uint32_t pptr = get_seq_offs(sequence.sequence);
|
||||
sequence.data = &m_rom[pptr];
|
||||
}
|
||||
else
|
||||
{
|
||||
sequence.is_playing = false;
|
||||
}
|
||||
break;
|
||||
case 0xfe: // timer delay
|
||||
sequence.delay = sequence.timer * 32; // possible needed -1 or +(32-1)
|
||||
break;
|
||||
default:
|
||||
if (m_bank == 0 && reg >= 0x60 && reg < 0xb0) // if we hit SEQ registers need to add this sequence offset
|
||||
{
|
||||
int sqn = i;
|
||||
if (reg < 0x70 || (reg >= 0x88 && reg < 0x98) || reg >= 0xa0)
|
||||
sqn = i * 2;
|
||||
internal_reg_write(reg + sqn, data);
|
||||
}
|
||||
else
|
||||
internal_reg_write(reg, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,9 +95,11 @@ protected:
|
||||
};
|
||||
struct ymz_sequence
|
||||
{
|
||||
uint32_t delay;
|
||||
uint16_t sequence;
|
||||
uint8_t control;
|
||||
uint8_t delay;
|
||||
uint16_t timer;
|
||||
uint16_t stopchan;
|
||||
uint8_t loop;
|
||||
uint8_t *data;
|
||||
bool is_playing;
|
||||
};
|
||||
@ -119,7 +121,7 @@ protected:
|
||||
virtual void internal_reg_write(uint8_t reg, uint8_t data) override;
|
||||
virtual uint32_t get_phrase_offs(int phrase) override { int ph = phrase * 4; return ((m_rom[ph] & 0x0f) << 24 | m_rom[ph + 1] << 16 | m_rom[ph + 2] << 8 | m_rom[ph + 3]) * 2; };
|
||||
virtual uint32_t get_seq_offs(int sqn) override { int sq = sqn * 4 + 0x2000; return ((m_rom[sq] & 0x0f) << 24 | m_rom[sq + 1] << 16 | m_rom[sq + 2] << 8 | m_rom[sq + 3]) * 2; };
|
||||
virtual void sequencer() override {};
|
||||
virtual void sequencer() override;
|
||||
private:
|
||||
int m_bank;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user