summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/flower.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/audio/flower.c')
-rw-r--r--src/mame/audio/flower.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/src/mame/audio/flower.c b/src/mame/audio/flower.c
new file mode 100644
index 00000000000..7d5c03c20c2
--- /dev/null
+++ b/src/mame/audio/flower.c
@@ -0,0 +1,285 @@
+/***************************************************************************
+
+ Flower sound driver (quick hack of the Wiping sound driver)
+
+***************************************************************************/
+
+#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 *flower_soundregs1,*flower_soundregs2;
+
+/* data about the sound system */
+static sound_channel channel_list[MAX_VOICES];
+static sound_channel *last_channel;
+
+/* global sound parameters */
+static const UINT8 *sound_rom1,*sound_rom2;
+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 flower_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 = 256*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] == 0xff)
+ {
+ voice->oneshotplaying = 0;
+ }
+
+ if (voice->oneshotplaying)
+ {
+// *mix++ += ((w[offs] - 0x80) * v) / 16;
+*mix++ += sound_rom2[v*256 + w[offs]] - 0x80;
+ }
+ }
+ }
+ else
+ {
+ offs = (c >> 15) & 0x1ff;
+
+// *mix++ += ((w[offs] - 0x80) * v) / 16;
+*mix++ += sound_rom2[v*256 + w[offs]] - 0x80;
+ }
+ }
+
+ /* 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 * flower_sh_start(int clock, const struct CustomSound_interface *config)
+{
+ sound_channel *voice;
+
+ /* get stream channels */
+ stream = stream_create(0, 1, samplerate, 0, flower_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_rom1 = memory_region(REGION_SOUND1);
+ sound_rom2 = 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_rom1[0];
+ voice->counter = 0;
+ }
+
+ return auto_malloc(1);
+}
+
+
+/********************************************************************************/
+
+WRITE8_HANDLER( flower_sound1_w )
+{
+ sound_channel *voice;
+ int base;
+
+ /* update the streams */
+ stream_update(stream);
+
+ /* set the register */
+ flower_soundregs1[offset] = data;
+
+ /* recompute all the voice parameters */
+ for (base = 0, voice = channel_list; voice < last_channel; voice++, base += 8)
+ {
+ voice->frequency = flower_soundregs1[2 + base] & 0x0f;
+ voice->frequency = voice->frequency * 16 + ((flower_soundregs1[3 + base]) & 0x0f);
+ voice->frequency = voice->frequency * 16 + ((flower_soundregs1[0 + base]) & 0x0f);
+ voice->frequency = voice->frequency * 16 + ((flower_soundregs1[1 + base]) & 0x0f);
+
+ voice->volume = (flower_soundregs1[7 + base] >> 4) | ((flower_soundregs2[7 + base] & 0x03) << 4);
+// the following would fix the hanging notes...
+//if ((flower_soundregs2[7 + base] & 0x01) == 0)
+// voice->volume = 0;
+
+ if (flower_soundregs1[4 + base] & 0x10)
+ {
+ voice->oneshot = 0;
+ voice->oneshotplaying = 0;
+ }
+ else
+ {
+ voice->oneshot = 1;
+ }
+ }
+}
+
+WRITE8_HANDLER( flower_sound2_w )
+{
+ sound_channel *voice;
+ int base = offset & 0xf8;
+
+/*
+popmessage("%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x",
+ flower_soundregs2[7 + 8*0],flower_soundregs1[7 + 8*0],
+ flower_soundregs2[7 + 8*1],flower_soundregs1[7 + 8*1],
+ flower_soundregs2[7 + 8*2],flower_soundregs1[7 + 8*2],
+ flower_soundregs2[7 + 8*3],flower_soundregs1[7 + 8*3],
+ flower_soundregs2[7 + 8*4],flower_soundregs1[7 + 8*4],
+ flower_soundregs2[7 + 8*5],flower_soundregs1[7 + 8*5],
+ flower_soundregs2[7 + 8*6],flower_soundregs1[7 + 8*6],
+ flower_soundregs2[7 + 8*7],flower_soundregs1[7 + 8*7]
+ );
+*/
+
+ /* update the streams */
+ stream_update(stream);
+
+ /* set the register */
+ flower_soundregs2[offset] = data;
+
+ /* recompute all the voice parameters */
+ voice = &channel_list[offset/8];
+ if (voice->oneshot)
+ {
+ int start;
+
+ start = flower_soundregs2[5 + base] & 0x0f;
+ start = start * 16 + ((flower_soundregs2[4 + base]) & 0x0f);
+ start = start * 16 + ((flower_soundregs2[3 + base]) & 0x0f);
+ start = start * 16 + ((flower_soundregs2[2 + base]) & 0x0f);
+ start = start * 16 + ((flower_soundregs2[1 + base]) & 0x0f);
+ start = start * 16 + ((flower_soundregs2[0 + base]) & 0x0f);
+
+ voice->wave = &sound_rom1[(start >> 7) & 0x7fff];
+
+ voice->counter = 0;
+ voice->oneshotplaying = 1;
+ }
+ else
+ {
+ int start;
+
+ start = flower_soundregs2[5 + base] & 0x0f;
+ start = start * 16 + ((flower_soundregs2[4 + base]) & 0x0f);
+
+ voice->wave = &sound_rom1[(start << 9) & 0x7fff]; // ???
+ voice->oneshot = 0;
+ voice->oneshotplaying = 0;
+ }
+}