diff options
author | 2008-09-04 08:57:02 +0000 | |
---|---|---|
committer | 2008-09-04 08:57:02 +0000 | |
commit | 7c90a0cd38d4816a8f252e8c4da84e9f751d8369 (patch) | |
tree | 434d0d421d10d1e05a0b93ba08fd7c45f97ab2b8 /src/emu/sound/snkwave.c | |
parent | f724e4c6bfc1be4d3a16c7eaa243750c153129d2 (diff) |
fixed emulation of the "SNK Wave" custom sound used by Marvin's Maze and Vanguard II and made it into a proper sound core
fixed palette decoding of early SNK games (from marvins to athena + fitegolf). The least significan bits were assigned incorrectly.
merged marvins.c into snk.c, with all resulting fixes (removed hacks, correct shadows, scroll offsets etc)
Diffstat (limited to 'src/emu/sound/snkwave.c')
-rw-r--r-- | src/emu/sound/snkwave.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/emu/sound/snkwave.c b/src/emu/sound/snkwave.c new file mode 100644 index 00000000000..b9319acdc13 --- /dev/null +++ b/src/emu/sound/snkwave.c @@ -0,0 +1,194 @@ +/*************************************************************************** + + SNK Wave sound driver. + + This is a very simple single-voice generator with a programmable waveform. + +***************************************************************************/ + +#include "sndintrf.h" +#include "streams.h" +#include "snkwave.h" + + +#define WAVEFORM_LENGTH 16 + +#define CLOCK_SHIFT 8 + + +struct snkwave_sound +{ + /* global sound parameters */ + sound_stream * stream; + int external_clock; + int sample_rate; + + /* data about the sound system */ + UINT32 frequency; + UINT32 counter; + int waveform_position; + + /* decoded waveform table */ + INT16 waveform[WAVEFORM_LENGTH]; +}; + + +/* update the decoded waveform data */ +/* The programmable waveform consists of 8 3-bit nibbles. + The waveform goes to a 4-bit DAC and is played alternatingly forwards and + backwards. + When going forwards, bit 3 is 1. When going backwards, it's 0. + So the sequence 01234567 will play as + 89ABCDEF76543210 +*/ +static void update_waveform(struct snkwave_sound *chip, unsigned int offset, UINT8 data) +{ + assert(offset < WAVEFORM_LENGTH/4); + + chip->waveform[offset * 2] = ((data & 0x38) >> 3) << (12-CLOCK_SHIFT); + chip->waveform[offset * 2 + 1] = ((data & 0x07) >> 0) << (12-CLOCK_SHIFT); + chip->waveform[WAVEFORM_LENGTH-2 - offset * 2] = ~chip->waveform[offset * 2 + 1]; + chip->waveform[WAVEFORM_LENGTH-1 - offset * 2] = ~chip->waveform[offset * 2]; +} + + +/* generate sound to the mix buffer */ +static void snkwave_update(void *param, stream_sample_t **inputs, stream_sample_t **_buffer, int length) +{ + struct snkwave_sound *chip = param; + stream_sample_t *buffer = _buffer[0]; + + /* zap the contents of the buffer */ + memset(buffer, 0, length * sizeof(*buffer)); + + assert(chip->counter < 0x1000); + assert(chip->frequency < 0x1000); + + /* if no sound, we're done */ + if (chip->frequency == 0xfff) + return; + + /* generate sound into buffer while updating the counter */ + while (length-- > 0) + { + int loops; + INT16 out = 0; + + loops = 1 << CLOCK_SHIFT; + while (loops > 0) + { + int steps = 0x1000 - chip->counter; + + if (steps <= loops) + { + out += chip->waveform[chip->waveform_position] * steps; + chip->counter = chip->frequency; + chip->waveform_position = (chip->waveform_position + 1) & (WAVEFORM_LENGTH-1); + loops -= steps; + } + else + { + out += chip->waveform[chip->waveform_position] * loops; + chip->counter += loops; + loops = 0; + } + } + + *buffer++ = out; + } +} + + +static void *snkwave_start(const char *tag, int sndindex, int clock, const void *config) +{ + struct snkwave_sound *chip; + + assert(config == 0); + + chip = auto_malloc(sizeof(*chip)); + memset(chip, 0, sizeof(*chip)); + + /* adjust internal clock */ + chip->external_clock = clock; + + /* adjust output clock */ + chip->sample_rate = chip->external_clock >> CLOCK_SHIFT; + + /* get stream channels */ + chip->stream = stream_create(0, 1, chip->sample_rate, chip, snkwave_update); + + /* reset all the voices */ + chip->frequency = 0; + chip->counter = 0; + chip->waveform_position = 0; + + /* register with the save state system */ + state_save_register_item("snkwave", sndindex, chip->frequency); + state_save_register_item("snkwave", sndindex, chip->counter); + state_save_register_item("snkwave", sndindex, chip->waveform_position); + state_save_register_item_pointer("snkwave", sndindex, chip->waveform, WAVEFORM_LENGTH); + + return chip; +} + + +/********************************************************************************/ + +/* SNK wave register map + all registers are 6-bit + 0-1 frequency (12-bit) + 2-5 waveform (8 3-bit nibbles) +*/ + +WRITE8_HANDLER( snkwave_w ) +{ + struct snkwave_sound *chip = sndti_token(SOUND_SNKWAVE, 0); + + stream_update(chip->stream); + + // all registers are 6-bit + data &= 0x3f; + + if (offset == 0) + chip->frequency = (chip->frequency & 0x03f) | (data << 6); + else if (offset == 1) + chip->frequency = (chip->frequency & 0xfc0) | data; + else if (offset <= 5) + update_waveform(chip, offset - 2, data); +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +static void snkwave_set_info(void *token, UINT32 state, sndinfo *info) +{ + switch (state) + { + /* no parameters to set */ + } +} + + +void snkwave_get_info(void *token, UINT32 state, sndinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case SNDINFO_PTR_SET_INFO: info->set_info = snkwave_set_info; break; + case SNDINFO_PTR_START: info->start = snkwave_start; break; + case SNDINFO_PTR_STOP: /* Nothing */ break; + case SNDINFO_PTR_RESET: /* Nothing */ break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case SNDINFO_STR_NAME: info->s = "SNK Wave"; break; + case SNDINFO_STR_CORE_FAMILY: info->s = "SNK Wave"; break; + case SNDINFO_STR_CORE_VERSION: info->s = "1.0"; break; + case SNDINFO_STR_CORE_FILE: info->s = __FILE__; break; + case SNDINFO_STR_CORE_CREDITS: info->s = "Copyright Nicola Salmoria and the MAME Team"; break; + } +} |