summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author angelosa <lordkale4@gmail.com>2026-03-06 11:57:06 +0100
committer angelosa <lordkale4@gmail.com>2026-03-06 11:57:13 +0100
commit93bb4549255f94d83ed599d5f80600371ad24a34 (patch)
tree766c36d1f9cb89db6a738ade3b23ff975094ec1d
parentf6c613d3ecaa25f95c178ec0724b5297c2882673 (diff)
sound/ac97_stac9704.cpp: basic PCM volume handling
-rw-r--r--src/devices/bus/pci/trident_4dwavedx.cpp36
-rw-r--r--src/devices/sound/ac97_stac9704.cpp34
-rw-r--r--src/devices/sound/ac97_stac9704.h6
3 files changed, 54 insertions, 22 deletions
diff --git a/src/devices/bus/pci/trident_4dwavedx.cpp b/src/devices/bus/pci/trident_4dwavedx.cpp
index ae865274582..195d3903fb9 100644
--- a/src/devices/bus/pci/trident_4dwavedx.cpp
+++ b/src/devices/bus/pci/trident_4dwavedx.cpp
@@ -2,7 +2,7 @@
// copyright-holders: Angelo Salese
/**************************************************************************************************
-Trident 4DWAVE-DX
+Trident 4DWAVE-DX / 4DWAVE-NX
AC'97 v1.x (fixed 48 kHz)
@@ -12,9 +12,10 @@ TODO:
- Add mono, 8-bit and unsigned modes;
- Missing features in Bank A (testable in dxdiag -> Music -> Trident PCI WaveTable MIDI);
- winamp has encoding issues with negative numbers (CPU core bug?);
-- Hookup wave engine output to AC'97 input;
+- Mix-in wave engine output to AC'97 input, upsample to 48 kHz there;
- wavetsr.com can't find a free IRQ for SB emulation under DOS;
- Soundblaster, FM and MPU-401 are emulated by the 4dwave sound engine;
+- Support for 4DWAVE-NX (minor upgrade with extra TLB, scatter-gather and SPDIF interface)
**************************************************************************************************/
@@ -49,12 +50,6 @@ trident_4dwavedx_device::trident_4dwavedx_device(const machine_config &mconfig,
void trident_4dwavedx_device::device_add_mconfig(machine_config &config)
{
- // Trident suggests to use an AD1819A
- // known actual configs:
- // '9700 for Hoontech ST-DIGITAL 4D_NX/SoundTrack 4D Wave (with the -NX variant)
- // '9704 for Addonics SV750/SIIG IC1607/GoodWell EPC-C4DWV840
- AC97_STAC9704(config, m_ac97, 12'288'000);
-
SPEAKER(config, "speaker", 2).front();
T4DWAVE_PCM(config, m_pcm, 0);
@@ -68,8 +63,17 @@ void trident_4dwavedx_device::device_add_mconfig(machine_config &config)
//if (state)
// irq_pin_w(0, 1);
});
- m_pcm->add_route(0, "speaker", 0.50, 0);
- m_pcm->add_route(1, "speaker", 0.50, 1);
+ m_pcm->add_route(0, m_ac97, 1.00, 0);
+ m_pcm->add_route(1, m_ac97, 1.00, 1);
+
+ // Trident suggests to use an AD1819A
+ // known actual configs:
+ // '9700 for Hoontech ST-DIGITAL 4D_NX/SoundTrack 4D Wave (with the -NX variant)
+ // '9704 for Addonics SV750/SIIG IC1607/GoodWell EPC-C4DWV840
+ AC97_STAC9704(config, m_ac97, 12'288'000);
+ m_ac97->set_pcm_tag(m_pcm);
+ m_ac97->add_route(0, "speaker", 1.0, 0);
+ m_ac97->add_route(1, "speaker", 1.0, 1);
PC_JOY(config, m_joy);
}
@@ -352,7 +356,7 @@ t4dwave_pcm_device::t4dwave_pcm_device(const machine_config &mconfig, const char
void t4dwave_pcm_device::device_start()
{
- m_stream = stream_alloc(0, 2, 48000 / 2);
+ m_stream = stream_alloc(0, 2, 44100 / 2);
save_item(NAME(m_global_control));
save_item(NAME(m_cir));
@@ -520,10 +524,7 @@ u32 t4dwave_pcm_device::cso_r(offs_t offset)
channel_t &channel = m_channel[m_cir];
if (!machine().side_effects_disabled())
- {
- //printf("%d: %08x\n", m_cir, channel.cso);
m_stream->update();
- }
return (channel.cso >> 2) << 16;
}
@@ -596,7 +597,6 @@ void t4dwave_pcm_device::gvsel_w(offs_t offset, u32 data, u32 mem_mask)
void t4dwave_pcm_device::update_irq_state()
{
- //printf("%08x & %08x\n", m_ainb, m_aintenb);
m_irq_cb(((m_aina & m_aintena) || (m_ainb & m_aintenb)) ? 1 : 0);
}
@@ -609,9 +609,7 @@ void t4dwave_pcm_device::sound_stream_update(sound_stream &stream)
if (!m_bankA_keyon && !m_bankB_keyon)
return;
- int ch;
-
- for (ch = 0; ch < 64; ch ++)
+ for (int ch = 0; ch < 64; ch ++)
{
channel_t &channel = m_channel[ch];
@@ -622,7 +620,7 @@ void t4dwave_pcm_device::sound_stream_update(sound_stream &stream)
s16 left = 0, right = 0;
- popmessage("%d: %08x -> %04x %04x delta %04x |16-bit %d sign %d stereo %d| control: %08x %d", ch, channel.lba, channel.cso, channel.eso, channel.delta, channel.is_16bit, channel.is_signed, channel.is_stereo, m_global_control, stream.samples());
+ //popmessage("%d: %08x -> %04x %04x delta %04x |16-bit %d sign %d stereo %d| control: %08x %d", ch, channel.lba, channel.cso, channel.eso, channel.delta, channel.is_16bit, channel.is_signed, channel.is_stereo, m_global_control, stream.samples());
for (int sampindex = 0; sampindex < stream.samples(); sampindex++)
{
diff --git a/src/devices/sound/ac97_stac9704.cpp b/src/devices/sound/ac97_stac9704.cpp
index 080594888b0..ba05b224c20 100644
--- a/src/devices/sound/ac97_stac9704.cpp
+++ b/src/devices/sound/ac97_stac9704.cpp
@@ -16,7 +16,9 @@ DEFINE_DEVICE_TYPE(AC97_STAC9704, ac97_stac9704_device, "ac97_stac9704", "SigmaT
ac97_stac9704_device::ac97_stac9704_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
+ , device_mixer_interface(mconfig, *this)
, device_memory_interface(mconfig, *this)
+ , m_pcm(*this, finder_base::DUMMY_TAG)
{
}
@@ -79,6 +81,8 @@ void ac97_stac9704_device::device_reset()
m_general_purpose = 0;
m_3d_control = 0;
m_power_ctrl = 0x000f;
+
+ update_gain_levels();
}
// TODO: the whole thing is asynchronous, bit 15 goes high if the codec is busy
@@ -117,7 +121,8 @@ void ac97_stac9704_device::mixer_map(address_map &map)
{
map(0x00, 0x00).lrw16(
NAME([this] (offs_t offset) {
- LOG("REG #00: Reset read ID\n");
+ if (!machine().side_effects_disabled())
+ LOG("REG #00: Reset read ID\n");
// TODO: unverified
// just bit 15 known to be low
return 0x1704;
@@ -135,6 +140,7 @@ void ac97_stac9704_device::mixer_map(address_map &map)
NAME([this] (offs_t offset, u16 data) {
LOG("REG #02: Master Volume %04x\n", data);
m_master_vol = data & 0x9f1f;
+ update_gain_levels();
})
);
map(0x04, 0x04).lrw16(
@@ -225,6 +231,7 @@ void ac97_stac9704_device::mixer_map(address_map &map)
NAME([this] (offs_t offset, u16 data) {
LOG("REG #18: PCM Out Volume %04x\n", data);
m_pcm_out_vol = data & 0x9f1f;
+ update_gain_levels();
})
);
map(0x1a, 0x1a).lrw16(
@@ -274,7 +281,28 @@ void ac97_stac9704_device::mixer_map(address_map &map)
m_power_ctrl = data & 0xff00;
})
);
- map(0x7c, 0x7c).lr16(NAME([this] () { LOG("REG #7C: Vendor ID1 read\n"); return m_vendor_id1; }));
- map(0x7e, 0x7e).lr16(NAME([this] () { LOG("REG #7E: Vendor ID2 read\n"); return m_vendor_id2; }));
+ map(0x7c, 0x7c).lr16(NAME([this] () {
+ if (!machine().side_effects_disabled()) { LOG("REG #7C: Vendor ID1 read\n"); } return m_vendor_id1; }));
+ map(0x7e, 0x7e).lr16(NAME([this] () {
+ if (!machine().side_effects_disabled()) { LOG("REG #7E: Vendor ID2 read\n"); } return m_vendor_id2; }));
}
+void ac97_stac9704_device::update_gain_levels()
+{
+ float mainL = (0x1f - ((m_master_vol & 0x1f00) >> 8)) / 31.0;
+ float mainR = (0x1f - (m_master_vol & 0x1f)) / 31.0;
+ bool global_mute = !!BIT(m_master_vol, 15);
+
+ if (global_mute || BIT(m_pcm_out_vol, 15))
+ {
+ m_pcm->set_output_gain(0, 0.0);
+ m_pcm->set_output_gain(1, 0.0);
+ }
+ else
+ {
+ float pcmL = (0x1f - ((m_pcm_out_vol & 0x1f00) >> 8)) / 31.0;
+ float pcmR = (0x1f - (m_pcm_out_vol & 0x1f)) / 31.0;
+ m_pcm->set_output_gain(0, mainL * pcmL);
+ m_pcm->set_output_gain(1, mainR * pcmR);
+ }
+}
diff --git a/src/devices/sound/ac97_stac9704.h b/src/devices/sound/ac97_stac9704.h
index 3e417c7bd81..6da4c293e76 100644
--- a/src/devices/sound/ac97_stac9704.h
+++ b/src/devices/sound/ac97_stac9704.h
@@ -6,11 +6,14 @@
#pragma once
class ac97_stac9704_device : public device_t
+ , public device_mixer_interface
, public device_memory_interface
{
public:
ac97_stac9704_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ template <typename T> void set_pcm_tag(T &&tag) { m_pcm.set_tag(std::forward<T>(tag)); }
+
void codec_write_w(offs_t offset, u32 data, u32 mem_mask = ~0);
u32 codec_write_r(offs_t offset, u32 mem_mask = ~0);
void codec_read_w(offs_t offset, u32 data, u32 mem_mask = ~0);
@@ -25,6 +28,7 @@ protected:
private:
address_space_config m_space_config;
+ required_device<device_sound_interface> m_pcm;
void mixer_map(address_map &map);
@@ -38,6 +42,8 @@ private:
u16 m_general_purpose, m_3d_control, m_power_ctrl;
u16 m_vendor_id1, m_vendor_id2;
+
+ void update_gain_levels();
};
DECLARE_DEVICE_TYPE(AC97_STAC9704, ac97_stac9704_device)