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]; int i,j;
stream_sample_t *bufferr = outputs[1]; short s;
stream_sample_t *bufferl2 = outputs[2]; stream_sample_t *buffer_fl = outputs[0];
stream_sample_t *bufferr2 = outputs[3]; stream_sample_t *buffer_fr = outputs[1];
stream_sample_t *buffer_rl = outputs[2];
for(i = 0 ; i < samples ; i++) 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;
for (j = 0 ; j < 32 ; j++) if(v->counter > 0x10000)
{ {
mix_one_channel(j, samples); v->counter &= 0xffff;
} fetch_sample(v);
}
for(i = 0 ; i < samples ; i++) s = v->sample;
{
*bufferl++ = (short) (m_channel_l[i] >>3); // Interpolate samples
*bufferr++ = (short) (m_channel_r[i] >>3); if((v->flags & C352_FLG_FILTER) == 0)
*bufferl2++ = (short) (m_channel_l2[i] >>3); s = v->last_sample + (v->counter*(v->sample-v->last_sample)>>16);
*bufferr2++ = (short) (m_channel_r2[i] >>3); }
// 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);
} }
} }
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; //printf("voice %d : pos= %08x\n",i,m_c352_v[i].pos);
break; }
else if(m_c352_v[i].flags & C352_FLG_KEYOFF)
case 0x6: {
// flags m_c352_v[i].flags &= ~(C352_FLG_BUSY|C352_FLG_KEYOFF);
LOG(("CH %02ld FLAG %02x\n", chan, val)); }
m_c352_ch[chan].flag = val; }
break; }
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__
@ -66,44 +66,38 @@ private:
C352_FLG_LOOP = 0x0002, // loop forward C352_FLG_LOOP = 0x0002, // loop forward
C352_FLG_REVERSE = 0x0001 // play sample backwards C352_FLG_REVERSE = 0x0001 // play sample backwards
}; };
struct c352_voice_t {
struct c352_ch_t unsigned int pos;
{ unsigned int counter;
UINT8 vol_l;
UINT8 vol_r; short sample;
UINT8 vol_l2; short last_sample;
UINT8 vol_r2;
UINT8 bank; unsigned short vol_f;
INT16 noise; unsigned short vol_r;
INT16 noisebuf; unsigned short freq;
UINT16 noisecnt; unsigned short flags;
UINT16 pitch;
UINT16 start_addr; unsigned short wave_bank;
UINT16 end_addr; unsigned short wave_start;
UINT16 repeat_addr; unsigned short wave_end;
UINT32 flag; 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;
unsigned short m_random;
unsigned short m_control; // control flags, purpose unknown.
void fetch_sample(c352_voice_t* v);
// private functions
int get_mseq_bit(void);
void mix_one_channel(unsigned long ch, long sample_count);
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