k054539: Uncross the streams [O. Galibert]

This commit is contained in:
Olivier Galibert 2012-03-05 18:28:03 +00:00
parent 4e3ac4fb9d
commit 347ff9bce4

View File

@ -69,11 +69,7 @@ void k054539_device::static_set_interface(device_t &device, const k054539_interf
22f: enable pcm (b0), disable register ram updating (b7)
The chip has a 0x4000 bytes reverb buffer (the ram from 0x22e).
The reverb delay is actually an offset in this buffer. This driver
uses some tricks (doubling the buffer size so that the longest
reverbs don't fold over the sound to output, and adding a space at
the end to fold back overflows in) to be able to do frame-based
rendering instead of sample-based.
The reverb delay is actually an offset in this buffer.
*/
void k054539_device::init_flags(int _flags)
@ -115,15 +111,18 @@ void k054539_device::sound_stream_update(sound_stream &stream, stream_sample_t *
};
int cur_reverb_pos = reverb_pos;
INT16 *rbase = (INT16 *)ram;
memset(outputs[0], 0, samples*sizeof(*outputs[0]));
memset(outputs[1], 0, samples*sizeof(*outputs[1]));
if(!(regs[0x22f] & 1))
return;
if(!(regs[0x22f] & 1)) return;
reverb_pos = (reverb_pos + samples) & 0x3fff;
for(int sample = 0; sample != samples; sample++) {
double lval, rval;
if(!(flags & DISABLE_REVERB))
lval = rval = rbase[reverb_pos];
else
lval = rval = 0;
rbase[reverb_pos] = 0;
for(int ch=0; ch<8; ch++)
if(regs[0x22c] & (1<<ch)) {
@ -136,34 +135,37 @@ void k054539_device::sound_stream_update(sound_stream &stream, stream_sample_t *
int vol = base1[0x03];
int bval = vol + base1[0x04];
if (bval > 255) bval = 255;
if (bval > 255)
bval = 255;
int pan = base1[0x05];
// DJ Main: 81-87 right, 88 middle, 89-8f left
if (pan >= 0x81 && pan <= 0x8f)
pan -= 0x81;
else if (pan >= 0x11 && pan <= 0x1f)
pan -= 0x11;
else
if (pan >= 0x11 && pan <= 0x1f) pan -= 0x11; else pan = 0x18 - 0x11;
pan = 0x18 - 0x11;
double cur_gain = gain[ch];
double lvol = voltab[vol] * pantab[pan] * cur_gain;
if (lvol > VOL_CAP) lvol = VOL_CAP;
if (lvol > VOL_CAP)
lvol = VOL_CAP;
double rvol = voltab[vol] * pantab[0xe - pan] * cur_gain;
if (rvol > VOL_CAP) rvol = VOL_CAP;
if (rvol > VOL_CAP)
rvol = VOL_CAP;
double rbvol= voltab[bval] * cur_gain / 2;
if (rbvol > VOL_CAP) rbvol = VOL_CAP;
if (rbvol > VOL_CAP)
rbvol = VOL_CAP;
int rdelta = (base1[6] | (base1[7] << 8)) >> 3;
rdelta = (rdelta + cur_reverb_pos) & 0x3fff;
rdelta = (rdelta + reverb_pos) & 0x3fff;
int cur_pos = (base1[0x0c] | (base1[0x0d] << 8) | (base1[0x0e] << 16)) & rom_mask;
stream_sample_t *bufl = outputs[0];
stream_sample_t *bufr = outputs[1];
int fdelta, pdelta;
if(base2[0] & 0x20) {
delta = -delta;
@ -186,17 +188,8 @@ void k054539_device::sound_stream_update(sound_stream &stream, stream_sample_t *
cur_pval = chan->pval;
}
#define UPDATE_CHANNELS \
do { \
*bufl++ += (INT16)(cur_val*lvol); \
*bufr++ += (INT16)(cur_val*rvol); \
rbase[rdelta++] += (INT16)(cur_val*rbvol); \
rdelta &= 0x3fff; \
} while(0)
switch(base2[0] & 0xc) {
case 0x0: { // 8bit pcm
for(int i=0; i<samples; i++) {
cur_pfrac += delta;
while(cur_pfrac & ~0xffff) {
cur_pfrac += fdelta;
@ -204,27 +197,22 @@ void k054539_device::sound_stream_update(sound_stream &stream, stream_sample_t *
cur_pval = cur_val;
cur_val = (INT16)(rom[cur_pos] << 8);
if(cur_val == (INT16)0x8000) {
if(base2[1] & 1) {
if(cur_val == (INT16)0x8000 && (base2[1] & 1)) {
cur_pos = (base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask;
cur_val = (INT16)(rom[cur_pos] << 8);
if(cur_val != (INT16)0x8000)
continue;
}
if(cur_val == (INT16)0x8000) {
keyoff(ch);
goto end_channel_0;
}
}
UPDATE_CHANNELS;
}
end_channel_0:
cur_val = 0;
break;
}
}
break;
}
case 0x4: { // 16bit pcm lsb first
pdelta <<= 1;
for(int i=0; i<samples; i++) {
cur_pfrac += delta;
while(cur_pfrac & ~0xffff) {
cur_pfrac += fdelta;
@ -232,23 +220,19 @@ void k054539_device::sound_stream_update(sound_stream &stream, stream_sample_t *
cur_pval = cur_val;
cur_val = (INT16)(rom[cur_pos] | rom[cur_pos+1]<<8);
if(cur_val == (INT16)0x8000) {
if(base2[1] & 1) {
if(cur_val == (INT16)0x8000 && (base2[1] & 1)) {
cur_pos = (base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask;
cur_val = (INT16)(rom[cur_pos] | rom[cur_pos+1]<<8);
if(cur_val != (INT16)0x8000)
continue;
}
if(cur_val == (INT16)0x8000) {
keyoff(ch);
goto end_channel_4;
}
}
UPDATE_CHANNELS;
}
end_channel_4:
cur_val = 0;
break;
}
}
break;
}
case 0x8: { // 4bit dpcm
cur_pos <<= 1;
cur_pfrac <<= 1;
@ -257,7 +241,6 @@ void k054539_device::sound_stream_update(sound_stream &stream, stream_sample_t *
cur_pos |= 1;
}
for(int i=0; i<samples; i++) {
cur_pfrac += delta;
while(cur_pfrac & ~0xffff) {
cur_pfrac += fdelta;
@ -265,17 +248,15 @@ void k054539_device::sound_stream_update(sound_stream &stream, stream_sample_t *
cur_pval = cur_val;
cur_val = rom[cur_pos>>1];
if(cur_val == 0x88) {
if(base2[1] & 1) {
if(cur_val == 0x88 && (base2[1] & 1)) {
cur_pos = ((base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask) << 1;
cur_val = rom[cur_pos>>1];
if(cur_val != 0x88)
goto next_iter;
}
if(cur_val == 0x88) {
keyoff(ch);
goto end_channel_8;
cur_val = 0;
break;
}
next_iter:
if(cur_pos & 1)
cur_val >>= 4;
else
@ -287,9 +268,6 @@ void k054539_device::sound_stream_update(sound_stream &stream, stream_sample_t *
cur_val = 32767;
}
UPDATE_CHANNELS;
}
end_channel_8:
cur_pfrac >>= 1;
if(cur_pos & 1)
cur_pfrac |= 0x8000;
@ -300,35 +278,27 @@ void k054539_device::sound_stream_update(sound_stream &stream, stream_sample_t *
LOG(("Unknown sample type %x for channel %d\n", base2[0] & 0xc, ch));
break;
}
lval += cur_val * lvol;
rval += cur_val * rvol;
rbase[(rdelta + reverb_pos) & 0x1fff] += INT16(cur_val*rbvol);
chan->pos = cur_pos;
chan->pfrac = cur_pfrac;
chan->pval = cur_pval;
chan->val = cur_val;
if(regupdate()) {
base1[0x0c] = cur_pos & 0xff;
base1[0x0d] = cur_pos>> 8 & 0xff;
base1[0x0e] = cur_pos>>16 & 0xff;
}
}
//* drivers should be given the option to disable reverb when things go terribly wrong
if(!(flags & DISABLE_REVERB))
{
for(int i=0; i<samples; i++) {
INT16 val = rbase[(i+reverb_pos) & 0x3fff];
outputs[0][i] += val;
outputs[1][i] += val;
reverb_pos = (reverb_pos + 1) & 0x1fff;
outputs[0][sample] = INT16(lval);
outputs[1][sample] = INT16(rval);
}
}
if(cur_reverb_pos + samples > 0x4000) {
int i = 0x4000 - cur_reverb_pos;
memset(rbase + cur_reverb_pos, 0, i*2);
memset(rbase, 0, (samples-i)*2);
} else
memset(rbase + cur_reverb_pos, 0, samples*2);
}
void k054539_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
@ -342,11 +312,10 @@ void k054539_device::init_chip()
memset(posreg_latch, 0, sizeof(posreg_latch)); //*
flags |= UPDATE_AT_KEYON; //* make it default until proven otherwise
// Real size of 0x4000, the addon is to simplify the reverb buffer computations
ram = auto_alloc_array(machine(), unsigned char, 0x4000*2+clock()/50*2);
ram = auto_alloc_array(machine(), unsigned char, 0x4000);
reverb_pos = 0;
cur_ptr = 0;
memset(ram, 0, 0x4000*2+clock()/50*2);
memset(ram, 0, 0x4000);
const memory_region *reg = (rgnoverride != NULL) ? machine().region(rgnoverride) : region();
rom = *reg;