public void c352_write_rom(byte ChipID, uint ROMSize, int DataStart, int DataLength, byte[] ROMData) { C352 c = C352Data[ChipID]; if (c.wavesize != ROMSize) { c.wave = new byte[ROMSize]; c.wavesize = ROMSize; for (c.wave_mask = 1; c.wave_mask < c.wavesize; c.wave_mask <<= 1) { ; } c.wave_mask--; for (int i = 0; i < ROMSize; i++) { c.wave[i] = 0xff; } } if (DataStart > ROMSize) { return; } if (DataStart + DataLength > ROMSize) { DataLength = (int)(ROMSize - DataStart); } for (int i = 0; i < DataLength; i++) { c.wave[i + DataStart] = ROMData[i]; } return; }
private void device_stop_c352(byte ChipID) { C352 c = C352Data[ChipID]; c.wave = null; return; }
private void c352_set_mute_mask(byte ChipID, uint MuteMask) { C352 c = C352Data[ChipID]; byte CurChn; for (CurChn = 0; CurChn < C352_VOICES; CurChn++) { c.v[CurChn].mute = (byte)((MuteMask >> CurChn) & 0x01); } return; }
private uint c352_get_mute_mask(byte ChipID) { C352 c = C352Data[ChipID]; uint muteMask; byte CurChn; muteMask = 0x00000000; for (CurChn = 0; CurChn < C352_VOICES; CurChn++) { muteMask |= (uint)((c.v[CurChn].mute << CurChn)); } return(muteMask); }
// private static ushort[] C352RegMap = new ushort[8]{ // offsetof(C352_Voice,vol_f) / sizeof(ushort), // offsetof(C352_Voice,vol_r) / sizeof(ushort), // offsetof(C352_Voice,freq) / sizeof(ushort), // offsetof(C352_Voice,flags) / sizeof(ushort), // offsetof(C352_Voice,wave_bank) / sizeof(ushort), // offsetof(C352_Voice,wave_start) / sizeof(ushort), // offsetof(C352_Voice,wave_end) / sizeof(ushort), // offsetof(C352_Voice,wave_loop) / sizeof(ushort), //}; private ushort c352_r(byte ChipID, int address) { C352 c = C352Data[ChipID]; if (address < 0x100) { int ch = address / 8; switch (address % 8) { case 0: return(c.v[ch].vol_f); case 1: return(c.v[ch].vol_r); case 2: return(c.v[ch].freq); case 3: return(c.v[ch].flags); case 4: return(c.v[ch].wave_bank); case 5: return(c.v[ch].wave_start); case 6: return(c.v[ch].wave_end); case 7: return(c.v[ch].wave_loop); } } else if (address == 0x200) { return(c.control); } else { return(0); } return(0); }
private void device_reset_c352(byte ChipID) { C352 c = C352Data[ChipID]; uint muteMask; muteMask = c352_get_mute_mask(ChipID); // clear all channels states c.v = new C352_Voice[C352_VOICES]; for (int i = 0; i < C352_VOICES; i++) { c.v[i] = new C352_Voice(); } // init noise generator c.random = 0x1234; c.control = 0; c352_set_mute_mask(ChipID, muteMask); return; }
public void c352_write_rom2(byte ChipID, uint ROMSize, int DataStart, int DataLength, byte[] ROMData, uint SrcStartAdr) { //Console.WriteLine("ROMSize={0:x} , DataStart={1:x} , DataLength={2:x}", ROMSize, DataStart, DataLength); C352 c = C352Data[ChipID]; if (c.wavesize != ROMSize) { c.wave = new byte[ROMSize]; c.wavesize = ROMSize; for (c.wave_mask = 1; c.wave_mask < c.wavesize; c.wave_mask <<= 1) { ; } c.wave_mask--; for (int i = 0; i < ROMSize; i++) { c.wave[i] = 0xff; } } if (DataStart > ROMSize) { return; } if (DataStart + DataLength > ROMSize) { DataLength = (int)(ROMSize - DataStart); } for (int i = 0; i < DataLength; i++) { c.wave[i + DataStart] = ROMData[i + SrcStartAdr]; } return; }
private void c352_w(byte ChipID, int address, ushort val) { //Console.WriteLine("address = {0} val = {1}", address, val); C352 c = C352Data[ChipID]; int i; if (address < 0x100) // Channel registers, see map above. { int ch = address / 8; switch (address % 8) { case 0: c.v[ch].vol_f = val; break; case 1: c.v[ch].vol_r = val; break; case 2: c.v[ch].freq = val; //Console.WriteLine("c.v[ch{0}].freq = {1}", ch, val); break; case 3: c.v[ch].flags = val; break; case 4: c.v[ch].wave_bank = val; break; case 5: c.v[ch].wave_start = val; break; case 6: c.v[ch].wave_end = val; break; case 7: c.v[ch].wave_loop = val; break; } } else if (address == 0x200) { c.control = val; //logerror("C352 control register write: %04x\n",val); } else if (address == 0x202) // execute keyons/keyoffs { for (i = 0; i < C352_VOICES; i++) { //if ((c.v[i].flags & C352_FLG_KEYON)) if ((c.v[i].flags & 0x4000) != 0) { c.v[i].pos = (uint)((c.v[i].wave_bank << 16) | c.v[i].wave_start); c.v[i].sample = 0; c.v[i].last_sample = 0; c.v[i].counter = 0xffff; //c.v[i].flags |= C352_FLG.BUSY; c.v[i].flags |= 0x8000; //c.v[i].flags &= ~(C352_FLG_KEYON | C352_FLG_LOOPHIST); c.v[i].flags &= 0xb7ff; c.v[i].curr_vol[0] = c.v[i].curr_vol[1] = 0; c.v[i].curr_vol[2] = c.v[i].curr_vol[3] = 0; } //else if (c.v[i].flags & C352_FLG.KEYOFF) else if ((c.v[i].flags & 0x2000) != 0) { //c.v[i].flags &= ~(C352_FLG.BUSY | C352_FLG.KEYOFF); c.v[i].flags &= 0x5fff; c.v[i].counter = 0xffff; } } } }
private void c352_update(byte ChipID, int[][] outputs, int samples) { C352 c = C352Data[ChipID]; int i, j; short s; int next_counter; C352_Voice v; int[] _out = new int[4]; //short[] _out = new short[4]; for (i = 0; i < samples; i++) { outputs[0][i] = 0; outputs[1][i] = 0; } for (i = 0; i < samples; i++) { _out[0] = _out[1] = _out[2] = _out[3] = 0; for (j = 0; j < C352_VOICES; j++) { v = c.v[j]; s = 0; flags[ChipID][j] = v.flags; //Console.WriteLine(" v.flags={0}", v.flags); //if (v.flags & C352_FLG_BUSY) if ((v.flags & 0x8000) != 0) { next_counter = (int)(v.counter + v.freq); if ((next_counter & 0x10000) != 0) { C352_fetch_sample(c, v); //Console.WriteLine("fetch"); //Console.WriteLine(" ch={0} 0={1} 1={2} 2={3} 3={4}",j, _out[0], _out[1], _out[2], _out[3]); } if (((next_counter ^ v.counter) & 0x18000) != 0) { c352_ramp_volume(v, 0, (byte)(v.vol_f >> 8)); c352_ramp_volume(v, 1, (byte)(v.vol_f & 0xff)); c352_ramp_volume(v, 2, (byte)(v.vol_r >> 8)); c352_ramp_volume(v, 3, (byte)(v.vol_r & 0xff)); } v.counter = (uint)(next_counter & 0xffff); //Console.WriteLine(" v.freq={0}", v.freq); //Console.WriteLine(" v.counter={0}", v.counter); s = v.sample; // Interpolate samples //if ((v.flags & C352_FLG_FILTER) == 0) if ((v.flags & 0x0004) == 0) { s = (short)(v.last_sample + (v.counter * (v.sample - v.last_sample) >> 16)); } } if (c.v[j].mute == 0) { // Left //_out[0] += (((v.flags & C352_FLG_PHASEFL) ? -s : s) * v.curr_vol[0]) >> 8; //_out[2] += (((v.flags & C352_FLG_PHASEFR) ? -s : s) * v.curr_vol[2]) >> 8; _out[0] += ((((v.flags & 0x0100) != 0 ? -s : s) * v.curr_vol[0]) >> 9); _out[2] += ((((v.flags & 0x0080) != 0 ? -s : s) * v.curr_vol[2]) >> 9); // Right //_out[1] += (((v.flags & C352_FLG_PHASERL) ? -s : s) * v.curr_vol[1]) >> 8; //_out[3] += (((v.flags & C352_FLG_PHASERL) ? -s : s) * v.curr_vol[3]) >> 8; _out[1] += ((((v.flags & 0x0200) != 0 ? -s : s) * v.curr_vol[1]) >> 9); _out[3] += ((((v.flags & 0x0200) != 0 ? -s : s) * v.curr_vol[3]) >> 9); } //Console.WriteLine("out [0]={0} [1]={1} [2]={2} [3]={3}", _out[0] , _out[1] , _out[2] , _out[3]); } outputs[0][i] += _out[0]; outputs[1][i] += _out[1]; if (c.muteRear == 0 && MuteAllRear == 0) { outputs[0][i] += _out[2]; outputs[1][i] += _out[3]; } } }
private static void C352_fetch_sample(C352 c, C352_Voice v) { //Console.WriteLine("v->sample = {0} v->pos = {1} c->wave_mask = {2} v->flags ={3} ", v.sample, v.pos, c.wave_mask, v.flags); v.last_sample = v.sample; //if (v.flags & C352_FLG_NOISE) if ((v.flags & 0x0010) != 0) { c.random = (ushort)((c.random >> 1) ^ ((-(c.random & 1)) & 0xfff6)); v.sample = (short)c.random; } else { sbyte s, s2; ushort pos; s = (sbyte)c.wave[v.pos & c.wave_mask]; v.sample = (short)(s << 8); //if (v.flags & C352_FLG_MULAW) if ((v.flags & 0x0008) != 0) { s2 = (sbyte)((s & 0x7f) >> 4); v.sample = (short)(((s2 * s2) << 4) - (~(s2 << 1)) * (s & 0x0f)); v.sample = (short)(((s & 0x80) != 0) ? ((~v.sample) << 5) : (v.sample << 5)); } pos = (ushort)(v.pos & 0xffff); //if ((v.flags & C352_FLG_LOOP) && v.flags & C352_FLG_REVERSE) if ((v.flags & 0x0002) != 0 && (v.flags & 0x0001) != 0) { // backwards>forwards //if ((v.flags & C352_FLG_LDIR) && pos == v.wave_loop) if ((v.flags & 0x0040) != 0 && pos == v.wave_loop) { //v.flags &= ~C352_FLG_LDIR; v.flags &= 0xffbf; } // forwards>backwards //else if (!(v.flags & C352_FLG_LDIR) && pos == v.wave_end) else if ((v.flags & 0x0040) == 0 && pos == v.wave_end) { //v.flags |= C352_FLG_LDIR; v.flags |= 0x0040; } //v.pos += (v.flags & C352_FLG_LDIR) ? -1 : 1; v.pos = (uint)(v.pos + ((v.flags & 0x0040) != 0 ? -1 : 1)); } else if (pos == v.wave_end) { //if ((v.flags & C352_FLG_LINK) && (v.flags & C352_FLG_LOOP)) if ((v.flags & 0x0020) != 0 && (v.flags & 0x0002) != 0) { v.pos = (uint)((v.wave_start << 16) | v.wave_loop); //v.flags |= C352_FLG_LOOPHIST; v.flags |= 0x0800; } //else if (v.flags & C352_FLG_LOOP) else if ((v.flags & 0x0002) != 0) { v.pos = (v.pos & 0xff0000) | v.wave_loop; //v.flags |= C352_FLG_LOOPHIST; v.flags |= 0x0800; } else { //v.flags |= C352_FLG_KEYOFF; v.flags |= 0x2000; //v.flags &= ~C352_FLG_BUSY; v.flags &= 0x7fff; v.sample = 0; } } else { //v.pos += (v.flags & C352_FLG_REVERSE) ? -1 : 1; v.pos = (uint)(v.pos + ((v.flags & 0x0001) != 0 ? -1 : 1)); } } }