static void K054539_update(int chip, INT16 **buffer, int length) { static INT16 dpcm[16] = { 0<<8, 1<<8, 4<<8, 9<<8, 16<<8, 25<<8, 36<<8, 49<<8, -64<<8, -49<<8, -36<<8, -25<<8, -16<<8, -9<<8, -4<<8, -1<<8 }; int ch; unsigned char *samples; UINT32 rom_mask; if(!Machine->sample_rate) return; memset(buffer[0], 0, length*2); memset(buffer[1], 0, length*2); if(!(K054539_chips.chip[chip].regs[0x22f] & 1)) return; samples = K054539_chips.chip[chip].rom; rom_mask = K054539_chips.chip[chip].rom_mask; for(ch=0; ch<8; ch++) if(K054539_chips.chip[chip].regs[0x22c] & (1<<ch)) { unsigned char *base1 = K054539_chips.chip[chip].regs + 0x20*ch; unsigned char *base2 = K054539_chips.chip[chip].regs + 0x200 + 0x2*ch; struct K054539_channel *chan = (struct K054539_channel*)K054539_chips.chip[chip].channels + ch; INT16 *bufl = buffer[0]; INT16 *bufr = buffer[1]; UINT32 cur_pos = (base1[0x0c] | (base1[0x0d] << 8) | (base1[0x0e] << 16)) & rom_mask; INT32 cur_pfrac; INT32 cur_val, cur_pval, rval; INT32 delta = (base1[0x00] | (base1[0x01] << 8) | (base1[0x02] << 16)) * K054539_chips.freq_ratio; INT32 fdelta; int pdelta; int pan = base1[0x05] >= 0x11 && base1[0x05] <= 0x1f ? base1[0x05] - 0x11 : 0x18 - 0x11; int vol = base1[0x03] & 0x7f; double lvol = K054539_chips.voltab[vol] * K054539_chips.pantab[pan]; double rvol = K054539_chips.voltab[vol] * K054539_chips.pantab[0xe - pan]; if(base2[0] & 0x20) { delta = -delta; fdelta = +0x10000; pdelta = -1; } else { fdelta = -0x10000; pdelta = +1; } if(cur_pos != chan->pos) { chan->pos = cur_pos; cur_pfrac = 0; cur_val = 0; cur_pval = 0; } else { cur_pfrac = chan->pfrac; cur_val = chan->val; cur_pval = chan->pval; } #define UPDATE_CHANNELS \ do { \ rval = (cur_pval*cur_pfrac + cur_val*(0x10000 - cur_pfrac)) >> 16; \ *bufl++ += (INT16)(rval*lvol); \ *bufr++ += (INT16)(rval*rvol); \ } while(0) switch(base2[0] & 0xc) { case 0x0: { // 8bit pcm int i; for(i=0; i<length; i++) { cur_pfrac += delta; while(cur_pfrac & ~0xffff) { cur_pfrac += fdelta; cur_pos += pdelta; cur_pval = cur_val; cur_val = (INT16)(samples[cur_pos] << 8); if(cur_val == (INT16)0x8000) { if(base2[1] & 1) { cur_pos = (base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask; cur_val = (INT16)(samples[cur_pos] << 8); if(cur_val != (INT16)0x8000) continue; } K054539_keyoff(chip, ch); goto end_channel_0; } } UPDATE_CHANNELS; } end_channel_0: break; } case 0x4: { // 16bit pcm lsb first int i; cur_pos >>= 1; for(i=0; i<length; i++) { cur_pfrac += delta; while(cur_pfrac & ~0xffff) { cur_pfrac += fdelta; cur_pos += pdelta; cur_pval = cur_val; cur_val = (INT16)(samples[cur_pos<<1] | samples[(cur_pos<<1)|1]<<8); if(cur_val == (INT16)0x8000) { if(base2[1] & 1) { cur_pos = ((base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask) >> 1; cur_val = (INT16)(samples[cur_pos<<1] | samples[(cur_pos<<1)|1]<<8); if(cur_val != (INT16)0x8000) continue; } K054539_keyoff(chip, ch); goto end_channel_4; } } UPDATE_CHANNELS; } end_channel_4: cur_pos <<= 1; break; } case 0x8: { // 4bit dpcm int i; cur_pos <<= 1; cur_pfrac <<= 1; if(cur_pfrac & 0x10000) { cur_pfrac &= 0xffff; cur_pos |= 1; } for(i=0; i<length; i++) { cur_pfrac += delta; while(cur_pfrac & ~0xffff) { cur_pfrac += fdelta; cur_pos += pdelta; cur_pval = cur_val; cur_val = samples[cur_pos>>1]; if(cur_val == 0x88) { if(base2[1] & 1) { cur_pos = ((base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask) << 1; cur_val = samples[cur_pos>>1]; if(cur_val != 0x88) goto next_iter; } K054539_keyoff(chip, ch); goto end_channel_8; } next_iter: if(cur_pos & 1) cur_val >>= 4; else cur_val &= 15; cur_val = cur_pval + dpcm[cur_val]; if(cur_val < -32768) cur_val = -32768; else if(cur_val > 32767) cur_val = 32767; } UPDATE_CHANNELS; }
static void K054539_update(void *param, stream_sample_t **inputs, stream_sample_t **buffer, int length) { struct k054539_info *info = param; #define VOL_CAP 1.80 static INT16 dpcm[16] = { 0<<8, 1<<8, 4<<8, 9<<8, 16<<8, 25<<8, 36<<8, 49<<8, -64<<8, -49<<8, -36<<8, -25<<8, -16<<8, -9<<8, -4<<8, -1<<8 }; int ch, reverb_pos; short *rev_max; short *rbase, *rbuffer, *rev_top; unsigned char *samples; UINT32 rom_mask; unsigned char *base1, *base2; struct K054539_channel *chan; stream_sample_t *bufl, *bufr; short *revb; int cur_pos, cur_pfrac, cur_val, cur_pval; int delta, rdelta, fdelta, pdelta; int vol, bval, pan, i; double gain, lvol, rvol, rbvol; reverb_pos = info->reverb_pos; rbase = (short *)(info->ram); rbuffer = rbase + reverb_pos; rev_max = rev_top = rbase + 0x4000; memset(buffer[0], 0, length*sizeof(*buffer[0])); memset(buffer[1], 0, length*sizeof(*buffer[1])); samples = info->rom; rom_mask = info->rom_mask; if(!(info->regs[0x22f] & 1)) return; info->reverb_pos = (reverb_pos + length) & 0x3fff; for(ch=0; ch<8; ch++) if(info->regs[0x22c] & (1<<ch)) { base1 = info->regs + 0x20*ch; base2 = info->regs + 0x200 + 0x2*ch; chan = info->channels + ch; /** */ delta = info->freq_ratio * (base1[0x00] | (base1[0x01] << 8) | (base1[0x02] << 16)); vol = base1[0x03]; bval = vol + base1[0x04]; if (bval > 255) bval = 255; 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 pan = 0x18 - 0x11; gain = info->K054539_gain[ch]; lvol = info->voltab[vol] * info->pantab[pan] * gain; if (lvol > VOL_CAP) lvol = VOL_CAP; rvol = info->voltab[vol] * info->pantab[0xe - pan] * gain; if (rvol > VOL_CAP) rvol = VOL_CAP; rbvol= info->voltab[bval] * gain / 2; if (rbvol > VOL_CAP) rbvol = VOL_CAP; /* INT x FLOAT could be interpreted as INT x (int)FLOAT instead of (float)INT x FLOAT on some compilers causing precision loss. (rdelta - 0x2000) wraps around on zero reverb and the scale factor should actually be 1/freq_ratio because the target is an offset to the reverb buffer not sample source. */ rdelta = (base1[6] | (base1[7] << 8)) >> 3; /* rdelta = (reverb_pos + (int)((rdelta - 0x2000) * info->freq_ratio)) & 0x3fff; */ rdelta = (int)((double)rdelta / info->freq_ratio + reverb_pos) & 0x3fff; revb = rbase + rdelta; cur_pos = (base1[0x0c] | (base1[0x0d] << 8) | (base1[0x0e] << 16)) & rom_mask; bufl = buffer[0]; bufr = buffer[1]; /** */ if(base2[0] & 0x20) { delta = -delta; fdelta = +0x10000; pdelta = -1; } else { fdelta = -0x10000; pdelta = +1; } if(cur_pos != chan->pos) { chan->pos = cur_pos; cur_pfrac = 0; cur_val = 0; cur_pval = 0; } else { cur_pfrac = chan->pfrac; cur_val = chan->val; cur_pval = chan->pval; } #define UPDATE_CHANNELS \ do { \ *bufl++ += (INT16)(cur_val*lvol); \ *bufr++ += (INT16)(cur_val*rvol); \ *revb++ += (INT16)(cur_val*rbvol); \ } while(0) switch(base2[0] & 0xc) { case 0x0: { /* 8bit pcm */ for(i=0; i<length; i++) { cur_pfrac += delta; while(cur_pfrac & ~0xffff) { cur_pfrac += fdelta; cur_pos += pdelta; cur_pval = cur_val; cur_val = (INT16)(samples[cur_pos] << 8); if(cur_val == (INT16)0x8000) { if(base2[1] & 1) { cur_pos = (base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask; cur_val = (INT16)(samples[cur_pos] << 8); if(cur_val != (INT16)0x8000) continue; } K054539_keyoff(info, ch); goto end_channel_0; } } UPDATE_CHANNELS; } end_channel_0: break; } case 0x4: { /* 16bit pcm lsb first */ pdelta <<= 1; for(i=0; i<length; i++) { cur_pfrac += delta; while(cur_pfrac & ~0xffff) { cur_pfrac += fdelta; cur_pos += pdelta; cur_pval = cur_val; cur_val = (INT16)(samples[cur_pos] | samples[cur_pos+1]<<8); if(cur_val == (INT16)0x8000) { if(base2[1] & 1) { cur_pos = (base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask; cur_val = (INT16)(samples[cur_pos] | samples[cur_pos+1]<<8); if(cur_val != (INT16)0x8000) continue; } K054539_keyoff(info, ch); goto end_channel_4; } } UPDATE_CHANNELS; } end_channel_4: break; } case 0x8: { /* 4bit dpcm */ cur_pos <<= 1; cur_pfrac <<= 1; if(cur_pfrac & 0x10000) { cur_pfrac &= 0xffff; cur_pos |= 1; } for(i=0; i<length; i++) { cur_pfrac += delta; while(cur_pfrac & ~0xffff) { cur_pfrac += fdelta; cur_pos += pdelta; cur_pval = cur_val; cur_val = samples[cur_pos>>1]; if(cur_val == 0x88) { if(base2[1] & 1) { cur_pos = ((base1[0x08] | (base1[0x09] << 8) | (base1[0x0a] << 16)) & rom_mask) << 1; cur_val = samples[cur_pos>>1]; if(cur_val != 0x88) goto next_iter; } K054539_keyoff(info, ch); goto end_channel_8; } next_iter: if(cur_pos & 1) cur_val >>= 4; else cur_val &= 15; cur_val = cur_pval + dpcm[cur_val]; if(cur_val < -32768) cur_val = -32768; else if(cur_val > 32767) cur_val = 32767; } UPDATE_CHANNELS; } end_channel_8: cur_pfrac >>= 1; if(cur_pos & 1) cur_pfrac |= 0x8000; cur_pos >>= 1; break; }