summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2025-08-28 20:41:50 +0200
committer hap <happppp@users.noreply.github.com>2025-08-28 20:41:50 +0200
commit745117446e3a6c3f86329d2ec9c535935f18eac6 (patch)
tree650562a8fbe4e06bd388dd590533dce1ef145c45
parentadc8879aeffed13a6cf1a5f4faa46badde17a397 (diff)
sn76496: whitespace cleanup, ready state variable was missing from savestates
-rw-r--r--src/devices/sound/sn76496.cpp168
-rw-r--r--src/devices/sound/sn76496.h41
2 files changed, 103 insertions, 106 deletions
diff --git a/src/devices/sound/sn76496.cpp b/src/devices/sound/sn76496.cpp
index 5ddf2587d9b..016a57c563e 100644
--- a/src/devices/sound/sn76496.cpp
+++ b/src/devices/sound/sn76496.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Nicola Salmoria
/***************************************************************************
- sn76496.c
+ sn76496.cpp
by Nicola Salmoria
with contributions by others
@@ -129,22 +129,20 @@
* READY line handling by own emu_timer, not depending on sound_stream_update
- TODO: * Implement the TMS9919 - any difference to sn94624?
- * Implement the T6W28; has registers in a weird order, needs writes
- to be 'sanitized' first. Also is stereo, similar to game gear.
- * Factor out common code so that the SAA1099 can share some code.
- * verify NCR8496/PSSJ-3 behavior on write to mirrored registers; unlike the
- other variants, the NCR-derived variants are implied to ignore writes to
- regs 1,3,5,6,7 if 0x80 is not set. This needs to be verified on real hardware.
+ TODO:
+ * Implement the TMS9919 - any difference to sn94624?
+ * Implement the T6W28; has registers in a weird order, needs writes to be
+ 'sanitized' first. Also is stereo, similar to game gear.
+ * Factor out common code so that the SAA1099 can share some code.
+ * verify NCR8496/PSSJ-3 behavior on write to mirrored registers; unlike the
+ other variants, the NCR-derived variants are implied to ignore writes to
+ regs 1,3,5,6,7 if 0x80 is not set. This needs to be verified on real hardware.
***************************************************************************/
#include "emu.h"
#include "sn76496.h"
-#define MAX_OUTPUT 0x7fff
-
-
sn76496_base_device::sn76496_base_device(
const machine_config &mconfig,
device_type type,
@@ -226,34 +224,33 @@ segapsg_device::segapsg_device(const machine_config &mconfig, const char *tag, d
void sn76496_base_device::device_start()
{
- int sample_rate = clock()/2;
- int gain;
+ static constexpr int MAX_OUTPUT = 0x7fff;
+ int sample_rate = clock() / 2;
- m_sound = stream_alloc(0, (m_stereo? 2:1), sample_rate);
+ m_sound = stream_alloc(0, (m_stereo ? 2 : 1), sample_rate);
- m_last_register = m_sega_style_psg ? 3 :0; // Sega VDP PSG defaults to selected period reg for 2nd channel
- for (int i = 0; i < 8; i+=2)
+ m_last_register = m_sega_style_psg ? 3 : 0; // Sega VDP PSG defaults to selected period reg for 2nd channel
+ for (int i = 0; i < 8; i += 2)
{
m_register[i] = 0;
- m_register[i + 1] = 0x0; // volume = 0x0 (max volume) on reset; this needs testing on chips other than SN76489A and Sega VDP PSG
+ m_register[i + 1] = 0x0; // volume = 0x0 (max volume) on reset; this needs testing on chips other than SN76489A and Sega VDP PSG
}
for (int i = 0; i < 4; i++)
{
m_output[i] = 0;
- m_period[i] = m_sega_style_psg ? 0 : 0x400;
- m_count[i] = m_sega_style_psg ? 0 : 0x400;
+ m_period[i] = m_sega_style_psg ? 0 : 0x400;
+ m_count[i] = m_sega_style_psg ? 0 : 0x400;
}
m_RNG = m_feedback_mask;
m_output[3] = m_RNG & 1;
- m_stereo_mask = 0xFF; // all channels enabled
- m_current_clock = m_clock_divider-1;
+ m_stereo_mask = 0xff; // all channels enabled
+ m_current_clock = m_clock_divider - 1;
// set gain
- gain = 0;
-
+ int gain = 0;
gain &= 0xff;
// increase max output basing on gain (0.2 dB per step)
@@ -265,8 +262,10 @@ void sn76496_base_device::device_start()
for (int i = 0; i < 15; i++)
{
// limit volume to avoid clipping
- if (out > MAX_OUTPUT / 4) m_vol_table[i] = MAX_OUTPUT / 4;
- else m_vol_table[i] = out;
+ if (out > MAX_OUTPUT / 4)
+ m_vol_table[i] = MAX_OUTPUT / 4;
+ else
+ m_vol_table[i] = out;
out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */
}
@@ -280,19 +279,33 @@ void sn76496_base_device::device_start()
m_ready_timer = timer_alloc(FUNC(sn76496_base_device::delayed_ready), this);
m_ready_handler(ASSERT_LINE);
- register_for_save_states();
+ // save states
+ save_item(NAME(m_ready_state));
+ save_item(NAME(m_vol_table));
+ save_item(NAME(m_register));
+ save_item(NAME(m_last_register));
+ save_item(NAME(m_volume));
+ save_item(NAME(m_RNG));
+ save_item(NAME(m_current_clock));
+ save_item(NAME(m_stereo_mask));
+ save_item(NAME(m_period));
+ save_item(NAME(m_count));
+ save_item(NAME(m_output));
}
void sn76496_base_device::device_clock_changed()
{
- m_sound->set_sample_rate(clock()/2);
+ m_sound->set_sample_rate(clock() / 2);
}
void sn76496_base_device::stereo_w(u8 data)
{
m_sound->update();
- if (m_stereo) m_stereo_mask = data;
- else fatalerror("sn76496_base_device: Call to stereo write with mono chip!\n");
+
+ if (m_stereo)
+ m_stereo_mask = data;
+ else
+ fatalerror("sn76496_base_device: Call to stereo write with mono chip!\n");
}
TIMER_CALLBACK_MEMBER(sn76496_base_device::delayed_ready)
@@ -303,38 +316,42 @@ TIMER_CALLBACK_MEMBER(sn76496_base_device::delayed_ready)
void sn76496_base_device::write(u8 data)
{
- int n, r, c;
-
// update the output buffer before changing the registers
m_sound->update();
+ int r;
if (data & 0x80)
{
r = (data & 0x70) >> 4;
m_last_register = r;
- if (((m_ncr_style_psg) && (r == 6)) && ((data&0x04) != (m_register[6]&0x04))) m_RNG = m_feedback_mask; // NCR-style PSG resets the LFSR only on a mode write which actually changes the state of bit 2 of register 6
+ if ((m_ncr_style_psg && (r == 6)) && ((data & 0x04) != (m_register[6] & 0x04)))
+ m_RNG = m_feedback_mask; // NCR-style PSG resets the LFSR only on a mode write which actually changes the state of bit 2 of register 6
m_register[r] = (m_register[r] & 0x3f0) | (data & 0x0f);
}
else
{
r = m_last_register;
- //if ((m_ncr_style_psg) && ((r & 1) || (r == 6))) return; // NCR-style PSG ignores writes to regs 1, 3, 5, 6 and 7 with bit 7 clear; this behavior is not verified on hardware yet, uncomment it once verified.
+ //if (m_ncr_style_psg && ((r & 1) || (r == 6)))
+ // return; // NCR-style PSG ignores writes to regs 1, 3, 5, 6 and 7 with bit 7 clear; this behavior is not verified on hardware yet, uncomment it once verified.
}
- c = r >> 1;
+ int c = r >> 1;
switch (r)
{
case 0: // tone 0: frequency
case 2: // tone 1: frequency
case 4: // tone 2: frequency
- if ((data & 0x80) == 0) m_register[r] = (m_register[r] & 0x0f) | ((data & 0x3f) << 4);
- if ((m_register[r] != 0) || m_sega_style_psg) m_period[c] = m_register[r];
+ if ((data & 0x80) == 0)
+ m_register[r] = (m_register[r] & 0x0f) | ((data & 0x3f) << 4);
+ if ((m_register[r] != 0) || m_sega_style_psg)
+ m_period[c] = m_register[r];
else m_period[c] = 0x400;
if (r == 4)
{
// update noise shift frequency
- if ((m_register[6] & 0x03) == 0x03) m_period[3] = m_period[2]<<1;
+ if ((m_register[6] & 0x03) == 0x03)
+ m_period[3] = m_period[2] << 1;
}
break;
case 1: // tone 0: volume
@@ -342,34 +359,37 @@ void sn76496_base_device::write(u8 data)
case 5: // tone 2: volume
case 7: // noise: volume
m_volume[c] = m_vol_table[data & 0x0f];
- if ((data & 0x80) == 0) m_register[r] = (m_register[r] & 0x3f0) | (data & 0x0f);
+ if ((data & 0x80) == 0)
+ m_register[r] = (m_register[r] & 0x3f0) | (data & 0x0f);
break;
case 6: // noise: frequency, mode
{
- if ((data & 0x80) == 0) logerror("sn76496_base_device: write to reg 6 with bit 7 clear; data was %03x, new write is %02x!\n", m_register[6], data);
- if ((data & 0x80) == 0) m_register[r] = (m_register[r] & 0x3f0) | (data & 0x0f);
- n = m_register[6];
+ if ((data & 0x80) == 0)
+ logerror("sn76496_base_device: write to reg 6 with bit 7 clear; data was %03x, new write is %02x!\n", m_register[6], data);
+ if ((data & 0x80) == 0)
+ m_register[r] = (m_register[r] & 0x3f0) | (data & 0x0f);
+
+ int n = m_register[6];
// N/512,N/1024,N/2048,Tone #3 output
- m_period[3] = ((n&3) == 3)? (m_period[2]<<1) : (1 << (5+(n&3)));
- if (!(m_ncr_style_psg)) m_RNG = m_feedback_mask;
+ m_period[3] = ((n & 3) == 3) ? (m_period[2] << 1) : (1 << (5 + (n & 3)));
+ if (!m_ncr_style_psg)
+ m_RNG = m_feedback_mask;
}
break;
}
m_ready_state = false;
m_ready_handler(CLEAR_LINE);
- m_ready_timer->adjust(attotime::from_hz(clock()/(4*m_clock_divider)));
+ m_ready_timer->adjust(attotime::from_hz(clock() / (4 * m_clock_divider)));
}
inline bool sn76496_base_device::in_noise_mode()
{
- return ((m_register[6] & 4)!=0);
+ return ((m_register[6] & 4) != 0);
}
void sn76496_base_device::sound_stream_update(sound_stream &stream)
{
- int i;
-
int16_t out;
int16_t out2 = 0;
@@ -382,10 +402,10 @@ void sn76496_base_device::sound_stream_update(sound_stream &stream)
}
else // ready for new divided clock, make a new sample
{
- m_current_clock = m_clock_divider-1;
+ m_current_clock = m_clock_divider - 1;
// handle channels 0,1,2
- for (i = 0; i < 3; i++)
+ for (int i = 0; i < 3; i++)
{
m_count[i]--;
if (m_count[i] <= 0)
@@ -402,7 +422,7 @@ void sn76496_base_device::sound_stream_update(sound_stream &stream)
// if noisemode is 1, both taps are enabled
// if noisemode is 0, the lower tap, whitenoisetap2, is held at 0
// The != was a bit-XOR (^) before
- if (((m_RNG & m_whitenoise_tap1)!=0) != (((m_RNG & m_whitenoise_tap2)!=(m_ncr_style_psg?m_whitenoise_tap2:0)) && in_noise_mode()))
+ if (((m_RNG & m_whitenoise_tap1) != 0) != (((m_RNG & m_whitenoise_tap2) != (m_ncr_style_psg ? m_whitenoise_tap2 : 0)) && in_noise_mode()))
{
m_RNG >>= 1;
m_RNG |= m_feedback_mask;
@@ -412,29 +432,28 @@ void sn76496_base_device::sound_stream_update(sound_stream &stream)
m_RNG >>= 1;
}
m_output[3] = m_RNG & 1;
-
m_count[3] = m_period[3];
}
}
if (m_stereo)
{
- out = ((((m_stereo_mask & 0x10)!=0) && (m_output[0]!=0))? m_volume[0] : 0)
- + ((((m_stereo_mask & 0x20)!=0) && (m_output[1]!=0))? m_volume[1] : 0)
- + ((((m_stereo_mask & 0x40)!=0) && (m_output[2]!=0))? m_volume[2] : 0)
- + ((((m_stereo_mask & 0x80)!=0) && (m_output[3]!=0))? m_volume[3] : 0);
-
- out2= ((((m_stereo_mask & 0x1)!=0) && (m_output[0]!=0))? m_volume[0] : 0)
- + ((((m_stereo_mask & 0x2)!=0) && (m_output[1]!=0))? m_volume[1] : 0)
- + ((((m_stereo_mask & 0x4)!=0) && (m_output[2]!=0))? m_volume[2] : 0)
- + ((((m_stereo_mask & 0x8)!=0) && (m_output[3]!=0))? m_volume[3] : 0);
+ out = ((((m_stereo_mask & 0x10) != 0) && (m_output[0] != 0)) ? m_volume[0] : 0) +
+ ((((m_stereo_mask & 0x20) != 0) && (m_output[1] != 0)) ? m_volume[1] : 0) +
+ ((((m_stereo_mask & 0x40) != 0) && (m_output[2] != 0)) ? m_volume[2] : 0) +
+ ((((m_stereo_mask & 0x80) != 0) && (m_output[3] != 0)) ? m_volume[3] : 0);
+
+ out2 = ((((m_stereo_mask & 0x1) != 0) && (m_output[0] != 0)) ? m_volume[0] : 0) +
+ ((((m_stereo_mask & 0x2) != 0) && (m_output[1] != 0)) ? m_volume[1] : 0) +
+ ((((m_stereo_mask & 0x4) != 0) && (m_output[2] != 0)) ? m_volume[2] : 0) +
+ ((((m_stereo_mask & 0x8) != 0) && (m_output[3] != 0)) ? m_volume[3] : 0);
}
else
{
- out= ((m_output[0]!=0)? m_volume[0]:0)
- +((m_output[1]!=0)? m_volume[1]:0)
- +((m_output[2]!=0)? m_volume[2]:0)
- +((m_output[3]!=0)? m_volume[3]:0);
+ out = ((m_output[0] != 0) ? m_volume[0] : 0) +
+ ((m_output[1] != 0) ? m_volume[1] : 0) +
+ ((m_output[2] != 0) ? m_volume[2] : 0) +
+ ((m_output[3] != 0) ? m_volume[3] : 0);
}
if (m_negate) { out = -out; out2 = -out2; }
@@ -445,27 +464,6 @@ void sn76496_base_device::sound_stream_update(sound_stream &stream)
}
}
-void sn76496_base_device::register_for_save_states()
-{
- save_item(NAME(m_vol_table));
- save_item(NAME(m_register));
- save_item(NAME(m_last_register));
- save_item(NAME(m_volume));
- save_item(NAME(m_RNG));
-// save_item(NAME(m_clock_divider));
- save_item(NAME(m_current_clock));
-// save_item(NAME(m_feedback_mask));
-// save_item(NAME(m_whitenoise_tap1));
-// save_item(NAME(m_whitenoise_tap2));
-// save_item(NAME(m_negate));
-// save_item(NAME(m_stereo));
- save_item(NAME(m_stereo_mask));
- save_item(NAME(m_period));
- save_item(NAME(m_count));
- save_item(NAME(m_output));
-// save_item(NAME(m_sega_style_psg));
-}
-
DEFINE_DEVICE_TYPE(SN76496, sn76496_device, "sn76496", "SN76496")
DEFINE_DEVICE_TYPE(Y2404, y2404_device, "y2404", "Y2404")
DEFINE_DEVICE_TYPE(SN76489, sn76489_device, "sn76489", "SN76489")
diff --git a/src/devices/sound/sn76496.h b/src/devices/sound/sn76496.h
index 46471398f02..074449454a6 100644
--- a/src/devices/sound/sn76496.h
+++ b/src/devices/sound/sn76496.h
@@ -39,34 +39,33 @@ protected:
private:
inline bool in_noise_mode();
- void register_for_save_states();
- bool m_ready_state;
devcb_write_line m_ready_handler;
+ emu_timer *m_ready_timer;
+ sound_stream *m_sound;
- sound_stream* m_sound;
-
- const int32_t m_feedback_mask; // mask for feedback
- const int32_t m_whitenoise_tap1; // mask for white noise tap 1 (higher one, usually bit 14)
- const int32_t m_whitenoise_tap2; // mask for white noise tap 2 (lower one, usually bit 13)
+ // internal state
+ bool m_ready_state;
+ int32_t m_vol_table[16]; // volume table (for 4-bit to db conversion)
+ int32_t m_register[8]; // registers
+ int32_t m_last_register; // last register written
+ int32_t m_volume[4]; // db volume of voice 0-2 and noise
+ uint32_t m_RNG; // noise generator LFSR
+ int32_t m_current_clock;
+ int32_t m_stereo_mask; // the stereo output mask
+ int32_t m_period[4]; // Length of 1/2 of waveform
+ int32_t m_count[4]; // Position within the waveform
+ int32_t m_output[4]; // 1-bit output of each channel, pre-volume
+
+ // configuration
+ const int32_t m_feedback_mask; // mask for feedback
+ const int32_t m_whitenoise_tap1; // mask for white noise tap 1 (higher one, usually bit 14)
+ const int32_t m_whitenoise_tap2; // mask for white noise tap 2 (lower one, usually bit 13)
const bool m_negate; // output negate flag
const bool m_stereo; // whether we're dealing with stereo or not
- const int32_t m_clock_divider; // clock divider
+ const int32_t m_clock_divider; // clock divider
const bool m_ncr_style_psg; // flag to ignore writes to regs 1,3,5,6,7 with bit 7 low
const bool m_sega_style_psg; // flag to make frequency zero acts as if it is one more than max (0x3ff+1) or if it acts like 0; the initial register is pointing to 0x3 instead of 0x0; the volume reg is preloaded with 0xF instead of 0x0
-
- int32_t m_vol_table[16]; // volume table (for 4-bit to db conversion)
- int32_t m_register[8]; // registers
- int32_t m_last_register; // last register written
- int32_t m_volume[4]; // db volume of voice 0-2 and noise
- uint32_t m_RNG; // noise generator LFSR
- int32_t m_current_clock;
- int32_t m_stereo_mask; // the stereo output mask
- int32_t m_period[4]; // Length of 1/2 of waveform
- int32_t m_count[4]; // Position within the waveform
- int32_t m_output[4]; // 1-bit output of each channel, pre-volume
-
- emu_timer *m_ready_timer;
};
// SN76496: Whitenoise verified, phase verified, periodic verified (by Michael Zapf)