private void rf5c68_mem_stream_flush(rf5c68_state chip) { mem_stream ms = chip.memstrm; if (ms.CurAddr >= ms.EndAddr) { return; } //memcpy(chip.data + ms.CurAddr, ms.MemPnt + (ms.CurAddr - ms.BaseAddr), ms.EndAddr - ms.CurAddr); Array.Copy(ms.MemPnt, (ms.CurAddr - ms.BaseAddr), chip.data, ms.CurAddr, ms.EndAddr - ms.CurAddr); ms.CurAddr = ms.EndAddr; return; }
public void rf5c68_write_ram2(byte ChipID, int DataStart, int DataLength, byte[] RAMData, uint SrcStartAdr) { rf5c68_state chip = RF5C68Data[ChipID]; mem_stream ms = chip.memstrm; UInt16 BytCnt; DataStart |= chip.wbank * 0x1000; if (DataStart >= chip.datasize) { return; } if (DataStart + DataLength > chip.datasize) { DataLength = (int)(chip.datasize - DataStart); } //memcpy(chip.data + DataStart, RAMData, DataLength); rf5c68_mem_stream_flush(chip); ms.BaseAddr = (uint)DataStart; ms.CurAddr = ms.BaseAddr; ms.EndAddr = (uint)(ms.BaseAddr + DataLength); ms.CurStep = 0x0000; byte[] dat = new byte[DataLength]; for (int ind = 0; ind < DataLength; ind++) { dat[ind] = RAMData[SrcStartAdr + ind]; } ms.MemPnt = dat; //BytCnt = (STEAM_STEP * 32) >> 11; BytCnt = 0x40; // SegaSonic Arcade: Run! Run! Run! needs such a high value if (ms.CurAddr + BytCnt > ms.EndAddr) { BytCnt = (UInt16)(ms.EndAddr - ms.CurAddr); } //memcpy(chip.data + ms.CurAddr, ms.MemPnt + (ms.CurAddr - ms.BaseAddr), BytCnt); Array.Copy(ms.MemPnt, (ms.CurAddr - ms.BaseAddr), chip.data, ms.CurAddr, BytCnt); ms.CurAddr += BytCnt; return; }
/*INLINE rf5c68_state *get_safe_token(const device_config *device) * { * assert(device != NULL); * assert(device->token != NULL); * assert(device->type == SOUND); * assert(sound_get_type(device) == SOUND_RF5C68); * return (rf5c68_state *)device->token; * }*/ /************************************************/ /* RF5C68 stream update */ /************************************************/ private void memstream_sample_check(rf5c68_state chip, UInt32 addr, UInt16 Speed) { mem_stream ms = chip.memstrm; UInt32 SmplSpd; SmplSpd = (uint)((Speed >= 0x0800) ? (Speed >> 11) : 1); if (addr >= ms.CurAddr) { // Is the stream too fast? (e.g. about to catch up the output) if (addr - ms.CurAddr <= SmplSpd * 5) { // Yes - delay the stream ms.CurAddr -= SmplSpd * 4; if (ms.CurAddr < ms.BaseAddr) { ms.CurAddr = ms.BaseAddr; } } } else { // Is the stream too slow? (e.g. the output is about to catch up the stream) if (ms.CurAddr - addr <= SmplSpd * 5) { if (ms.CurAddr + SmplSpd * 4 >= ms.EndAddr) { rf5c68_mem_stream_flush(chip); } else { //memcpy(chip.data + ms.CurAddr, ms.MemPnt + (ms.CurAddr - ms.BaseAddr), SmplSpd * 4); Array.Copy(ms.MemPnt, (ms.CurAddr - ms.BaseAddr), chip.data, ms.CurAddr, SmplSpd * 4); ms.CurAddr += SmplSpd * 4; } } } return; }
private void device_reset_rf5c68(byte ChipID) { rf5c68_state chip = RF5C68Data[ChipID]; int i; pcm_channel chan; mem_stream ms = chip.memstrm; // Clear the PCM memory. //memset(chip.data, 0x00, chip.datasize); for (int ind = 0; ind < chip.datasize; ind++) { chip.data[ind] = 0; } chip.enable = 0; chip.cbank = 0; chip.wbank = 0; /* clear channel registers */ for (i = 0; i < NUM_CHANNELS; i++) { chan = chip.chan[i]; chan.enable = 0; chan.env = 0; chan.pan = 0; chan.start = 0; chan.addr = 0; chan.step = 0; chan.loopst = 0; } ms.BaseAddr = 0x0000; ms.CurAddr = 0x0000; ms.EndAddr = 0x0000; ms.CurStep = 0x0000; ms.MemPnt = null; }
//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; * }*/ }