summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/ymf271.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/ymf271.cpp')
-rw-r--r--src/devices/sound/ymf271.cpp243
1 files changed, 111 insertions, 132 deletions
diff --git a/src/devices/sound/ymf271.cpp b/src/devices/sound/ymf271.cpp
index f2ef28cfeeb..3f748656d91 100644
--- a/src/devices/sound/ymf271.cpp
+++ b/src/devices/sound/ymf271.cpp
@@ -12,13 +12,13 @@
- EN and EXT Out bits
- Src B and Src NOTE bits
- statusreg Busy flag
- - timer register 0x11
- PFM (FM using external PCM waveform)
- detune (should be same as on other Yamaha chips)
- Acc On bit (some sound effects in viprp1?). The documentation says
"determines if slot output is accumulated(1), or output directly(0)"
- - Is memory handling 100% correct? At the moment, seibuspi.c is the only
+ - Is memory handling 100% correct? At the moment, seibuspi.cpp is the only
hardware currently emulated that uses external handlers.
+ - *16 multiplier for timer B is free-running like other yamaha FM chips?
*/
#include "emu.h"
@@ -253,11 +253,11 @@ inline void ymf271_device::calculate_status_end(int slotnum, bool state)
if(slotnum & 3)
return;
- /*
- bit scheme is kinda twisted
- status1 Busy End36 End24 End12 End0 ---- TimB TimA
- status2 End44 End32 End20 End8 End40 End28 End16 End4
- */
+ /*
+ bit scheme is kinda twisted
+ status1 Busy End36 End24 End12 End0 ---- TimB TimA
+ status2 End44 End32 End20 End8 End40 End28 End16 End4
+ */
uint8_t subbit = slotnum / 12;
uint8_t bankbit = ((slotnum % 12) >> 2);
@@ -566,7 +566,7 @@ void ymf271_device::set_feedback(int slotnum, int64_t inp)
// sound_stream_update - handle a stream update
//-------------------------------------------------
-void ymf271_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void ymf271_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
int i, j;
int op;
@@ -599,7 +599,7 @@ void ymf271_device::sound_stream_update(sound_stream &stream, stream_sample_t **
if (m_slots[slot1].active)
{
- for (i = 0; i < samples; i++)
+ for (i = 0; i < outputs[0].samples(); i++)
{
int64_t output1 = 0, output2 = 0, output3 = 0, output4 = 0;
int64_t phase_mod1, phase_mod2, phase_mod3;
@@ -833,7 +833,7 @@ void ymf271_device::sound_stream_update(sound_stream &stream, stream_sample_t **
mixp = &m_mix_buffer[0];
if (m_slots[slot1].active)
{
- for (i = 0; i < samples; i++)
+ for (i = 0; i < outputs[0].samples(); i++)
{
int64_t output1 = 0, output3 = 0;
int64_t phase_mod1, phase_mod3;
@@ -900,7 +900,7 @@ void ymf271_device::sound_stream_update(sound_stream &stream, stream_sample_t **
if (m_slots[slot1].active)
{
- for (i = 0; i < samples; i++)
+ for (i = 0; i < outputs[0].samples(); i++)
{
int64_t output1 = 0, output2 = 0, output3 = 0;
int64_t phase_mod1, phase_mod3;
@@ -1006,29 +1006,29 @@ void ymf271_device::sound_stream_update(sound_stream &stream, stream_sample_t **
}
mixp = &m_mix_buffer[0];
- update_pcm(j + (3*12), mixp, samples);
+ update_pcm(j + (3*12), mixp, outputs[0].samples());
break;
}
// PCM
case 3:
{
- update_pcm(j + (0*12), mixp, samples);
- update_pcm(j + (1*12), mixp, samples);
- update_pcm(j + (2*12), mixp, samples);
- update_pcm(j + (3*12), mixp, samples);
+ update_pcm(j + (0*12), mixp, outputs[0].samples());
+ update_pcm(j + (1*12), mixp, outputs[0].samples());
+ update_pcm(j + (2*12), mixp, outputs[0].samples());
+ update_pcm(j + (3*12), mixp, outputs[0].samples());
break;
}
}
}
mixp = &m_mix_buffer[0];
- for (i = 0; i < samples; i++)
+ for (i = 0; i < outputs[0].samples(); i++)
{
- outputs[0][i] = (*mixp++)>>2;
- outputs[1][i] = (*mixp++)>>2;
- outputs[2][i] = (*mixp++)>>2;
- outputs[3][i] = (*mixp++)>>2;
+ outputs[0].put_int(i, *mixp++, 32768 << 2);
+ outputs[1].put_int(i, *mixp++, 32768 << 2);
+ outputs[2].put_int(i, *mixp++, 32768 << 2);
+ outputs[3].put_int(i, *mixp++, 32768 << 2);
}
}
@@ -1309,46 +1309,34 @@ void ymf271_device::ymf271_write_pcm(uint8_t address, uint8_t data)
}
}
-void ymf271_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(ymf271_device::timer_a_expired)
{
- switch(id)
- {
- case 0:
- m_status |= 1;
-
- // assert IRQ
- if (m_enable & 4)
- {
- m_irqstate |= 1;
-
- if (!m_irq_handler.isnull())
- m_irq_handler(1);
- }
-
- // reload timer
- m_timA->adjust(clocks_to_attotime(384 * 4 * (256 - m_timerA)), 0);
- break;
+ m_status |= 1;
- case 1:
- m_status |= 2;
-
- // assert IRQ
- if (m_enable & 8)
- {
- m_irqstate |= 2;
+ // assert IRQ
+ if (m_enable & 4)
+ {
+ m_irqstate |= 1;
+ m_irq_handler(1);
+ }
- if (!m_irq_handler.isnull())
- m_irq_handler(1);
- }
+ // reload timer
+ m_timA->adjust(clocks_to_attotime(384 * (1024 - m_timerA)), 0);
+}
- // reload timer
- m_timB->adjust(clocks_to_attotime(384 * 16 * (256 - m_timerB)), 0);
- break;
+TIMER_CALLBACK_MEMBER(ymf271_device::timer_b_expired)
+{
+ m_status |= 2;
- default:
- throw emu_fatalerror("Unknown id in ymf271_device::device_timer");
- break;
+ // assert IRQ
+ if (m_enable & 8)
+ {
+ m_irqstate |= 2;
+ m_irq_handler(1);
}
+
+ // reload timer
+ m_timB->adjust(clocks_to_attotime(384 * 16 * (256 - m_timerB)), 0);
}
void ymf271_device::ymf271_write_timer(uint8_t address, uint8_t data)
@@ -1371,14 +1359,13 @@ void ymf271_device::ymf271_write_timer(uint8_t address, uint8_t data)
switch (address)
{
case 0x10:
- m_timerA = data;
+ m_timerA = (m_timerA & 0x003) | (data << 2); // High 8 bit of Timer A period
break;
case 0x11:
- // According to Yamaha's documentation, this sets timer A upper 2 bits
- // (it says timer A is 10 bits). But, PCB audio recordings proves
- // otherwise: it doesn't affect timer A frequency. (see ms32.c tetrisp)
- // Does this register have another function regarding timer A/B?
+ // Timer A is 10 bit, split high 8 bit and low 2 bit like other Yamaha FM chips
+ // unlike Yamaha's documentation; it says 0x11 writes timer A upper 2 bits.
+ m_timerA = (m_timerA & 0x3fc) | (data & 0x03); // Low 2 bit of Timer A period
break;
case 0x12:
@@ -1389,7 +1376,7 @@ void ymf271_device::ymf271_write_timer(uint8_t address, uint8_t data)
// timer A load
if (~m_enable & data & 1)
{
- attotime period = clocks_to_attotime(384 * 4 * (256 - m_timerA));
+ attotime period = clocks_to_attotime(384 * (1024 - m_timerA));
m_timA->adjust((data & 1) ? period : attotime::never, 0);
}
@@ -1406,7 +1393,7 @@ void ymf271_device::ymf271_write_timer(uint8_t address, uint8_t data)
m_irqstate &= ~1;
m_status &= ~1;
- if (!m_irq_handler.isnull() && ~m_irqstate & 2)
+ if (~m_irqstate & 2)
m_irq_handler(0);
}
@@ -1416,7 +1403,7 @@ void ymf271_device::ymf271_write_timer(uint8_t address, uint8_t data)
m_irqstate &= ~2;
m_status &= ~2;
- if (!m_irq_handler.isnull() && ~m_irqstate & 1)
+ if (~m_irqstate & 1)
m_irq_handler(0);
}
@@ -1520,8 +1507,11 @@ u8 ymf271_device::read(offs_t offset)
return 0xff;
uint8_t ret = m_ext_readlatch;
- m_ext_address = (m_ext_address + 1) & 0x7fffff;
- m_ext_readlatch = read_byte(m_ext_address);
+ if (!machine().side_effects_disabled())
+ {
+ m_ext_address = (m_ext_address + 1) & 0x7fffff;
+ m_ext_readlatch = read_byte(m_ext_address);
+ }
return ret;
}
@@ -1660,64 +1650,56 @@ void ymf271_device::calculate_clock_correction()
void ymf271_device::init_state()
{
- int i;
-
- for (i = 0; i < ARRAY_LENGTH(m_slots); i++)
- {
- save_item(NAME(m_slots[i].ext_en), i);
- save_item(NAME(m_slots[i].ext_out), i);
- save_item(NAME(m_slots[i].lfoFreq), i);
- save_item(NAME(m_slots[i].pms), i);
- save_item(NAME(m_slots[i].ams), i);
- save_item(NAME(m_slots[i].detune), i);
- save_item(NAME(m_slots[i].multiple), i);
- save_item(NAME(m_slots[i].tl), i);
- save_item(NAME(m_slots[i].keyscale), i);
- save_item(NAME(m_slots[i].ar), i);
- save_item(NAME(m_slots[i].decay1rate), i);
- save_item(NAME(m_slots[i].decay2rate), i);
- save_item(NAME(m_slots[i].decay1lvl), i);
- save_item(NAME(m_slots[i].relrate), i);
- save_item(NAME(m_slots[i].block), i);
- save_item(NAME(m_slots[i].fns_hi), i);
- save_item(NAME(m_slots[i].fns), i);
- save_item(NAME(m_slots[i].feedback), i);
- save_item(NAME(m_slots[i].waveform), i);
- save_item(NAME(m_slots[i].accon), i);
- save_item(NAME(m_slots[i].algorithm), i);
- save_item(NAME(m_slots[i].ch0_level), i);
- save_item(NAME(m_slots[i].ch1_level), i);
- save_item(NAME(m_slots[i].ch2_level), i);
- save_item(NAME(m_slots[i].ch3_level), i);
- save_item(NAME(m_slots[i].startaddr), i);
- save_item(NAME(m_slots[i].loopaddr), i);
- save_item(NAME(m_slots[i].endaddr), i);
- save_item(NAME(m_slots[i].altloop), i);
- save_item(NAME(m_slots[i].fs), i);
- save_item(NAME(m_slots[i].srcnote), i);
- save_item(NAME(m_slots[i].srcb), i);
- save_item(NAME(m_slots[i].step), i);
- save_item(NAME(m_slots[i].stepptr), i);
- save_item(NAME(m_slots[i].active), i);
- save_item(NAME(m_slots[i].bits), i);
- save_item(NAME(m_slots[i].volume), i);
- save_item(NAME(m_slots[i].env_state), i);
- save_item(NAME(m_slots[i].env_attack_step), i);
- save_item(NAME(m_slots[i].env_decay1_step), i);
- save_item(NAME(m_slots[i].env_decay2_step), i);
- save_item(NAME(m_slots[i].env_release_step), i);
- save_item(NAME(m_slots[i].feedback_modulation0), i);
- save_item(NAME(m_slots[i].feedback_modulation1), i);
- save_item(NAME(m_slots[i].lfo_phase), i);
- save_item(NAME(m_slots[i].lfo_step), i);
- save_item(NAME(m_slots[i].lfo_amplitude), i);
- }
-
- for (i = 0; i < ARRAY_LENGTH(m_groups); i++)
- {
- save_item(NAME(m_groups[i].sync), i);
- save_item(NAME(m_groups[i].pfm), i);
- }
+ save_item(STRUCT_MEMBER(m_slots, ext_en));
+ save_item(STRUCT_MEMBER(m_slots, ext_out));
+ save_item(STRUCT_MEMBER(m_slots, lfoFreq));
+ save_item(STRUCT_MEMBER(m_slots, pms));
+ save_item(STRUCT_MEMBER(m_slots, ams));
+ save_item(STRUCT_MEMBER(m_slots, detune));
+ save_item(STRUCT_MEMBER(m_slots, multiple));
+ save_item(STRUCT_MEMBER(m_slots, tl));
+ save_item(STRUCT_MEMBER(m_slots, keyscale));
+ save_item(STRUCT_MEMBER(m_slots, ar));
+ save_item(STRUCT_MEMBER(m_slots, decay1rate));
+ save_item(STRUCT_MEMBER(m_slots, decay2rate));
+ save_item(STRUCT_MEMBER(m_slots, decay1lvl));
+ save_item(STRUCT_MEMBER(m_slots, relrate));
+ save_item(STRUCT_MEMBER(m_slots, block));
+ save_item(STRUCT_MEMBER(m_slots, fns_hi));
+ save_item(STRUCT_MEMBER(m_slots, fns));
+ save_item(STRUCT_MEMBER(m_slots, feedback));
+ save_item(STRUCT_MEMBER(m_slots, waveform));
+ save_item(STRUCT_MEMBER(m_slots, accon));
+ save_item(STRUCT_MEMBER(m_slots, algorithm));
+ save_item(STRUCT_MEMBER(m_slots, ch0_level));
+ save_item(STRUCT_MEMBER(m_slots, ch1_level));
+ save_item(STRUCT_MEMBER(m_slots, ch2_level));
+ save_item(STRUCT_MEMBER(m_slots, ch3_level));
+ save_item(STRUCT_MEMBER(m_slots, startaddr));
+ save_item(STRUCT_MEMBER(m_slots, loopaddr));
+ save_item(STRUCT_MEMBER(m_slots, endaddr));
+ save_item(STRUCT_MEMBER(m_slots, altloop));
+ save_item(STRUCT_MEMBER(m_slots, fs));
+ save_item(STRUCT_MEMBER(m_slots, srcnote));
+ save_item(STRUCT_MEMBER(m_slots, srcb));
+ save_item(STRUCT_MEMBER(m_slots, step));
+ save_item(STRUCT_MEMBER(m_slots, stepptr));
+ save_item(STRUCT_MEMBER(m_slots, active));
+ save_item(STRUCT_MEMBER(m_slots, bits));
+ save_item(STRUCT_MEMBER(m_slots, volume));
+ save_item(STRUCT_MEMBER(m_slots, env_state));
+ save_item(STRUCT_MEMBER(m_slots, env_attack_step));
+ save_item(STRUCT_MEMBER(m_slots, env_decay1_step));
+ save_item(STRUCT_MEMBER(m_slots, env_decay2_step));
+ save_item(STRUCT_MEMBER(m_slots, env_release_step));
+ save_item(STRUCT_MEMBER(m_slots, feedback_modulation0));
+ save_item(STRUCT_MEMBER(m_slots, feedback_modulation1));
+ save_item(STRUCT_MEMBER(m_slots, lfo_phase));
+ save_item(STRUCT_MEMBER(m_slots, lfo_step));
+ save_item(STRUCT_MEMBER(m_slots, lfo_amplitude));
+
+ save_item(STRUCT_MEMBER(m_groups, sync));
+ save_item(STRUCT_MEMBER(m_groups, pfm));
save_item(NAME(m_regs_main));
save_item(NAME(m_timerA));
@@ -1738,17 +1720,15 @@ void ymf271_device::init_state()
void ymf271_device::device_start()
{
- m_timA = timer_alloc(0);
- m_timB = timer_alloc(1);
-
- m_irq_handler.resolve();
+ m_timA = timer_alloc(FUNC(ymf271_device::timer_a_expired), this);
+ m_timB = timer_alloc(FUNC(ymf271_device::timer_b_expired), this);
m_master_clock = clock();
init_tables();
init_state();
m_mix_buffer.resize(m_master_clock/(384/4));
- m_stream = machine().sound().stream_alloc(*this, 0, 4, m_master_clock/384);
+ m_stream = stream_alloc(0, 4, m_master_clock/384);
}
//-------------------------------------------------
@@ -1771,8 +1751,7 @@ void ymf271_device::device_reset()
m_status = 0;
m_enable = 0;
- if (!m_irq_handler.isnull())
- m_irq_handler(0);
+ m_irq_handler(0);
}
//-------------------------------------------------
@@ -1795,7 +1774,7 @@ void ymf271_device::device_clock_changed()
calculate_clock_correction();
}
-void ymf271_device::rom_bank_updated()
+void ymf271_device::rom_bank_pre_change()
{
m_stream->update();
}
@@ -1805,7 +1784,7 @@ DEFINE_DEVICE_TYPE(YMF271, ymf271_device, "ymf271", "Yamaha YMF271 OPX")
ymf271_device::ymf271_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, YMF271, tag, owner, clock)
, device_sound_interface(mconfig, *this)
- , device_rom_interface(mconfig, *this, 23)
+ , device_rom_interface(mconfig, *this)
, m_timerA(0)
, m_timerB(0)
, m_irqstate(0)