summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/wiping.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/audio/wiping.c')
-rw-r--r--src/mame/audio/wiping.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/mame/audio/wiping.c b/src/mame/audio/wiping.c
new file mode 100644
index 00000000000..6ca3348fd62
--- /dev/null
+++ b/src/mame/audio/wiping.c
@@ -0,0 +1,249 @@
+/***************************************************************************
+
+ Wiping sound driver (quick hack of the Namco sound driver)
+
+ used by wiping.c and clshroad.c
+
+***************************************************************************/
+
+#include "driver.h"
+#include "streams.h"
+#include "sound/custom.h"
+
+
+/* 8 voices max */
+#define MAX_VOICES 8
+
+
+static const int samplerate = 48000;
+static const int defgain = 48;
+
+
+/* this structure defines the parameters for a channel */
+typedef struct
+{
+ int frequency;
+ int counter;
+ int volume;
+ const UINT8 *wave;
+ int oneshot;
+ int oneshotplaying;
+} sound_channel;
+
+
+/* globals available to everyone */
+UINT8 *wiping_soundregs;
+
+/* data about the sound system */
+static sound_channel channel_list[MAX_VOICES];
+static sound_channel *last_channel;
+
+/* global sound parameters */
+static const UINT8 *sound_prom,*sound_rom;
+static int num_voices;
+static int sound_enable;
+static sound_stream *stream;
+
+/* mixer tables and internal buffers */
+static INT16 *mixer_table;
+static INT16 *mixer_lookup;
+static short *mixer_buffer;
+static short *mixer_buffer_2;
+
+
+
+/* build a table to divide by the number of voices; gain is specified as gain*16 */
+static int make_mixer_table(int voices, int gain)
+{
+ int count = voices * 128;
+ int i;
+
+ /* allocate memory */
+ mixer_table = auto_malloc(256 * voices * sizeof(INT16));
+
+ /* find the middle of the table */
+ mixer_lookup = mixer_table + (128 * voices);
+
+ /* fill in the table - 16 bit case */
+ for (i = 0; i < count; i++)
+ {
+ int val = i * gain * 16 / voices;
+ if (val > 32767) val = 32767;
+ mixer_lookup[ i] = val;
+ mixer_lookup[-i] = -val;
+ }
+
+ return 0;
+}
+
+
+/* generate sound to the mix buffer in mono */
+static void wiping_update_mono(void *param, stream_sample_t **inputs, stream_sample_t **outputs, int length)
+{
+ stream_sample_t *buffer = outputs[0];
+ sound_channel *voice;
+ short *mix;
+ int i;
+
+ /* if no sound, we're done */
+ if (sound_enable == 0)
+ {
+ memset(buffer, 0, length * sizeof(*buffer));
+ return;
+ }
+
+ /* zap the contents of the mixer buffer */
+ memset(mixer_buffer, 0, length * sizeof(short));
+
+ /* loop over each voice and add its contribution */
+ for (voice = channel_list; voice < last_channel; voice++)
+ {
+ int f = 16*voice->frequency;
+ int v = voice->volume;
+
+ /* only update if we have non-zero volume and frequency */
+ if (v && f)
+ {
+ const UINT8 *w = voice->wave;
+ int c = voice->counter;
+
+ mix = mixer_buffer;
+
+ /* add our contribution */
+ for (i = 0; i < length; i++)
+ {
+ int offs;
+
+ c += f;
+
+ if (voice->oneshot)
+ {
+ if (voice->oneshotplaying)
+ {
+ offs = (c >> 15);
+ if (w[offs>>1] == 0xff)
+ {
+ voice->oneshotplaying = 0;
+ }
+
+ if (voice->oneshotplaying)
+ {
+ /* use full byte, first the high 4 bits, then the low 4 bits */
+ if (offs & 1)
+ *mix++ += ((w[offs>>1] & 0x0f) - 8) * v;
+ else
+ *mix++ += (((w[offs>>1]>>4) & 0x0f) - 8) * v;
+ }
+ }
+ }
+ else
+ {
+ offs = (c >> 15) & 0x1f;
+
+ /* use full byte, first the high 4 bits, then the low 4 bits */
+ if (offs & 1)
+ *mix++ += ((w[offs>>1] & 0x0f) - 8) * v;
+ else
+ *mix++ += (((w[offs>>1]>>4) & 0x0f) - 8) * v;
+ }
+ }
+
+ /* update the counter for this voice */
+ voice->counter = c;
+ }
+ }
+
+ /* mix it down */
+ mix = mixer_buffer;
+ for (i = 0; i < length; i++)
+ *buffer++ = mixer_lookup[*mix++];
+}
+
+
+
+void *wiping_sh_start(int clock, const struct CustomSound_interface *config)
+{
+ sound_channel *voice;
+
+ /* get stream channels */
+ stream = stream_create(0, 1, samplerate, NULL, wiping_update_mono);
+
+ /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
+ mixer_buffer = auto_malloc(2 * sizeof(short) * samplerate);
+ mixer_buffer_2 = mixer_buffer + samplerate;
+
+ /* build the mixer table */
+ if (make_mixer_table(8, defgain))
+ return NULL;
+
+ /* extract globals from the interface */
+ num_voices = 8;
+ last_channel = channel_list + num_voices;
+
+ sound_rom = memory_region(REGION_SOUND1);
+ sound_prom = memory_region(REGION_SOUND2);
+
+ /* start with sound enabled, many games don't have a sound enable register */
+ sound_enable = 1;
+
+ /* reset all the voices */
+ for (voice = channel_list; voice < last_channel; voice++)
+ {
+ voice->frequency = 0;
+ voice->volume = 0;
+ voice->wave = &sound_prom[0];
+ voice->counter = 0;
+ }
+
+ return auto_malloc(1);
+}
+
+
+
+/********************************************************************************/
+
+WRITE8_HANDLER( wiping_sound_w )
+{
+ sound_channel *voice;
+ int base;
+
+ /* update the streams */
+ stream_update(stream);
+
+ /* set the register */
+ wiping_soundregs[offset] = data;
+
+ /* recompute all the voice parameters */
+ if (offset <= 0x3f)
+ {
+ for (base = 0, voice = channel_list; voice < last_channel; voice++, base += 8)
+ {
+ voice->frequency = wiping_soundregs[0x02 + base] & 0x0f;
+ voice->frequency = voice->frequency * 16 + ((wiping_soundregs[0x01 + base]) & 0x0f);
+ voice->frequency = voice->frequency * 16 + ((wiping_soundregs[0x00 + base]) & 0x0f);
+
+ voice->volume = wiping_soundregs[0x07 + base] & 0x0f;
+ if (wiping_soundregs[0x5 + base] & 0x0f)
+ {
+ voice->wave = &sound_rom[128 * (16 * (wiping_soundregs[0x5 + base] & 0x0f)
+ + (wiping_soundregs[0x2005 + base] & 0x0f))];
+ voice->oneshot = 1;
+ }
+ else
+ {
+ voice->wave = &sound_rom[16 * (wiping_soundregs[0x3 + base] & 0x0f)];
+ voice->oneshot = 0;
+ voice->oneshotplaying = 0;
+ }
+ }
+ }
+ else if (offset >= 0x2000)
+ {
+ voice = &channel_list[(offset & 0x3f)/8];
+ if (voice->oneshot)
+ {
+ voice->counter = 0;
+ voice->oneshotplaying = 1;
+ }
+ }
+}