Merge pull request #1254 from superctr/c352_improvement

Namco C352 improvements
This commit is contained in:
Olivier Galibert 2016-08-17 13:48:14 +02:00 committed by GitHub
commit 2d198239db
9 changed files with 246 additions and 463 deletions

View File

@ -1,9 +1,10 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:R. Belmont // copyright-holders:R. Belmont, superctr
/* /*
c352.c - Namco C352 custom PCM chip emulation c352.c - Namco C352 custom PCM chip emulation
v1.2 v2.0
By R. Belmont By R. Belmont
Rewritten and improved by superctr
Additional code by cync and the hoot development team Additional code by cync and the hoot development team
Thanks to Cap of VivaNonno for info and The_Author for preliminary reverse-engineering Thanks to Cap of VivaNonno for info and The_Author for preliminary reverse-engineering
@ -13,14 +14,6 @@
Supports 8-bit linear and 8-bit muLaw samples Supports 8-bit linear and 8-bit muLaw samples
Output: digital, 16 bit, 4 channels Output: digital, 16 bit, 4 channels
Output sample rate is the input clock / (288 * 2). Output sample rate is the input clock / (288 * 2).
superctr: The clock divider appears to be configurable for each system.
Below is a list of the divider values followed by the systems that use it.
* 228: System 11.
* 288: System 22, Super 22, NB-1/2, ND-1, FL.
* 296: System 23, Super 23.
* 332: System 12.
*/ */
#include "emu.h" #include "emu.h"
@ -58,405 +51,195 @@ void c352_device::static_set_divider(device_t &device, int setting)
c352.m_divider = setting; c352.m_divider = setting;
} }
void c352_device::fetch_sample(c352_voice_t* v)
// noise generator
int c352_device::get_mseq_bit()
{ {
unsigned int mask = (1 << (7 - 1)); v->last_sample = v->sample;
unsigned int reg = m_mseq_reg;
unsigned int bit = reg & (1 << (17 - 1));
if (bit) if(v->flags & C352_FLG_NOISE)
{ {
reg = ((reg ^ mask) << 1) | 1; m_random = (m_random>>1) ^ ((-(m_random&1)) & 0xfff6);
v->sample = m_random;
} }
else else
{ {
reg = reg << 1; char s;
}
m_mseq_reg = reg; s = (char)read_byte(v->pos);
return (reg & 1); if(v->flags & C352_FLG_MULAW)
} v->sample = m_mulaw_table[(unsigned char)s];
else
v->sample = s<<8;
void c352_device::mix_one_channel(unsigned long ch, long sample_count) unsigned short pos = v->pos&0xffff;
{
int i;
signed short sample, nextsample; if((v->flags & C352_FLG_LOOP) && v->flags & C352_FLG_REVERSE)
signed short noisebuf; {
UINT16 noisecnt; // backwards>forwards
INT32 frequency, delta, offset, cnt, flag; if((v->flags & C352_FLG_LDIR) && pos == v->wave_loop)
UINT32 bank; v->flags &= ~C352_FLG_LDIR;
UINT32 pos; // forwards>backwards
else if(!(v->flags & C352_FLG_LDIR) && pos == v->wave_end)
v->flags |= C352_FLG_LDIR;
frequency = m_c352_ch[ch].pitch; v->pos += (v->flags&C352_FLG_LDIR) ? -1 : 1;
delta=frequency; }
else if(pos == v->wave_end)
pos = m_c352_ch[ch].current_addr; // sample pointer {
offset = m_c352_ch[ch].pos; // 16.16 fixed-point offset into the sample if((v->flags & C352_FLG_LINK) && (v->flags & C352_FLG_LOOP))
flag = m_c352_ch[ch].flag; {
bank = m_c352_ch[ch].bank << 16; v->pos = (v->wave_start<<16) | v->wave_loop;
v->flags |= C352_FLG_LOOPHIST;
noisecnt = m_c352_ch[ch].noisecnt; }
noisebuf = m_c352_ch[ch].noisebuf; else if(v->flags & C352_FLG_LOOP)
{
for(i = 0 ; (i < sample_count) && (flag & C352_FLG_BUSY) ; i++) v->pos = (v->pos&0xff0000) | v->wave_loop;
{ v->flags |= C352_FLG_LOOPHIST;
offset += delta; }
cnt = (offset>>16)&0x7fff; else
if (cnt) // if there is a whole sample part, chop it off now that it's been applied {
{ v->flags |= C352_FLG_KEYOFF;
offset &= 0xffff; v->flags &= ~C352_FLG_BUSY;
} v->sample=0;
}
if (pos > 0x1000000) }
{
m_c352_ch[ch].flag &= ~C352_FLG_BUSY;
return;
}
sample = (char)read_byte(pos);
nextsample = (char)read_byte(pos+cnt);
// sample is muLaw, not 8-bit linear (Fighting Layer uses this extensively)
if (flag & C352_FLG_MULAW)
{
sample = m_mulaw_table[(unsigned char)sample];
nextsample = m_mulaw_table[(unsigned char)nextsample];
}
else else
{ {
sample <<= 8; v->pos += (v->flags&C352_FLG_REVERSE) ? -1 : 1;
nextsample <<= 8;
}
// play noise instead of sample data
if (flag & C352_FLG_NOISE)
{
int noise_level = 0x8000;
sample = m_c352_ch[ch].noise = (m_c352_ch[ch].noise << 1) | get_mseq_bit();
sample = (sample & (noise_level - 1)) - (noise_level >> 1);
if (sample > 0x7f)
{
sample = 0x7f;
}
else if (sample < 0)
{
sample = 0xff;
}
sample = m_mulaw_table[(unsigned char)sample];
if ( (pos+cnt) == pos )
{
noisebuf += sample;
noisecnt++;
sample = noisebuf / noisecnt;
}
else
{
if ( noisecnt )
{
sample = noisebuf / noisecnt;
}
else
{
sample = m_mulaw_table[0x7f]; // Nearest sound(s) is here.
}
noisebuf = 0;
noisecnt = ( flag & C352_FLG_FILTER ) ? 0 : 1;
}
}
// apply linear interpolation
if ( (flag & (C352_FLG_FILTER | C352_FLG_NOISE)) == 0 )
{
sample = (short)(sample + ((nextsample-sample) * (((double)(0x0000ffff&offset) )/0x10000)));
}
if ( flag & C352_FLG_PHASEFL )
{
m_channel_l[i] += ((-sample * m_c352_ch[ch].vol_l)>>8);
}
else
{
m_channel_l[i] += ((sample * m_c352_ch[ch].vol_l)>>8);
}
if ( flag & C352_FLG_PHASEFR )
{
m_channel_r[i] += ((-sample * m_c352_ch[ch].vol_r)>>8);
}
else
{
m_channel_r[i] += ((sample * m_c352_ch[ch].vol_r)>>8);
}
if ( flag & C352_FLG_PHASERL )
{
m_channel_l2[i] += ((-sample * m_c352_ch[ch].vol_l2)>>8);
}
else
{
m_channel_l2[i] += ((sample * m_c352_ch[ch].vol_l2)>>8);
}
m_channel_r2[i] += ((sample * m_c352_ch[ch].vol_r2)>>8);
if ( (flag & C352_FLG_REVERSE) && (flag & C352_FLG_LOOP) )
{
if ( !(flag & C352_FLG_LDIR) )
{
pos += cnt;
if (
(((pos&0xFFFF) > m_c352_ch[ch].end_addr) && ((pos&0xFFFF) < m_c352_ch[ch].start) && (m_c352_ch[ch].start > m_c352_ch[ch].end_addr) ) ||
(((pos&0xFFFF) > m_c352_ch[ch].end_addr) && ((pos&0xFFFF) > m_c352_ch[ch].start) && (m_c352_ch[ch].start < m_c352_ch[ch].end_addr) ) ||
((pos > (bank|0xFFFF)) && (m_c352_ch[ch].end_addr == 0xFFFF))
)
{
m_c352_ch[ch].flag |= C352_FLG_LDIR;
m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
}
}
else
{
pos -= cnt;
if (
(((pos&0xFFFF) < m_c352_ch[ch].repeat) && ((pos&0xFFFF) < m_c352_ch[ch].end_addr) && (m_c352_ch[ch].end_addr > m_c352_ch[ch].start) ) ||
(((pos&0xFFFF) < m_c352_ch[ch].repeat) && ((pos&0xFFFF) > m_c352_ch[ch].end_addr) && (m_c352_ch[ch].end_addr < m_c352_ch[ch].start) ) ||
((pos < bank) && (m_c352_ch[ch].repeat == 0x0000))
)
{
m_c352_ch[ch].flag &= ~C352_FLG_LDIR;
m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
}
}
}
else if ( flag & C352_FLG_REVERSE )
{
pos -= cnt;
if (
(((pos&0xFFFF) < m_c352_ch[ch].end_addr) && ((pos&0xFFFF) < m_c352_ch[ch].start) && (m_c352_ch[ch].start > m_c352_ch[ch].end_addr) ) ||
(((pos&0xFFFF) < m_c352_ch[ch].end_addr) && ((pos&0xFFFF) > m_c352_ch[ch].start) && (m_c352_ch[ch].start < m_c352_ch[ch].end_addr) ) ||
((pos < bank) && (m_c352_ch[ch].end_addr == 0x0000))
)
{
if ( (flag & C352_FLG_LINK) && (flag & C352_FLG_LOOP) )
{
m_c352_ch[ch].bank = m_c352_ch[ch].start_addr & 0xFF;
m_c352_ch[ch].start_addr = m_c352_ch[ch].repeat_addr;
m_c352_ch[ch].start = m_c352_ch[ch].start_addr;
m_c352_ch[ch].repeat = m_c352_ch[ch].repeat_addr;
pos = (m_c352_ch[ch].bank<<16) + m_c352_ch[ch].start_addr;
m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
}
else if (flag & C352_FLG_LOOP)
{
pos = (pos & 0xFF0000) + m_c352_ch[ch].repeat;
m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
}
else
{
m_c352_ch[ch].flag |= C352_FLG_KEYOFF;
m_c352_ch[ch].flag &= ~C352_FLG_BUSY;
return;
}
}
} else {
pos += cnt;
if (
(((pos&0xFFFF) > m_c352_ch[ch].end_addr) && ((pos&0xFFFF) < m_c352_ch[ch].start) && (m_c352_ch[ch].start > m_c352_ch[ch].end_addr) ) ||
(((pos&0xFFFF) > m_c352_ch[ch].end_addr) && ((pos&0xFFFF) > m_c352_ch[ch].start) && (m_c352_ch[ch].start < m_c352_ch[ch].end_addr) ) ||
((pos > (bank|0xFFFF)) && (m_c352_ch[ch].end_addr == 0xFFFF))
)
{
if ( (flag & C352_FLG_LINK) && (flag & C352_FLG_LOOP) )
{
m_c352_ch[ch].bank = m_c352_ch[ch].start_addr & 0xFF;
m_c352_ch[ch].start_addr = m_c352_ch[ch].repeat_addr;
m_c352_ch[ch].start = m_c352_ch[ch].start_addr;
m_c352_ch[ch].repeat = m_c352_ch[ch].repeat_addr;
pos = (m_c352_ch[ch].bank<<16) + m_c352_ch[ch].start_addr;
m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
}
else if (flag & C352_FLG_LOOP)
{
pos = (pos & 0xFF0000) + m_c352_ch[ch].repeat;
m_c352_ch[ch].flag |= C352_FLG_LOOPHIST;
}
else
{
m_c352_ch[ch].flag |= C352_FLG_KEYOFF;
m_c352_ch[ch].flag &= ~C352_FLG_BUSY;
return;
}
}
} }
} }
m_c352_ch[ch].noisecnt = noisecnt;
m_c352_ch[ch].noisebuf = noisebuf;
m_c352_ch[ch].pos = offset;
m_c352_ch[ch].current_addr = pos;
} }
void c352_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) void c352_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{ {
int i, j;
stream_sample_t *bufferl = outputs[0];
stream_sample_t *bufferr = outputs[1];
stream_sample_t *bufferl2 = outputs[2];
stream_sample_t *bufferr2 = outputs[3];
for(i = 0 ; i < samples ; i++) int i,j;
short s;
stream_sample_t *buffer_fl = outputs[0];
stream_sample_t *buffer_fr = outputs[1];
stream_sample_t *buffer_rl = outputs[2];
stream_sample_t *buffer_rr = outputs[3];
c352_voice_t* v;
long out[4];
for(i=0;i<samples;i++)
{ {
m_channel_l[i] = m_channel_r[i] = m_channel_l2[i] = m_channel_r2[i] = 0; out[0]=out[1]=out[2]=out[3]=0;
for(j=0;j<32;j++)
{
v = &m_c352_v[j];
s = 0;
if(v->flags & C352_FLG_BUSY)
{
v->counter += v->freq;
if(v->counter > 0x10000)
{
v->counter &= 0xffff;
fetch_sample(v);
}
s = v->sample;
// Interpolate samples
if((v->flags & C352_FLG_FILTER) == 0)
s = v->last_sample + (v->counter*(v->sample-v->last_sample)>>16);
}
// Left
out[0] += ((v->flags & C352_FLG_PHASEFL) ? -s * (v->vol_f>>8) : s * (v->vol_f>>8))>>8;
out[2] += ((v->flags & C352_FLG_PHASERL) ? -s * (v->vol_r>>8) : s * (v->vol_r>>8))>>8;
// Right
out[1] += ((v->flags & C352_FLG_PHASEFR) ? -s * (v->vol_f&0xff) : s * (v->vol_f&0xff))>>8;
out[3] += ((v->flags & C352_FLG_PHASEFR) ? -s * (v->vol_r&0xff) : s * (v->vol_r&0xff))>>8;
}
*buffer_fl++ = (short) (out[0]>>3);
*buffer_fr++ = (short) (out[1]>>3);
*buffer_rl++ = (short) (out[2]>>3);
*buffer_rr++ = (short) (out[3]>>3);
} }
for (j = 0 ; j < 32 ; j++)
{
mix_one_channel(j, samples);
}
for(i = 0 ; i < samples ; i++)
{
*bufferl++ = (short) (m_channel_l[i] >>3);
*bufferr++ = (short) (m_channel_r[i] >>3);
*bufferl2++ = (short) (m_channel_l2[i] >>3);
*bufferr2++ = (short) (m_channel_r2[i] >>3);
}
} }
unsigned short c352_device::read_reg16(unsigned long address) unsigned short c352_device::read_reg16(unsigned long address)
{ {
unsigned long chan;
unsigned short val;
m_stream->update(); m_stream->update();
chan = (address >> 4) & 0xfff; const int reg_map[8] =
if (chan > 31)
{ {
val = 0; offsetof(c352_voice_t,vol_f) / sizeof(unsigned short),
} offsetof(c352_voice_t,vol_r) / sizeof(unsigned short),
else offsetof(c352_voice_t,freq) / sizeof(unsigned short),
{ offsetof(c352_voice_t,flags) / sizeof(unsigned short),
if ((address & 0xf) == 6) offsetof(c352_voice_t,wave_bank) / sizeof(unsigned short),
{ offsetof(c352_voice_t,wave_start) / sizeof(unsigned short),
val = m_c352_ch[chan].flag; offsetof(c352_voice_t,wave_end) / sizeof(unsigned short),
} offsetof(c352_voice_t,wave_loop) / sizeof(unsigned short),
else };
{
val = 0; if(address < 0x100)
} return *((unsigned short*)&m_c352_v[address/8]+reg_map[address%8]);
} else
return val; return 0;
return 0;
} }
void c352_device::write_reg16(unsigned long address, unsigned short val) void c352_device::write_reg16(unsigned long address, unsigned short val)
{ {
unsigned long chan;
int i;
m_stream->update(); m_stream->update();
chan = (address >> 4) & 0xfff; const int reg_map[8] =
if ( address >= 0x400 )
{ {
switch(address) offsetof(c352_voice_t,vol_f) / sizeof(unsigned short),
{ offsetof(c352_voice_t,vol_r) / sizeof(unsigned short),
case 0x404: // execute key-ons/offs offsetof(c352_voice_t,freq) / sizeof(unsigned short),
for ( i = 0 ; i <= 31 ; i++ ) offsetof(c352_voice_t,flags) / sizeof(unsigned short),
{ offsetof(c352_voice_t,wave_bank) / sizeof(unsigned short),
if ( m_c352_ch[i].flag & C352_FLG_KEYON ) offsetof(c352_voice_t,wave_start) / sizeof(unsigned short),
{ offsetof(c352_voice_t,wave_end) / sizeof(unsigned short),
if (m_c352_ch[i].start_addr != m_c352_ch[i].end_addr) offsetof(c352_voice_t,wave_loop) / sizeof(unsigned short),
{ };
m_c352_ch[i].current_addr = (m_c352_ch[i].bank << 16) + m_c352_ch[i].start_addr;
m_c352_ch[i].start = m_c352_ch[i].start_addr;
m_c352_ch[i].repeat = m_c352_ch[i].repeat_addr;
m_c352_ch[i].noisebuf = 0;
m_c352_ch[i].noisecnt = 0;
m_c352_ch[i].flag &= ~(C352_FLG_KEYON | C352_FLG_LOOPHIST);
m_c352_ch[i].flag |= C352_FLG_BUSY;
}
}
else if ( m_c352_ch[i].flag & C352_FLG_KEYOFF )
{
m_c352_ch[i].flag &= ~C352_FLG_BUSY;
m_c352_ch[i].flag &= ~(C352_FLG_KEYOFF);
}
}
break;
default:
break;
}
return;
}
if (chan > 31) int i;
if(address < 0x100)
{ {
LOG(("C352 CTRL %08lx %04x\n", address, val)); //printf("w %04lx,%04x, %d\n", address, val, reg_map[address&7]);
return; *((unsigned short*)&m_c352_v[address/8]+reg_map[address%8]) = val;
} }
switch(address & 0xf) else if(address == 0x200)
{ m_control = val;
case 0x0: else if(address == 0x202) // execute keyons/keyoffs
// volumes (output 1) {
LOG(("CH %02ld LVOL %02x RVOL %02x\n", chan, val & 0xff, val >> 8)); for(i=0;i<32;i++)
m_c352_ch[chan].vol_l = val & 0xff; {
m_c352_ch[chan].vol_r = val >> 8; if((m_c352_v[i].flags & C352_FLG_KEYON))
break; {
m_c352_v[i].pos = (m_c352_v[i].wave_bank<<16) | m_c352_v[i].wave_start;
case 0x2: m_c352_v[i].sample = 0;
// volumes (output 2) m_c352_v[i].last_sample = 0;
LOG(("CH %02ld RLVOL %02x RRVOL %02x\n", chan, val & 0xff, val >> 8)); m_c352_v[i].counter = 0x10000;
m_c352_ch[chan].vol_l2 = val & 0xff;
m_c352_ch[chan].vol_r2 = val >> 8;
break;
case 0x4: m_c352_v[i].flags |= C352_FLG_BUSY;
// pitch m_c352_v[i].flags &= ~(C352_FLG_KEYON|C352_FLG_LOOPHIST);
LOG(("CH %02ld PITCH %04x\n", chan, val));
m_c352_ch[chan].pitch = val;
break;
case 0x6: //printf("voice %d : pos= %08x\n",i,m_c352_v[i].pos);
// flags }
LOG(("CH %02ld FLAG %02x\n", chan, val)); else if(m_c352_v[i].flags & C352_FLG_KEYOFF)
m_c352_ch[chan].flag = val; {
break; m_c352_v[i].flags &= ~(C352_FLG_BUSY|C352_FLG_KEYOFF);
}
case 0x8: }
// bank (bits 16-31 of address); }
m_c352_ch[chan].bank = val & 0xff;
LOG(("CH %02ld BANK %02x", chan, m_c352_ch[chan].bank));
break;
case 0xa:
// start address
LOG(("CH %02ld SADDR %04x\n", chan, val));
m_c352_ch[chan].start_addr = val;
break;
case 0xc:
// end address
LOG(("CH %02ld EADDR %04x\n", chan, val));
m_c352_ch[chan].end_addr = val;
break;
case 0xe:
// loop address
LOG(("CH %02ld LADDR %04x\n", chan, val));
m_c352_ch[chan].repeat_addr = val;
break;
default:
LOG(("CH %02ld UNKN %01lx %04x", chan, address & 0xf, val));
break;
}
} }
void c352_device::device_start() void c352_device::device_start()
@ -486,45 +269,44 @@ void c352_device::device_start()
// register save state info // register save state info
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
{ {
save_item(NAME(m_c352_ch[i].vol_l), i); save_item(NAME(m_c352_v[i].pos), i);
save_item(NAME(m_c352_ch[i].vol_r), i); save_item(NAME(m_c352_v[i].counter), i);
save_item(NAME(m_c352_ch[i].vol_l2), i); save_item(NAME(m_c352_v[i].sample), i);
save_item(NAME(m_c352_ch[i].vol_r2), i); save_item(NAME(m_c352_v[i].last_sample), i);
save_item(NAME(m_c352_ch[i].bank), i); save_item(NAME(m_c352_v[i].vol_f), i);
save_item(NAME(m_c352_ch[i].noise), i); save_item(NAME(m_c352_v[i].vol_r), i);
save_item(NAME(m_c352_ch[i].noisebuf), i); save_item(NAME(m_c352_v[i].freq), i);
save_item(NAME(m_c352_ch[i].noisecnt), i); save_item(NAME(m_c352_v[i].flags), i);
save_item(NAME(m_c352_ch[i].pitch), i); save_item(NAME(m_c352_v[i].wave_bank), i);
save_item(NAME(m_c352_ch[i].start_addr), i); save_item(NAME(m_c352_v[i].wave_start), i);
save_item(NAME(m_c352_ch[i].end_addr), i); save_item(NAME(m_c352_v[i].wave_end), i);
save_item(NAME(m_c352_ch[i].repeat_addr), i); save_item(NAME(m_c352_v[i].wave_loop), i);
save_item(NAME(m_c352_ch[i].flag), i);
save_item(NAME(m_c352_ch[i].start), i);
save_item(NAME(m_c352_ch[i].repeat), i);
save_item(NAME(m_c352_ch[i].current_addr), i);
save_item(NAME(m_c352_ch[i].pos), i);
} }
save_item(NAME(m_random));
save_item(NAME(m_control));
} }
void c352_device::device_reset() void c352_device::device_reset()
{ {
// clear all channels states // clear all channels states
memset(m_c352_ch, 0, sizeof(c352_ch_t)*32); memset(m_c352_v, 0, sizeof(c352_voice_t)*32);
// init noise generator // init noise generator
m_mseq_reg = 0x12345678; m_random = 0x1234;
m_control = 0;
} }
READ16_MEMBER( c352_device::read ) READ16_MEMBER( c352_device::read )
{ {
return(read_reg16(offset*2)); return(read_reg16(offset));
} }
WRITE16_MEMBER( c352_device::write ) WRITE16_MEMBER( c352_device::write )
{ {
if (mem_mask == 0xffff) if (mem_mask == 0xffff)
{ {
write_reg16(offset*2, data); write_reg16(offset, data);
} }
else else
{ {

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:R. Belmont // copyright-holders:R. Belmont, superctr
#pragma once #pragma once
#ifndef __C352_H__ #ifndef __C352_H__
@ -67,43 +67,37 @@ private:
C352_FLG_REVERSE = 0x0001 // play sample backwards C352_FLG_REVERSE = 0x0001 // play sample backwards
}; };
struct c352_ch_t struct c352_voice_t {
{
UINT8 vol_l; unsigned int pos;
UINT8 vol_r; unsigned int counter;
UINT8 vol_l2;
UINT8 vol_r2; short sample;
UINT8 bank; short last_sample;
INT16 noise;
INT16 noisebuf; unsigned short vol_f;
UINT16 noisecnt; unsigned short vol_r;
UINT16 pitch; unsigned short freq;
UINT16 start_addr; unsigned short flags;
UINT16 end_addr;
UINT16 repeat_addr; unsigned short wave_bank;
UINT32 flag; unsigned short wave_start;
unsigned short wave_end;
unsigned short wave_loop;
UINT16 start;
UINT16 repeat;
UINT32 current_addr;
UINT32 pos;
}; };
c352_ch_t m_c352_ch[32];
int m_sample_rate_base; int m_sample_rate_base;
int m_divider; int m_divider;
long m_channel_l[2048*2]; c352_voice_t m_c352_v[32];
long m_channel_r[2048*2];
long m_channel_l2[2048*2];
long m_channel_r2[2048*2];
short m_mulaw_table[256]; short m_mulaw_table[256];
unsigned int m_mseq_reg;
// private functions unsigned short m_random;
int get_mseq_bit(void); unsigned short m_control; // control flags, purpose unknown.
void mix_one_channel(unsigned long ch, long sample_count);
void fetch_sample(c352_voice_t* v);
unsigned short read_reg16(unsigned long address); unsigned short read_reg16(unsigned long address);
void write_reg16(unsigned long address, unsigned short val); void write_reg16(unsigned long address, unsigned short val);
}; };

View File

@ -611,10 +611,10 @@ static MACHINE_CONFIG_START( namcofl, namcofl_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_C352_ADD("c352", 48384000/2, 288) MCFG_C352_ADD("c352", 48384000/2, 288)
MCFG_SOUND_ROUTE(0, "rspeaker", 1.00) MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(1, "lspeaker", 1.00) MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
MCFG_SOUND_ROUTE(2, "rspeaker", 1.00) //MCFG_SOUND_ROUTE(2, "lspeaker", 1.00) // Second DAC not present.
MCFG_SOUND_ROUTE(3, "lspeaker", 1.00) //MCFG_SOUND_ROUTE(3, "rspeaker", 1.00)
MACHINE_CONFIG_END MACHINE_CONFIG_END
ROM_START( speedrcr ) ROM_START( speedrcr )

View File

@ -1146,10 +1146,10 @@ static MACHINE_CONFIG_START( namconb1, namconb1_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_C352_ADD("c352", MASTER_CLOCK/2, 288) MCFG_C352_ADD("c352", MASTER_CLOCK/2, 288)
MCFG_SOUND_ROUTE(0, "rspeaker", 1.00) MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(1, "lspeaker", 1.00) MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
MCFG_SOUND_ROUTE(2, "rspeaker", 1.00) //MCFG_SOUND_ROUTE(2, "lspeaker", 1.00) // Second DAC not present.
MCFG_SOUND_ROUTE(3, "lspeaker", 1.00) //MCFG_SOUND_ROUTE(3, "rspeaker", 1.00)
MACHINE_CONFIG_END MACHINE_CONFIG_END
static MACHINE_CONFIG_START( namconb2, namconb1_state ) static MACHINE_CONFIG_START( namconb2, namconb1_state )

View File

@ -209,10 +209,10 @@ static MACHINE_CONFIG_START( namcond1, namcond1_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_C352_ADD("c352", XTAL_49_152MHz/2, 288) MCFG_C352_ADD("c352", XTAL_49_152MHz/2, 288)
MCFG_SOUND_ROUTE(0, "rspeaker", 1.00) MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(1, "lspeaker", 1.00) MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
MCFG_SOUND_ROUTE(2, "rspeaker", 1.00) //MCFG_SOUND_ROUTE(2, "lspeaker", 1.00) // Second DAC not present.
MCFG_SOUND_ROUTE(3, "lspeaker", 1.00) //MCFG_SOUND_ROUTE(3, "rspeaker", 1.00)
MCFG_AT28C16_ADD( "at28c16", nullptr ) MCFG_AT28C16_ADD( "at28c16", nullptr )

View File

@ -593,11 +593,11 @@ static MACHINE_CONFIG_START( coh110, namcos11_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_C352_ADD("c352", 20013200, 228) MCFG_C352_ADD("c352", 25401600, 288)
MCFG_SOUND_ROUTE(0, "rspeaker", 1.00) MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(1, "lspeaker", 1.00) MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
MCFG_SOUND_ROUTE(2, "rspeaker", 1.00) //MCFG_SOUND_ROUTE(2, "lspeaker", 1.00) // Second DAC not present.
MCFG_SOUND_ROUTE(3, "lspeaker", 1.00) //MCFG_SOUND_ROUTE(3, "rspeaker", 1.00)
MCFG_AT28C16_ADD( "at28c16", nullptr ) MCFG_AT28C16_ADD( "at28c16", nullptr )
MACHINE_CONFIG_END MACHINE_CONFIG_END

View File

@ -1665,7 +1665,7 @@ static MACHINE_CONFIG_START( coh700, namcos12_state )
MCFG_PSX_DMA_CHANNEL_READ( "maincpu", 5, psx_dma_read_delegate( FUNC( namcos12_state::namcos12_rom_read ), (namcos12_state *) owner ) ) MCFG_PSX_DMA_CHANNEL_READ( "maincpu", 5, psx_dma_read_delegate( FUNC( namcos12_state::namcos12_rom_read ), (namcos12_state *) owner ) )
MCFG_CPU_ADD("sub", H83002, 16737350) MCFG_CPU_ADD("sub", H83002, 16934400) // frequency based on research (superctr)
MCFG_CPU_PROGRAM_MAP(s12h8rwmap) MCFG_CPU_PROGRAM_MAP(s12h8rwmap)
MCFG_CPU_IO_MAP(s12h8iomap) MCFG_CPU_IO_MAP(s12h8iomap)
@ -1691,11 +1691,11 @@ static MACHINE_CONFIG_START( coh700, namcos12_state )
/* sound hardware */ /* sound hardware */
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_C352_ADD("c352", 29168000, 332) MCFG_C352_ADD("c352", 25401600, 288)
MCFG_SOUND_ROUTE(0, "rspeaker", 1.00) MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(1, "lspeaker", 1.00) MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
MCFG_SOUND_ROUTE(2, "rspeaker", 1.00) //MCFG_SOUND_ROUTE(2, "lspeaker", 1.00) // Second DAC not present.
MCFG_SOUND_ROUTE(3, "lspeaker", 1.00) //MCFG_SOUND_ROUTE(3, "rspeaker", 1.00)
MACHINE_CONFIG_END MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( ptblank2, coh700 ) static MACHINE_CONFIG_DERIVED( ptblank2, coh700 )

View File

@ -3781,10 +3781,10 @@ static MACHINE_CONFIG_START( namcos22, namcos22_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_C352_ADD("c352", SS22_MASTER_CLOCK/2, 288) MCFG_C352_ADD("c352", SS22_MASTER_CLOCK/2, 288)
MCFG_SOUND_ROUTE(0, "rspeaker", 1.00) MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(1, "lspeaker", 1.00) MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
MCFG_SOUND_ROUTE(2, "rspeaker", 1.00) MCFG_SOUND_ROUTE(2, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(3, "lspeaker", 1.00) MCFG_SOUND_ROUTE(3, "rspeaker", 1.00)
MACHINE_CONFIG_END MACHINE_CONFIG_END
@ -3840,10 +3840,10 @@ static MACHINE_CONFIG_START( namcos22s, namcos22_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_C352_ADD("c352", SS22_MASTER_CLOCK/2, 288) MCFG_C352_ADD("c352", SS22_MASTER_CLOCK/2, 288)
MCFG_SOUND_ROUTE(0, "rspeaker", 1.00) MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(1, "lspeaker", 1.00) MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
MCFG_SOUND_ROUTE(2, "rspeaker", 1.00) MCFG_SOUND_ROUTE(2, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(3, "lspeaker", 1.00) MCFG_SOUND_ROUTE(3, "rspeaker", 1.00)
MACHINE_CONFIG_END MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( alpine, namcos22s ) static MACHINE_CONFIG_DERIVED( alpine, namcos22s )

View File

@ -1267,10 +1267,17 @@ Notes:
#include "machine/namco_settings.h" #include "machine/namco_settings.h"
#define JVSCLOCK (XTAL_14_7456MHz) #define JVSCLOCK (XTAL_14_7456MHz)
#define H8CLOCK (16737350) /* from 2061 */
#define BUSCLOCK (16737350*2) /* 33MHz CPU bus clock / input */ //#define H8CLOCK (16737350) /* from 2061 */
#define C352CLOCK (25992000) /* measured at 25.992MHz from 2061 pin 9 */ //#define BUSCLOCK (16737350*2) /* 33MHz CPU bus clock / input */
#define C352DIV (296) //#define C352CLOCK (25401600) /* previously measured at 25.992MHz from 2061 pin 9 */
//#define C352DIV (296)
#define H8CLOCK (16934400) /* based on research (superctr) */
#define BUSCLOCK (16934400*2)
#define C352CLOCK (25401600)
#define C352DIV (288)
#define VSYNC1 (59.8824) #define VSYNC1 (59.8824)
#define VSYNC2 (59.915) #define VSYNC2 (59.915)
#define HSYNC (16666150) #define HSYNC (16666150)
@ -3587,10 +3594,10 @@ static MACHINE_CONFIG_START( gorgon, namcos23_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_C352_ADD("c352", C352CLOCK, C352DIV) MCFG_C352_ADD("c352", C352CLOCK, C352DIV)
MCFG_SOUND_ROUTE(0, "rspeaker", 1.00) MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(1, "lspeaker", 1.00) MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
MCFG_SOUND_ROUTE(2, "rspeaker", 1.00) MCFG_SOUND_ROUTE(2, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(3, "lspeaker", 1.00) MCFG_SOUND_ROUTE(3, "rspeaker", 1.00)
MACHINE_CONFIG_END MACHINE_CONFIG_END