/************************************************/ /* RF5C68 write register */ /************************************************/ //WRITE8_DEVICE_HANDLER( rf5c68_w ) public void rf5c68_w(byte ChipID, int offset, byte data) { //rf5c68_state *chip = get_safe_token(device); rf5c68_state chip = RF5C68Data[ChipID]; pcm_channel chan = chip.chan[chip.cbank]; int i; /* force the stream to update first */ //stream_update(chip.stream); /* switch off the address */ switch (offset) { case 0x00: /* envelope */ chan.env = data; break; case 0x01: /* pan */ chan.pan = data; break; case 0x02: /* FDL */ chan.step = (UInt16)((chan.step & 0xff00) | (data & 0x00ff)); break; case 0x03: /* FDH */ chan.step = (UInt16)((chan.step & 0x00ff) | ((data << 8) & 0xff00)); break; case 0x04: /* LSL */ chan.loopst = (UInt16)((chan.loopst & 0xff00) | (data & 0x00ff)); break; case 0x05: /* LSH */ chan.loopst = (UInt16)((chan.loopst & 0x00ff) | ((data << 8) & 0xff00)); break; case 0x06: /* ST */ chan.start = data; if (chan.enable == 0) { chan.addr = (uint)(chan.start << (8 + 11)); } break; case 0x07: /* control reg */ chip.enable = (byte)((data >> 7) & 1); if ((data & 0x40) != 0) { chip.cbank = (byte)(data & 7); } else { chip.wbank = (byte)(data & 15); } break; case 0x08: /* channel on/off reg */ for (i = 0; i < 8; i++) { byte old = chip.chan[i].enable; chip.chan[i].enable = (byte)((~data >> i) & 1); if (old == 0 && chip.chan[i].enable != 0) { chip.chan[i].keyOn = true; } if (chip.chan[i].enable == 0) { chip.chan[i].addr = (uint)(chip.chan[i].start << (8 + 11)); } } break; } }
//static STREAM_UPDATE( rf5c68_update ) private void rf5c68_update(byte ChipID, int[][] outputs, int samples) { //rf5c68_state *chip = (rf5c68_state *)param; rf5c68_state chip = RF5C68Data[ChipID]; mem_stream ms = chip.memstrm; int[] left = outputs[0]; int[] right = outputs[1]; int i, j; /* start with clean buffers */ for (int ind = 0; ind < samples; ind++) { left[ind] = 0; right[ind] = 0; } /* bail if not enabled */ if (chip.enable == 0) { return; } /* loop over channels */ for (i = 0; i < NUM_CHANNELS; i++) { pcm_channel chan = chip.chan[i]; /* if this channel is active, accumulate samples */ if (chan.enable != 0)// && chan.Muted == 0) { int lv = (chan.pan & 0x0f) * chan.env; int rv = ((chan.pan >> 4) & 0x0f) * chan.env; /* loop over the sample buffer */ for (j = 0; j < samples; j++) { int sample; /* trigger sample callback */ /*if(chip.sample_callback) * { * if(((chan.addr >> 11) & 0xfff) == 0xfff) * chip.sample_callback(chip.device,((chan.addr >> 11)/0x2000)); * }*/ memstream_sample_check(chip, (chan.addr >> 11) & 0xFFFF, chan.step); /* fetch the sample and handle looping */ sample = chip.data[(chan.addr >> 11) & 0xffff]; if (sample == 0xff) { chan.addr = (uint)(chan.loopst << 11); sample = chip.data[(chan.addr >> 11) & 0xffff]; /* if we loop to a loop point, we're effectively dead */ if (sample == 0xff) { chan.key = false; break; } } chan.key = true; chan.addr += chan.step; if (chan.Muted == 0) { /* add to the buffer */ if ((sample & 0x80) != 0) { sample &= 0x7f; left[j] += (sample * lv) >> 5; right[j] += (sample * rv) >> 5; } else { left[j] -= (sample * lv) >> 5; right[j] -= (sample * rv) >> 5; } } //Console.WriteLine("Ch:{0} L:{1} R:{2}", i, outputs[0][j], outputs[1][j]); } } } if (samples != 0 && ms.CurAddr < ms.EndAddr) { ms.CurStep += (UInt16)(STEAM_STEP * samples); if (ms.CurStep >= 0x0800) // 1 << 11 { i = ms.CurStep >> 11; ms.CurStep &= 0x07FF; if (ms.CurAddr + i > ms.EndAddr) { i = (int)(ms.EndAddr - ms.CurAddr); } //memcpy(chip.data + ms.CurAddr, ms.MemPnt + (ms.CurAddr - ms.BaseAddr), i); Array.Copy(ms.MemPnt, (ms.CurAddr - ms.BaseAddr), chip.data, ms.CurAddr, i); ms.CurAddr += (uint)i; } } // I think, this is completely useless /* now clamp and shift the result (output is only 10 bits) */ /*for (j = 0; j < samples; j++) * { * stream_sample_t temp; * * temp = left[j]; * if (temp > 32767) temp = 32767; * else if (temp < -32768) temp = -32768; * left[j] = temp & ~0x3f; * * temp = right[j]; * if (temp > 32767) temp = 32767; * else if (temp < -32768) temp = -32768; * right[j] = temp & ~0x3f; * }*/ }