From 7f9a0514926537a2a6a4a37cffa1f373bf6b4b78 Mon Sep 17 00:00:00 2001 From: Olivier Galibert Date: Fri, 6 Oct 2023 22:46:59 +0200 Subject: mu50: correct default a/d level swp00: Add more bits to the sample values (24.8 instead of 16.0) swp00: Cleanups of the meg registers --- src/devices/sound/swp00.cpp | 131 +++++++++++++++++++++++++++----------------- src/devices/sound/swp00.h | 31 +++++++---- src/mame/yamaha/ymmu50.cpp | 8 +-- 3 files changed, 103 insertions(+), 67 deletions(-) diff --git a/src/devices/sound/swp00.cpp b/src/devices/sound/swp00.cpp index c891e754508..89a355bd6b8 100644 --- a/src/devices/sound/swp00.cpp +++ b/src/devices/sound/swp00.cpp @@ -123,16 +123,18 @@ bool swp00_device::fpstep(s32 &value, s32 limit, s32 step) return false; } -s16 swp00_device::fpapply(s32 value, s16 sample) +// sample is signed 24.8 +s32 swp00_device::fpapply(s32 value, s32 sample) { if(value >= 0x10000000) return 0; - return (sample - ((sample * ((value >> 9) & 0x7fff)) >> 16)) >> (value >> 24); + return (s64(sample) - ((s64(sample) * ((value >> 9) & 0x7fff)) >> 16)) >> (value >> 24); } -s16 swp00_device::lpffpapply(s32 value, s16 sample) +// sample is signed 24.8 +s32 swp00_device::lpffpapply(s32 value, s32 sample) { - return ((((value >> 7) & 0x7fff) | 0x8000) * sample) >> (31 - (value >> 22)); + return ((((value >> 7) & 0x7fff) | 0x8000) * s64(sample)) >> (31 - (value >> 22)); } // Some tables we need. Maybe they're in roms inside the chip, @@ -171,8 +173,10 @@ void swp00_device::device_start() save_item(NAME(m_waverom_access)); save_item(NAME(m_waverom_val)); - save_item(NAME(m_intreg)); - save_item(NAME(m_fpreg)); + save_item(NAME(m_meg_control)); + + save_item(NAME(m_off)); + save_item(NAME(m_fp)); save_item(NAME(m_lpf_info)); save_item(NAME(m_lpf_speed)); save_item(NAME(m_lfo_famod_depth)); @@ -253,9 +257,10 @@ void swp00_device::device_reset() { m_waverom_access = 0; m_waverom_val = 0; + m_meg_control = 0; - std::fill(m_intreg.begin(), m_intreg.end(), 0); - std::fill(m_fpreg.begin(), m_fpreg.end(), 0); + std::fill(m_off.begin(), m_off.end(), 0); + std::fill(m_fp.begin(), m_fp.end(), 0); std::fill(m_lpf_info.begin(), m_lpf_info.end(), 0); std::fill(m_lpf_speed.begin(), m_lpf_speed.end(), 0); std::fill(m_lfo_famod_depth.begin(), m_lfo_famod_depth.end(), 0); @@ -308,8 +313,16 @@ void swp00_device::map(address_map &map) { map(0x000, 0x7ff).rw(FUNC(swp00_device::snd_r), FUNC(swp00_device::snd_w)); + // 00-01: control + + rchan(map, 0x08).w(FUNC(swp00_device::slot8_w)); // always 80 + rchan(map, 0x09).w(FUNC(swp00_device::slot9_w)); // always 00 rchan(map, 0x0a).rw(FUNC(swp00_device::sample_start_r<1>), FUNC(swp00_device::sample_start_w<1>)); rchan(map, 0x0b).rw(FUNC(swp00_device::sample_start_r<0>), FUNC(swp00_device::sample_start_w<0>)); + + // 0c-0f: meg offsets + // 10-1b: meg values + rchan(map, 0x20).rw(FUNC(swp00_device::lpf_info_r<1>), FUNC(swp00_device::lpf_info_w<1>)); rchan(map, 0x21).rw(FUNC(swp00_device::lpf_info_r<0>), FUNC(swp00_device::lpf_info_w<0>)); rchan(map, 0x22).rw(FUNC(swp00_device::lpf_speed_r), FUNC(swp00_device::lpf_speed_w)); @@ -335,38 +348,39 @@ void swp00_device::map(address_map &map) rchan(map, 0x36).rw(FUNC(swp00_device::sample_end_r<1>), FUNC(swp00_device::sample_end_w<1>)); rchan(map, 0x37).rw(FUNC(swp00_device::sample_end_r<0>), FUNC(swp00_device::sample_end_w<0>)); - rany(map, 0x00, 0x02).rw(FUNC(swp00_device::waverom_access_r), FUNC(swp00_device::waverom_access_w)); - rany(map, 0x00, 0x03).r(FUNC(swp00_device::waverom_val_r)); - rany(map, 0x00, 0x08).w(FUNC(swp00_device::keyon_w<3>)); - rany(map, 0x00, 0x09).w(FUNC(swp00_device::keyon_w<2>)); - rany(map, 0x00, 0x0a).w(FUNC(swp00_device::keyon_w<1>)); - rany(map, 0x00, 0x0b).w(FUNC(swp00_device::keyon_w<0>)); - - map(0x001, 0x001).rw(FUNC(swp00_device::state_r), FUNC(swp00_device::state_adr_w)); + rctrl(map, 0x00); // 01 at startup + rctrl(map, 0x01).rw(FUNC(swp00_device::state_r), FUNC(swp00_device::state_adr_w)); + rctrl(map, 0x02).rw(FUNC(swp00_device::waverom_access_r), FUNC(swp00_device::waverom_access_w)); + rctrl(map, 0x03).r(FUNC(swp00_device::waverom_val_r)); + rctrl(map, 0x04).rw(FUNC(swp00_device::meg_control_r), FUNC(swp00_device::meg_control_w)); + rctrl(map, 0x08).w(FUNC(swp00_device::keyon_w<3>)); + rctrl(map, 0x09).w(FUNC(swp00_device::keyon_w<2>)); + rctrl(map, 0x0a).w(FUNC(swp00_device::keyon_w<1>)); + rctrl(map, 0x0b).w(FUNC(swp00_device::keyon_w<0>)); + rctrl(map, 0x0c); // 00 at startup + rctrl(map, 0x0d); // 00 at startup + rctrl(map, 0x0e); // 00 at startup - map(0x180, 0x1ff).rw(FUNC(swp00_device::intreg_r), FUNC(swp00_device::intreg_w)); - map(0x200, 0x3ff).rw(FUNC(swp00_device::fpreg_r), FUNC(swp00_device::fpreg_w)); + map(0x180, 0x1ff).rw(FUNC(swp00_device::off_r), FUNC(swp00_device::off_w)); + map(0x200, 0x37f).rw(FUNC(swp00_device::fp_r), FUNC(swp00_device::fp_w)); } // Voice control -#if 0 -static double exp_mant_to_double(signed int a1) +void swp00_device::slot8_w(offs_t offset, u8 data) { - signed int v1; // eax@1 - a1 >>= 6; - v1 = a1; - if ( a1 < 0 ) - v1 = 0; - return (double)((unsigned short)v1 | 0x10000u) / ((double)(1 << (24 - (v1 >> 16))) * 256.0); + if(data == 0x80) + return; + logerror("slot8[%02x] = %02x\n", offset >> 1, data); } -static double v2f(s32 value) +void swp00_device::slot9_w(offs_t offset, u8 data) { - return 1.0 - (1.0 - (value & 0xffffff) / 33554432.0) / (1 << (value >> 24)); + if(data == 0x00) + return; + logerror("slot9[%02x] = %02x\n", offset >> 1, data); } -#endif template void swp00_device::lpf_info_w(offs_t offset, u8 data) { @@ -744,46 +758,46 @@ template void swp00_device::keyon_w(u8 data) keyon(8*sel+i); } -void swp00_device::intreg_w(offs_t offset, u8 data) +void swp00_device::off_w(offs_t offset, u8 data) { m_stream->update(); if(offset & 1) - m_intreg[offset >> 1] = (m_intreg[offset >> 1] & 0xff00) | data; + m_off[offset >> 1] = (m_off[offset >> 1] & 0xff00) | data; else - m_intreg[offset >> 1] = (m_intreg[offset >> 1] & 0x00ff) | (data << 8); - if(0) + m_off[offset >> 1] = (m_off[offset >> 1] & 0x00ff) | (data << 8); + if(1) if(offset & 1) - logerror("intreg[%02x] = %04x\n", offset >> 1, m_intreg[offset >> 1]); + logerror("off[%02x] = %04x\n", 3*(offset >> 1), m_off[offset >> 1]); } -u8 swp00_device::intreg_r(offs_t offset) +u8 swp00_device::off_r(offs_t offset) { if(offset & 1) - return m_intreg[offset >> 1]; + return m_off[offset >> 1]; else - return m_intreg[offset >> 1] >> 8; + return m_off[offset >> 1] >> 8; } -void swp00_device::fpreg_w(offs_t offset, u8 data) +void swp00_device::fp_w(offs_t offset, u8 data) { m_stream->update(); if(offset & 1) - m_fpreg[offset >> 1] = (m_fpreg[offset >> 1] & 0xff00) | data; + m_fp[offset >> 1] = (m_fp[offset >> 1] & 0xff00) | data; else - m_fpreg[offset >> 1] = (m_fpreg[offset >> 1] & 0x00ff) | (data << 8); - if(0) + m_fp[offset >> 1] = (m_fp[offset >> 1] & 0x00ff) | (data << 8); + if(1) if(offset & 1) - logerror("fpreg[%03x] = %04x\n", offset >> 1, m_fpreg[offset >> 1]); + logerror("fp[%02x] = %04x\n", offset >> 1, m_fp[offset >> 1]); } -u8 swp00_device::fpreg_r(offs_t offset) +u8 swp00_device::fp_r(offs_t offset) { if(offset & 1) - return m_fpreg[offset >> 1]; + return m_fp[offset >> 1]; else - return m_fpreg[offset >> 1] >> 8; + return m_fp[offset >> 1] >> 8; } void swp00_device::waverom_access_w(u8 data) @@ -804,6 +818,17 @@ u8 swp00_device::waverom_val_r() return val; } +void swp00_device::meg_control_w(u8 data) +{ + m_meg_control = data; + logerror("meg_control %02x (variation %x, %s)\n", m_meg_control >> 6, m_meg_control & 2 ? "mute" : "on"); +} + +u8 swp00_device::meg_control_r() +{ + return m_meg_control; +} + // Counters state access u8 swp00_device::state_r() { @@ -873,8 +898,7 @@ u8 swp00_device::snd_r(offs_t offset) else #endif preg = util::string_format("%02x.%02x", chan, slot); - if(offset != 1) - logerror("snd_r [%03x] %-5s, %02x\n", offset, preg, rr[offset]); + logerror("snd_r [%03x] %-5s, %02x\n", offset, preg, rr[offset]); } return rr[offset]; } @@ -905,9 +929,6 @@ void swp00_device::snd_w(offs_t offset, u8 data) #endif preg = util::string_format("%02x.%02x", chan, slot); - if(offset == 1) - return; - logerror("snd_w [%03x] %-5s, %02x\n", offset, preg, data); } @@ -990,7 +1011,7 @@ void swp00_device::sound_stream_update(sound_stream &stream, std::vector> 15; + s32 sample = (val1 * mul + val0 * (0x8000 - mul)) >> 7; s32 lpf_value = m_lpf_value[chan] + ((lfo_fa_phase * (m_lfo_famod_depth[chan] >> 5)) << (m_lfo_step[chan] & 0x40 ? 2 : 1)); @@ -1052,6 +1073,14 @@ void swp00_device::sound_stream_update(sound_stream &stream, std::vector>= 8; + dry_r >>= 8; + rev >>= 8; + cho_l >>= 8; + cho_r >>= 8; + var_l >>= 8; + var_r >>= 8; + outputs[0].put_int(i, dry_l, 32768); outputs[1].put_int(i, dry_r, 32768); (void)rev; diff --git a/src/devices/sound/swp00.h b/src/devices/sound/swp00.h index 88f8c1cdc0c..82d91aa0534 100644 --- a/src/devices/sound/swp00.h +++ b/src/devices/sound/swp00.h @@ -41,9 +41,11 @@ private: static const std::array lfo_shape_offset_saw; static const std::array lfo_shape_offset_tri; - std::array m_intreg; - std::array m_fpreg; + // MEG registers + std::array m_off; + std::array m_fp; + // AWM registers std::array m_lpf_info; std::array m_lpf_speed; std::array m_lfo_famod_depth; @@ -83,6 +85,7 @@ private: u16 m_waverom_val; u8 m_waverom_access; u8 m_state_adr; + u8 m_meg_control; // Voice control @@ -127,15 +130,20 @@ private: void lfo_pmod_depth_w(offs_t offset, u8 data); u8 lfo_pmod_depth_r(offs_t offset); + void slot8_w(offs_t offset, u8 data); + void slot9_w(offs_t offset, u8 data); + // Internal state access u8 state_r(); void state_adr_w(u8 data); - // MEG variables - void intreg_w(offs_t offset, u8 data); - u8 intreg_r(offs_t offset); - void fpreg_w(offs_t offset, u8 data); - u8 fpreg_r(offs_t offset); + // MEG + void off_w(offs_t offset, u8 data); + u8 off_r(offs_t offset); + void fp_w(offs_t offset, u8 data); + u8 fp_r(offs_t offset); + void meg_control_w(u8 data); + u8 meg_control_r(); // Control registers void keyon(int chan); @@ -149,9 +157,8 @@ private: u8 snd_r(offs_t offset); void snd_w(offs_t offset, u8 data); - inline auto &rany(address_map &map, int chan, int idx) { - int slot = (chan << 6) | idx; - return map(slot, slot); + inline auto &rctrl(address_map &map, int idx) { + return map(idx, idx); } inline auto &rchan(address_map &map, int idx) { @@ -164,8 +171,8 @@ private: static bool fpstep(s32 &value, s32 limit, s32 step); static s32 fpadd(s32 value, s32 step); static s32 fpsub(s32 value, s32 step); - static s16 fpapply(s32 value, s16 sample); - static s16 lpffpapply(s32 value, s16 sample); + static s32 fpapply(s32 value, s32 sample); + static s32 lpffpapply(s32 value, s32 sample); }; DECLARE_DEVICE_TYPE(SWP00, swp00_device) diff --git a/src/mame/yamaha/ymmu50.cpp b/src/mame/yamaha/ymmu50.cpp index e429d708680..e6192a05c43 100644 --- a/src/mame/yamaha/ymmu50.cpp +++ b/src/mame/yamaha/ymmu50.cpp @@ -116,16 +116,16 @@ void mu50_state::mu50_map(address_map &map) map(0x400000, 0x4007ff).m(m_swp00, FUNC(swp00_device::map)); } -// Analog input right (not sent to the swp) +// Analog input right (not sent to the swp, mixing is analog) u16 mu50_state::adc_ar_r() { - return 0; + return 0x3ff; } -// Analog input left (not sent to the swp) +// Analog input left (not sent to the swp, mixing is analog) u16 mu50_state::adc_al_r() { - return 0; + return 0x3ff; } // Put the host switch to pure midi -- cgit v1.2.3