private void Ym2612WriteData(byte address, int op, int slot, byte data) { switch (op) { case 0: op = 0; break; case 1: op = 2; break; case 2: op = 1; break; case 3: op = 3; break; } uint yreg = (uint)(0 / 3) * 2; comPortOPNA2?.DeferredWriteData(0, (byte)((1 + (yreg + 0)) * 4), (byte)(address + (op * 4) + (slot % 3)), (int)Settings.Default.BitBangWaitOPNA2); comPortOPNA2?.DeferredWriteData(0, (byte)((1 + (yreg + 1)) * 4), data, (int)Settings.Default.BitBangWaitOPNA2); }
protected override void StopAllSounds(bool volumeOff) { if (comPortDCSG != null) { comPortDCSG.ClearDeferredWriteData(); switch (comPortDCSG?.SoundModuleType) { case VsifSoundModuleType.Genesis: case VsifSoundModuleType.Genesis_Low: case VsifSoundModuleType.Genesis_FTDI: for (int i = 0; i < 3; i++) { comPortDCSG.WriteData(0, 0x14, (byte)(0x80 | i << 5 | 0x1f), (int)Settings.Default.BitBangWaitDCSG); } comPortDCSG.WriteData(0, 0x14, (byte)(0x80 | 3 << 5 | 0x1f), (int)Settings.Default.BitBangWaitDCSG); break; case VsifSoundModuleType.SMS: for (int i = 0; i < 3; i++) { comPortDCSG.WriteData(0, 0xFF, (byte)(0x80 | i << 5 | 0x1f), (int)Settings.Default.BitBangWaitOPNA2); } comPortDCSG.WriteData(0, 0xFF, (byte)(0x80 | 3 << 5 | 0x1f), (int)Settings.Default.BitBangWaitOPNA2); break; } comPortDCSG.FlushDeferredWriteData(); } if (comPortOPNA2 != null) { comPortOPNA2.ClearDeferredWriteData(); for (int i = 0; i < 3; i++) { comPortOPNA2.DeferredWriteData(0, 4, (byte)(0xB4 | i), (int)Settings.Default.BitBangWaitOPNA2); comPortOPNA2.DeferredWriteData(0, 8, 0xC0, (int)Settings.Default.BitBangWaitOPNA2); comPortOPNA2.DeferredWriteData(0, 12, (byte)(0xB4 | i), (int)Settings.Default.BitBangWaitOPNA2); comPortOPNA2.DeferredWriteData(0, 16, 0xC0, (int)Settings.Default.BitBangWaitOPNA2); } // disable LFO comPortOPNA2.DeferredWriteData(0, 4, 0x22, (int)Settings.Default.BitBangWaitOPNA2); comPortOPNA2.DeferredWriteData(0, 8, 0x00, (int)Settings.Default.BitBangWaitOPNA2); // disable timer & set channel 6 to normal mode comPortOPNA2.DeferredWriteData(0, 4, 0x27, (int)Settings.Default.BitBangWaitOPNA2); comPortOPNA2.DeferredWriteData(0, 8, 0x00, (int)Settings.Default.BitBangWaitOPNA2); // ALL KEY OFF comPortOPNA2.DeferredWriteData(0, 4, 0x28, (int)Settings.Default.BitBangWaitOPNA2); for (int i = 0; i < 3; i++) { comPortOPNA2.DeferredWriteData(0, 8, (byte)(0x00 | i), (int)Settings.Default.BitBangWaitOPNA2); comPortOPNA2.DeferredWriteData(0, 8, (byte)(0x04 | i), (int)Settings.Default.BitBangWaitOPNA2); } // disable DAC comPortOPNA2.DeferredWriteData(0, 4, 0x2B, (int)Settings.Default.BitBangWaitOPNA2); comPortOPNA2.DeferredWriteData(0, 8, 0x00, (int)Settings.Default.BitBangWaitOPNA2); for (int slot = 0; slot < 6; slot++) { uint reg = (uint)(slot / 3) * 2; Ym2612WriteData(0x28, 0, 0, (byte)(0x00 | (reg << 1) | (byte)(slot % 3))); //TL if (volumeOff) { for (int op = 0; op < 4; op++) { Ym2612WriteData(0x40, op, slot, 127); } } } //if (volumeOff) // for (int slot = 0; slot < 6; slot++) // for (int op = 0; op < 4; op++) // Ym2612WriteData(0x80, op, slot, 0x0ff); comPortOPNA2.FlushDeferredWriteData(); } Thread.Sleep(50); }
protected override void StreamSong() { xgmReader.BaseStream?.Seek(0, SeekOrigin.Begin); double wait = 0; double xgmWaitDelta = 0; double streamWaitDelta = 0; double lastDiff = 0; using (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, false, null)) { long freq, before, after; QueryPerformanceFrequency(out freq); SampleData[] currentPlaySamples = new SampleData[4]; while (true) { QueryPerformanceCounter(out before); if (State == SoundState.Stopped) { break; } else if (State == SoundState.Paused) { Thread.Sleep(1); continue; } try { if (xgmWaitDelta <= 0) { int command = readByte(); if (command != -1) { switch (command) { case int cmd when 0x0 <= cmd && cmd <= 0x0F: { switch (xgmMHead.bytNTSC_PAL & 1) { case 0: xgmWaitDelta += 735; break; case 1: xgmWaitDelta += 882; break; } flushDeferredWriteData(); break; } case int cmd when 0x10 <= cmd && cmd <= 0x1F: { int size = cmd & 0xf; for (int i = 0; i <= size; i++) { var data = readByte(); if (data < 0) { break; } switch (comPortDCSG?.SoundModuleType) { case VsifSoundModuleType.Genesis: case VsifSoundModuleType.Genesis_Low: case VsifSoundModuleType.Genesis_FTDI: comPortDCSG?.DeferredWriteData(0, 0x14, (byte)data, (int)Settings.Default.BitBangWaitOPNA2); break; case VsifSoundModuleType.SMS: comPortDCSG?.DeferredWriteData(0, 0xFF, (byte)data, (int)Settings.Default.BitBangWaitOPNA2); break; } } } break; case int cmd when 0x20 <= cmd && cmd <= 0x2F: //YM2612 Write Port 0 { int size = cmd & 0xf; for (int i = 0; i <= size; i++) { var data = readByte(); if (data < 0) { break; } comPortOPNA2?.DeferredWriteData(0, 0x04, (byte)data, (int)Settings.Default.BitBangWaitOPNA2); data = readByte(); if (data < 0) { break; } comPortOPNA2?.DeferredWriteData(0, 0x08, (byte)data, (int)Settings.Default.BitBangWaitOPNA2); } } break; case int cmd when 0x30 <= cmd && cmd <= 0x3F: //YM2612 Write Port 1 { int size = cmd & 0xf; for (int i = 0; i <= size; i++) { var data = readByte(); if (data < 0) { break; } comPortOPNA2?.DeferredWriteData(0, 0x0C, (byte)data, (int)Settings.Default.BitBangWaitOPNA2); data = readByte(); if (data < 0) { break; } comPortOPNA2?.DeferredWriteData(0, 0x10, (byte)data, (int)Settings.Default.BitBangWaitOPNA2); } } break; case int cmd when 0x40 <= cmd && cmd <= 0x4F: //YM2612 Write Port 0 { int size = cmd & 0xf; for (int i = 0; i <= size; i++) { var data = readByte(); if (data < 0) { break; } comPortOPNA2?.DeferredWriteData(0, 0x04, 0x28, (int)Settings.Default.BitBangWaitOPNA2); comPortOPNA2?.DeferredWriteData(0, 0x08, (byte)data, (int)Settings.Default.BitBangWaitOPNA2); } } break; case int cmd when 0x50 <= cmd && cmd <= 0x5F: //Play PCM { int ch = cmd & 0x3; var id = readByte(); if (id < 0) { break; } if (id == 0) { currentPlaySamples[ch] = null; } else { currentPlaySamples[ch] = SampleDataTable[id - 1]; currentPlaySamples[ch].Restart(); } } break; case 0x7E: flushDeferredWriteData(); uint ofst = xgmReader.ReadUInt32(); if (ofst < 0) { xgmReader.BaseStream?.Seek(0, SeekOrigin.Begin); } else { xgmReader.BaseStream?.Seek((int)ofst, SeekOrigin.Begin); } break; case 0x7F: flushDeferredWriteData(); //End of song xgmReader.BaseStream?.Seek(0, SeekOrigin.Begin); break; } } if ((command == 0x7E || command == 0x7F || command == -1)) { flushDeferredWriteData(); if (Looped == false || LoopCount == 0) { State = SoundState.Stopped; NotifyFinished(); break; } LoopCount--; } } if (streamWaitDelta <= 0) { short dacData = 0; bool playDac = false; for (int i = 0; i < currentPlaySamples.Length; i++) { var dt = currentPlaySamples[i]?.GetDacData(); if (dt != null) { dacData += (short)dt.Value; playDac = true; } } if (playDac) { if (dacData > sbyte.MaxValue) { dacData = sbyte.MaxValue; } else if (dacData < sbyte.MinValue) { dacData = sbyte.MinValue; } dacData += 0x80; comPortOPNA2?.DeferredWriteData(0, 0x04, (byte)0x2a, (int)Settings.Default.BitBangWaitOPNA2); comPortOPNA2?.DeferredWriteData(0, 0x08, (byte)dacData, (int)Settings.Default.BitBangWaitOPNA2); streamWaitDelta += 44.1d / 14d; } } } catch (Exception ex) { if (ex.GetType() == typeof(Exception)) { throw; } else if (ex.GetType() == typeof(SystemException)) { throw; } flushDeferredWriteData(); if (Looped == false || LoopCount == 0) { State = SoundState.Stopped; NotifyFinished(); break; } LoopCount--; xgmReader.BaseStream?.Seek(0, SeekOrigin.Begin); } if (streamWaitDelta < xgmWaitDelta) { if (streamWaitDelta <= 0) { wait += xgmWaitDelta; xgmWaitDelta = 0; } else { wait += streamWaitDelta; xgmWaitDelta -= streamWaitDelta; streamWaitDelta = 0; } } else { if (xgmWaitDelta <= 0) { wait += streamWaitDelta; streamWaitDelta = 0; } else { wait += xgmWaitDelta; streamWaitDelta -= xgmWaitDelta; xgmWaitDelta = 0; } } if (wait <= (double)Settings.Default.VGMWait) { continue; } flushDeferredWriteData(); QueryPerformanceCounter(out after); double pwait = (wait / PlaybackSpeed); if (((double)(after - before) / freq) > (pwait / (44.1 * 1000))) { lastDiff = ((double)(after - before) / freq) - (pwait / (44.1 * 1000)); wait = -(lastDiff * 44.1 * 1000); NotifyProcessLoadOccurred(); } else { while (((double)(after - before) / freq) <= (pwait / (44.1 * 1000))) { QueryPerformanceCounter(out after); } wait = 0; HighLoad = false; } } } }