cleanup
This commit is contained in:
parent
f900b44eb0
commit
ff2de72d6a
@ -6,26 +6,28 @@
|
|||||||
Namco Sound, Amuse by Cab, Haunted Castle schematics and whoever first
|
Namco Sound, Amuse by Cab, Haunted Castle schematics and whoever first
|
||||||
figured out SCC!
|
figured out SCC!
|
||||||
|
|
||||||
The 051649 is a 5 channel sound generator, each channel gets it's
|
The 051649 is a 5 channel sound generator, each channel gets its
|
||||||
waveform from RAM (32 bytes per waveform, 8 bit signed data).
|
waveform from RAM (32 bytes per waveform, 8 bit signed data).
|
||||||
|
|
||||||
This sound chip is the same as the sound chip in some Konami
|
This sound chip is the same as the sound chip in some Konami
|
||||||
megaROM cartridges for the MSX. It is actually well researched
|
megaROM cartridges for the MSX. It is actually well researched
|
||||||
and documented:
|
and documented:
|
||||||
|
|
||||||
http://www.msxnet.org/tech/scc
|
http://bifi.msxnet.org/msxnet/tech/scc.html
|
||||||
|
|
||||||
Thanks to Sean Young (sean@mess.org) for some bugfixes.
|
Thanks to Sean Young (sean@mess.org) for some bugfixes.
|
||||||
|
|
||||||
K052539 is equivalent to this chip except channel 5 does not share
|
K052539 is more or less equivalent to this chip except channel 5
|
||||||
waveforms with channel 4.
|
does not share waveram with channel 4.
|
||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "k051649.h"
|
#include "k051649.h"
|
||||||
|
|
||||||
#define FREQBASEBITS 16
|
#define FREQ_BITS 16
|
||||||
|
#define DEF_GAIN 8
|
||||||
|
|
||||||
|
|
||||||
/* this structure defines the parameters for a channel */
|
/* this structure defines the parameters for a channel */
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -34,7 +36,7 @@ typedef struct
|
|||||||
int frequency;
|
int frequency;
|
||||||
int volume;
|
int volume;
|
||||||
int key;
|
int key;
|
||||||
signed char waveform[32]; /* 19991207.CAB */
|
signed char waveram[32];
|
||||||
} k051649_sound_channel;
|
} k051649_sound_channel;
|
||||||
|
|
||||||
typedef struct _k051649_state k051649_state;
|
typedef struct _k051649_state k051649_state;
|
||||||
@ -51,9 +53,8 @@ struct _k051649_state
|
|||||||
INT16 *mixer_lookup;
|
INT16 *mixer_lookup;
|
||||||
short *mixer_buffer;
|
short *mixer_buffer;
|
||||||
|
|
||||||
/* misc */
|
/* chip registers */
|
||||||
UINT8 test;
|
UINT8 test;
|
||||||
int f[10];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
INLINE k051649_state *get_safe_token(device_t *device)
|
INLINE k051649_state *get_safe_token(device_t *device)
|
||||||
@ -66,9 +67,7 @@ INLINE k051649_state *get_safe_token(device_t *device)
|
|||||||
/* build a table to divide by the number of voices */
|
/* build a table to divide by the number of voices */
|
||||||
static void make_mixer_table(running_machine &machine, k051649_state *info, int voices)
|
static void make_mixer_table(running_machine &machine, k051649_state *info, int voices)
|
||||||
{
|
{
|
||||||
int count = voices * 256;
|
|
||||||
int i;
|
int i;
|
||||||
int gain = 8;
|
|
||||||
|
|
||||||
/* allocate memory */
|
/* allocate memory */
|
||||||
info->mixer_table = auto_alloc_array(machine, INT16, 512 * voices);
|
info->mixer_table = auto_alloc_array(machine, INT16, 512 * voices);
|
||||||
@ -77,9 +76,9 @@ static void make_mixer_table(running_machine &machine, k051649_state *info, int
|
|||||||
info->mixer_lookup = info->mixer_table + (256 * voices);
|
info->mixer_lookup = info->mixer_table + (256 * voices);
|
||||||
|
|
||||||
/* fill in the table - 16 bit case */
|
/* fill in the table - 16 bit case */
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < (voices * 256); i++)
|
||||||
{
|
{
|
||||||
int val = i * gain * 16 / voices;
|
int val = i * DEF_GAIN * 16 / voices;
|
||||||
if (val > 32767) val = 32767;
|
if (val > 32767) val = 32767;
|
||||||
info->mixer_lookup[ i] = val;
|
info->mixer_lookup[ i] = val;
|
||||||
info->mixer_lookup[-i] = -val;
|
info->mixer_lookup[-i] = -val;
|
||||||
@ -94,20 +93,19 @@ static STREAM_UPDATE( k051649_update )
|
|||||||
k051649_sound_channel *voice=info->channel_list;
|
k051649_sound_channel *voice=info->channel_list;
|
||||||
stream_sample_t *buffer = outputs[0];
|
stream_sample_t *buffer = outputs[0];
|
||||||
short *mix;
|
short *mix;
|
||||||
int i,v,f,j,k;
|
int i,j;
|
||||||
|
|
||||||
/* zap the contents of the mixer buffer */
|
/* zap the contents of the mixer buffer */
|
||||||
memset(info->mixer_buffer, 0, samples * sizeof(short));
|
memset(info->mixer_buffer, 0, samples * sizeof(short));
|
||||||
|
|
||||||
for (j=0; j<5; j++) {
|
for (j = 0; j < 5; j++) {
|
||||||
v=voice[j].volume;
|
/* channel is halted for freq < 9 */
|
||||||
f=voice[j].frequency;
|
if (voice[j].frequency > 8)
|
||||||
k=voice[j].key;
|
|
||||||
/* SY 20040109: the SCC produces no sound for freq < 9 (channel is halted) */
|
|
||||||
if (f > 8)
|
|
||||||
{
|
{
|
||||||
const signed char *w = voice[j].waveform; /* 19991207.CAB */
|
const signed char *w = voice[j].waveram;
|
||||||
|
int v=voice[j].volume * voice[j].key;
|
||||||
int c=voice[j].counter;
|
int c=voice[j].counter;
|
||||||
|
int step = ((INT64)info->mclock * (1 << FREQ_BITS)) / (float)((voice[j].frequency + 1) * 16 * (info->rate / 32)) + 0.5;
|
||||||
|
|
||||||
mix = info->mixer_buffer;
|
mix = info->mixer_buffer;
|
||||||
|
|
||||||
@ -116,11 +114,9 @@ static STREAM_UPDATE( k051649_update )
|
|||||||
{
|
{
|
||||||
int offs;
|
int offs;
|
||||||
|
|
||||||
/* Amuse source: Cab suggests this method gives greater resolution */
|
c += step;
|
||||||
/* Sean Young 20010417: the formula is really: f = clock/(16*(f+1))*/
|
offs = (c >> FREQ_BITS) & 0x1f;
|
||||||
c+=(long)((((float)info->mclock / (float)((f+1) * 16))*(float)(1<<FREQBASEBITS)) / (float)(info->rate / 32));
|
*mix++ += (w[offs] * v)>>3;
|
||||||
offs = (c >> FREQBASEBITS) & 0x1f;
|
|
||||||
*mix++ += (w[offs] * v * k)>>3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update the counter for this voice */
|
/* update the counter for this voice */
|
||||||
@ -166,8 +162,6 @@ static DEVICE_RESET( k051649 )
|
|||||||
|
|
||||||
/* other parameters */
|
/* other parameters */
|
||||||
info->test = 0;
|
info->test = 0;
|
||||||
for (i = 0; i < 5; i++)
|
|
||||||
info->f[i] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************/
|
/********************************************************************************/
|
||||||
@ -175,69 +169,63 @@ static DEVICE_RESET( k051649 )
|
|||||||
WRITE8_DEVICE_HANDLER( k051649_waveform_w )
|
WRITE8_DEVICE_HANDLER( k051649_waveform_w )
|
||||||
{
|
{
|
||||||
k051649_state *info = get_safe_token(device);
|
k051649_state *info = get_safe_token(device);
|
||||||
if (info->test & 0x40)
|
|
||||||
|
/* waveram is read-only? */
|
||||||
|
if (info->test & 0x40 || (info->test & 0x80 && offset >= 0x60))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
info->stream->update();
|
info->stream->update();
|
||||||
|
|
||||||
if (offset >= 0x60)
|
if (offset >= 0x60)
|
||||||
{
|
{
|
||||||
if (info->test & 0x80)
|
/* channel 5 shares waveram with channel 4 */
|
||||||
return;
|
info->channel_list[3].waveram[offset&0x1f]=data;
|
||||||
|
info->channel_list[4].waveram[offset&0x1f]=data;
|
||||||
/* SY 20001114: Channel 5 shares the waveform with channel 4 */
|
|
||||||
info->channel_list[3].waveform[offset&0x1f]=data;
|
|
||||||
info->channel_list[4].waveform[offset&0x1f]=data;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
info->channel_list[offset>>5].waveform[offset&0x1f]=data;
|
info->channel_list[offset>>5].waveram[offset&0x1f]=data;
|
||||||
}
|
}
|
||||||
|
|
||||||
READ8_DEVICE_HANDLER ( k051649_waveform_r )
|
READ8_DEVICE_HANDLER ( k051649_waveform_r )
|
||||||
{
|
{
|
||||||
k051649_state *info = get_safe_token(device);
|
k051649_state *info = get_safe_token(device);
|
||||||
|
|
||||||
if (offset >= 0x60)
|
/* test-register bits 6/7 expose the internal counter */
|
||||||
{
|
|
||||||
if (info->test & 0xc0)
|
if (info->test & 0xc0)
|
||||||
{
|
{
|
||||||
info->stream->update();
|
info->stream->update();
|
||||||
offset += (info->channel_list[3 + (info->test >> 6 & 1)].counter >> FREQBASEBITS);
|
|
||||||
|
if (offset >= 0x60)
|
||||||
|
offset += (info->channel_list[3 + (info->test >> 6 & 1)].counter >> FREQ_BITS);
|
||||||
|
else if (info->test & 0x40)
|
||||||
|
offset += (info->channel_list[offset>>5].counter >> FREQ_BITS);
|
||||||
}
|
}
|
||||||
}
|
return info->channel_list[offset>>5].waveram[offset&0x1f];
|
||||||
else
|
|
||||||
{
|
|
||||||
if (info->test & 0x40)
|
|
||||||
{
|
|
||||||
info->stream->update();
|
|
||||||
offset += (info->channel_list[offset>>5].counter >> FREQBASEBITS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return info->channel_list[offset>>5].waveform[offset&0x1f];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE8_DEVICE_HANDLER( k052539_waveform_w )
|
WRITE8_DEVICE_HANDLER( k052539_waveform_w )
|
||||||
{
|
{
|
||||||
k051649_state *info = get_safe_token(device);
|
k051649_state *info = get_safe_token(device);
|
||||||
|
|
||||||
|
/* waveram is read-only? */
|
||||||
if (info->test & 0x40)
|
if (info->test & 0x40)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
info->stream->update();
|
info->stream->update();
|
||||||
|
info->channel_list[offset>>5].waveram[offset&0x1f]=data;
|
||||||
/* SY 20001114: Channel 5 doesn't share the waveform with channel 4 on this chip */
|
|
||||||
info->channel_list[offset>>5].waveform[offset&0x1f]=data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
READ8_DEVICE_HANDLER ( k052539_waveform_r )
|
READ8_DEVICE_HANDLER ( k052539_waveform_r )
|
||||||
{
|
{
|
||||||
k051649_state *info = get_safe_token(device);
|
k051649_state *info = get_safe_token(device);
|
||||||
|
|
||||||
|
/* test-register bit 6 exposes the internal counter */
|
||||||
if (info->test & 0x40)
|
if (info->test & 0x40)
|
||||||
{
|
{
|
||||||
info->stream->update();
|
info->stream->update();
|
||||||
offset += (info->channel_list[offset>>5].counter >> FREQBASEBITS);
|
offset += (info->channel_list[offset>>5].counter >> FREQ_BITS);
|
||||||
}
|
}
|
||||||
return info->channel_list[offset>>5].waveform[offset&0x1f];
|
return info->channel_list[offset>>5].waveram[offset&0x1f];
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE8_DEVICE_HANDLER( k051649_volume_w )
|
WRITE8_DEVICE_HANDLER( k051649_volume_w )
|
||||||
@ -250,16 +238,22 @@ WRITE8_DEVICE_HANDLER( k051649_volume_w )
|
|||||||
WRITE8_DEVICE_HANDLER( k051649_frequency_w )
|
WRITE8_DEVICE_HANDLER( k051649_frequency_w )
|
||||||
{
|
{
|
||||||
k051649_state *info = get_safe_token(device);
|
k051649_state *info = get_safe_token(device);
|
||||||
info->f[offset]=data;
|
int freq_hi = offset & 1;
|
||||||
|
offset >>= 1;
|
||||||
|
|
||||||
info->stream->update();
|
info->stream->update();
|
||||||
|
|
||||||
|
/* test-register bit 5 resets the internal counter */
|
||||||
if (info->test & 0x20)
|
if (info->test & 0x20)
|
||||||
info->channel_list[offset>>1].counter = ~0;
|
info->channel_list[offset].counter = ~0;
|
||||||
else if (info->channel_list[offset>>1].frequency < 9)
|
else if (info->channel_list[offset].frequency < 9)
|
||||||
info->channel_list[offset>>1].counter |= ((1 << FREQBASEBITS) - 1);
|
info->channel_list[offset].counter |= ((1 << FREQ_BITS) - 1);
|
||||||
|
|
||||||
info->channel_list[offset>>1].frequency=(info->f[offset&0xe] + (info->f[offset|1]<<8))&0xfff;
|
/* update frequency */
|
||||||
|
if (freq_hi)
|
||||||
|
info->channel_list[offset].frequency = (info->channel_list[offset].frequency & 0x0ff) | (data << 8 & 0xf00);
|
||||||
|
else
|
||||||
|
info->channel_list[offset].frequency = (info->channel_list[offset].frequency & 0xf00) | data;
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE8_DEVICE_HANDLER( k051649_keyonoff_w )
|
WRITE8_DEVICE_HANDLER( k051649_keyonoff_w )
|
||||||
@ -282,10 +276,8 @@ WRITE8_DEVICE_HANDLER( k051649_test_w )
|
|||||||
|
|
||||||
READ8_DEVICE_HANDLER ( k051649_test_r )
|
READ8_DEVICE_HANDLER ( k051649_test_r )
|
||||||
{
|
{
|
||||||
k051649_state *info = get_safe_token(device);
|
|
||||||
|
|
||||||
/* reading the test register sets it to $ff! */
|
/* reading the test register sets it to $ff! */
|
||||||
info->test = 0xff;
|
k051649_test_w(device, offset, 0xff);
|
||||||
return 0xff;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user