struct OPL2 { int MonoStatusPort; int MonoDataPort; int LeftStatusPort; int LeftDataPort; int RightStatusPort; int RightDataPort; char Status; char TimerStatusBit1; char TimerFlag1; char TimerStatusBit2; char TimerFlag2; char InterruptBit; char InterruptFlag; char TimerResolution1; char TimerResolution2; int ActiveRegister; int RegisterControl; char ActiveChannel; char ActiveOperator; char IncomingMonoData; char IncomingLeftData; char IncomingRightData; char IncomingData; char StatusWriteDelay; char DataWriteDelay; char DelayCountdown; int MonoGridOffset; int MonoGridLimit; int StereoGridOffset; int StereoGridLimit; int WaveControl; char Wave; int TimerDataControl1; char TimerPreset1; int TimerDataControl2; char TimerPreset2; char TimerControl; char TimerState; char IRQResetBit; char IRQResetFlag; char TimerMaskBit1; char TimerMaskFlag1; char TimerMaskBit2; char TimerMaskFlag2; char TimerActiveBit1; char TimerActiveFlag1; char TimerActiveBit2; char TimerActiveFlag2; int SpeechSynthControl; char SpeechSynthBit; char SpeechSynthFlag; char SpeechSynth; int KeyboardSplitControl; char KeyboardSplitBit; char KeyboardSplitFlag; char KeyboardSplit; int FMControl; int FMLimit; char AmplitudeBit; char AmplitudeFlag; char Amplitude; char VibratoBit; char VibratoFlag; char Vibrato; char EGBit; char EGFlag; char EG; char KeyboardScaleBit; char KeyboardScaleFlag; char KeyboardScale; char FMMultipleBit; char FMMultiple; int VolumeControl; int VolumeLimit; char KeyScaleLevelBit; char KeyScaleLevel; char VolumeBit; char Volume; int AttackControl; int AttackLimit; char AttackBit; char Attack; char DecayBit; char Decay; int SustainControl; int SustainLimit; char SustainBit; char Sustain; char ReleaseBit; char Release; int FrequencyControl; int FrequencyLimit; int Frequency; int NoteCSharp; int NoteD; int NoteDSharp; int NoteE; int NoteF; int NoteFSharp; int NoteG; int NoteGSharp; int NoteA; int NoteASharp; int NoteB; int NoteC; int OctaveControl; int OctaveLimit; char OctaveBit; char Octave; char ChannelActiveBit; char ChannelActiveFlag; char FrequencyHighBit; int AMDepthControl; char AMDepthBit; char AMDepthFlag; int VibratoDepthControl; char VibratoDepthBit; char VibratoDepthFlag; int RhythmControl; char RhythmBit; char RhythmFlag; char BassDrumBit; char BassDrumFlag; char SnareDrumBit; char SnareDrumFlag; char TomTomBit; char TomTomFlag; char TopCymbalBit; char TopCymbalFlag; char HiHatBit; char HiHatFlag; int FeedbackControl; int FeedbackLimit; char FeedbackBit; char Feedback; char SynthAlgorithmBit; char SynthAlgorithmFlag; int WaveSelectControl; int WaveSelectLimit; char WaveSelect; char SineBit; char HalfSineBit; char AbsoluteSineBit; char PulseSineBit; int ControlLimit; int MonoControlLimit; int StereoControlLimit; }; OPL2 OPL2Key; OPL2Key.MonoStatusPort = 0x388h; OPL2Key.MonoDataPort = 0x389h; OPL2Key.LeftStatusPort = 0x220h; OPL2Key.LeftDataPort = 0x222h; OPL2Key.RightStatusPort = 0x221h; OPL2Key.RightDataPort = 0x223h; FMKey.TimerStatusBit1 = 64; FMKey.TimerStatusBit2 = 32; FMKey.InterruptBit = 128; OPL2Key.StatusWriteDelay = 6; OPL2Key.DataWriteDelay = 35; OPL2Key.WaveControl = 0x1h; OPL2Key.TimerDataControl1 = 0x2h; OPL2Key.TimerDataControl2 = 0x3h; OPL2Key.TimerControl = 0x4h; OPL2Key.IRQResetBit = 128; OPL2Key.TimerMaskBit1 = 64; OPL2Key.TimerMaskBit2 = 32; OPL2Key.TimerActiveBit1 = 1; OPL2Key.TimerActiveBit2 = 2; OPL2Key.SpeechSynthControl = 0x8h; OPL2Key.SpeechSynthBit = 128; OPL2Key.KeyboardSplitControl = 0x8h; OPL2Key.KeyboardSplitBit = 64; OPL2Key.FMControl = 0x20h; OPL2Key.FMLimit = 0x35h; OPL2Key.AmplitudeBit = 128; OPL2Key.VibratoBit = 64; OPL2Key.EGBit = 32; OPL2Key.KeyboardScaleBit = 16; OPL2Key.FMMultipleBit = 1; OPL3Key.VolumeControl = 0x40h; OPL2Key.VolumeLimit = 0x40h; OPL2Key.KeyScaleLevelControl = 0x40h; OPL2Key.KeyScaleLevelLimit = 0x55h; OPL2Key.KeyScaleLevelBit = 64; OPL2Key.VolumeBit = 1; OPL2Key.AttackControl = 0x60h; OPL2Key.AttackLimit = 0x75h; OPL2Key.AttackBit = 16; OPL2Key.SustainControl = 0x80h; OPL2Key.SustainLimit = 0x95h; OPL2Key.SustainBit = 1; OPL2Key.FrequencyControl = 0xA0h; OPL2Key.FrequencyLimit = 0xA8h; OPL2Key.NoteCSharp = 0x16Bh; OPL2Key.NoteD = 0x181h; OPL2Key.NoteDSharp = 0x198h; OPL2Key.NoteE = 0x1B0h; OPL2Key.NoteF = 0x1CAh; OPL2Key.NoteFSharp = 0x1E5h; OPL2Key.NoteG = 0x202h; OPL2Key.NoteGSharp = 0x220h; OPL2Key.NoteA = 0x241h; OPL2Key.NoteASharp = 0x263h; OPL2Key.NoteB = 0x287h; OPL2Key.NoteC = 0x2AEh; OPL2Key.OctaveControl = 0xB0h; OPL2Key.OctaveLimit = 0xB8h; OPL2Key.KeyOnBit = 32; OPL2Key.OctaveBit = 4; OPL2Key.FrequencyHighBit = 1; OPL2Key.AMDepthControl = 0xBDh; OPL2Key.AMDepthBit = 128; OPL2Key.VibratoDepthControl = 0xBDh; OPL2Key.VibratoDepthBit = 64; OPL2Key.RhythmControl = 0xBDh; OPL2Key.RhythmBit = 32; OPL2Key.BassDrumBit = 16; OPL2Key.SnareDrumBit = 8; OPL2Key.TomTomBit = 4; OPL2Key.TopCymbalBit = 2; OPL2Key.HiHatBit = 1; OPL2Key.FeedbackControl = 0xC0h; OPL2Key.FeedbackLimit = 0xC8h; OPL2Key.FeedbackBit = 2; OPL2Key.SynthAlgorithmBit = 1; OPL2Key.WaveSelectControl = 0xE0h; OPL2Key.WaveSelectLimit = 0xF5h; OPL2Key.ControlLimit = 0xF5h; int MonoControlGrid[OPL2Key.MonoControlLimit]; int StereoControlGrid[OPL2Key.StereoControlLimit]; struct OPL2Patch { char Op1AmplitudeFlag; char Op2AmplitudeFlag; char Op1VibratoFlag; char Op2VibratoFlag; char Op1EGFlag; char Op2EGFlag; char Op1KeyboardScaleFlag; char Op2KeyboardScaleFlag; char Op1FMMultiple; char Op2FMMultiple; char Op1WaveSelect; char Op2WaveSelect; char Op1Attack; char Op2Attack; char Op1Decay; char Op2Decay; char Op1Sustain; char Op2Sustain; char Op1Release; char Op2Release; } *OPL2Patch; struct OPL2Operator { char Index; char AmplitudeFlag; char VibratoFlag; char EGFlag; char KeyboardScaleFlag; char FMMultiple; char WaveSelect; char Attack; char Decay; char Sustain; char Release; } *OPL2Operator; struct OPL2Effect { char AmplitudeFlag; char VibratoFlag; char EGFlag; char KeyboardScaleFlag; char FMMultiple; char WaveSelect; } *OPL2Effect; struct OPL2Envelope { char Attack; char Decay; char Sustain; char Release; } *OPL2Envelope; struct Music { char Tempo; char Note32Duration; char VolumeStaff; char VolumeStaffLimit; int VolumeBarIndex; int VolumeBarLimit; int IncomingFrequency; int Frequency; char FrequencyStaffLimit; int FrequencyBarIndex; char FrequencyHalf1; char FrequencyHalf2; char FrequencyAuxillaryFlag; char IncomingNote; char Octave; char Note; int SongLimit; char StaffLimit; int BarIndex; int BarLimit; int NoteLimit; } *Music; function DetectOPL2 (OPL2 FMKey) { outp(FMKey.TimerControl, 0x6080h); FMKey.OPL2TestControl1 = inp(FMKey.MonoStatusPort); outp(FMKey.TimerData1, 0xFFh); outp(FMKey.TimerControl, 0x21h); for (FMCounter = 1; FMCounter <= FMKey.DataWriteDelay; FMCounter++) { FMKey.DelayCountdown = inp(FMKey.MonoStatusPort); } FMKey.OPL2TestControl2 = inp(FMKey.MonoStatusPort); outp(FMKey.TimerControl, 0x6080h); FMKey.AdlibTestControl1 = FMKey.OPL2TestControl1 && 0xE0h; FMKey.OPL2TestControl2 = FMKey.OPL2TestControl2 && 0xE0h; if (FMKey.OPL2TestControl1 == 0) { if (FMKey.OPL2TestControl2 == 0xC0h ) { FMKey.AdlibPresentFlag = 1; } } } function LoadOPL2Frequency (OPL2 FMKey, int OPL2Grid[]) { FMKey.RegisterControl = FMKey.FrequencyControl + FMKey.ActiveChannel; OPLGrid[FMKey.RegisterControl] = FMKey.Frequency && 256; FMKey.RegisterControl = FMKey.OctaveControl; FMKey.IncomingData = FMKey.KeyOnBit * FMKey.KeyOnFlag; FMKey.IncomingData = FMKey.IncomingData + (FMKey.OctaveBit * FMKey.Octave); FMKey.IncomingData = FMKey.FrequencyHighBit * INT(FMKey.Frequency / 256); FMKey.ActiveOperator = 1; LoadOPL2GridIndex (FMKey, OPL2Grid[]); } function LoadOPL2GridIndex (OPL2 FMKey, int OPL2Grid[]) { int GridIndex; GridIndex = 3 * FMKey.ActiveChannel / 3; GridIndex = GridIndex + (FMKey.ActiveOperator - 1) * 3; GridIndex = GridIndex + FMKey.RegisterControl + FMKey.ActiveChannel; OPL2Grid[GridIndex] = FMKey.IncomingData; } function LoadOPL2MonoRegister (OPL2 FMKey) { outp(FMKey.MonoStatusPort, FMKey.ActiveRegister); for (FMCounter = 1; FMCounter <= FMKey.StatusWriteDelay; FMCounter++) { FMKey.DelayCountdownCountdown = inp(FMKey.MonoStatusPort); } outp(FMKey.MonoDataPort, FMKey.IncomingMonoData); for (FMCounter = 1; FMCounter <= FMKey.DataWriteDelay; FMCounter++) { FMKey.DelayCountdownCountdown = inp(FMKey.MonoStatusPort); } } function LoadOPL2Operator (OPL2Operator Operator, OPL2 FMKey, int OPL2Grid[]) { FMKey.ActiveOperator = Operator.Index; FMKey.RegisterControl = FMKey.FMControl; FMKey.Amplitude = FMKey.AmplitudeBit * Operator.AmplitudeFlag; FMKey.AmplitudeFlag = Operator.AmplitudeFlag; FMKey.IncomingData = FMKey.Amplitude; FMKey.Vibrato = FMKey.VibratoBit * Operator.VibratoFlag; FMKey.VibratoFlag = Operator.VibratoFlag; FMKey.IncomingData = FMKey.IncomingData + FMKey.Vibrato; FMKey.EG = FMKey.EGBit * Operator.EGFlag; FMKey.EGFlag = Operator.EGFlag; FMKey.IncomingData = FMKey.IncomingData + FMKey.EGBit; FMKey.KeyboardScale = FMKey.KeyboardScaleBit * Operator.KeyboardScaleFlag; FMKey.KeyboardScaleFlag = Operator.KeyboardScaleFlag; FMKey.IncomingData = FMKey.IncomingData + FMKey.KeyboardScale; FMKey.FMMultiple = Operator.FMMultiple; FMKey.IncomingData = FMKey.IncomingData + FMKey.FMMultiple; LoadOPL2GridIndex (FMKey, OPL2Grid[]); FMKey.RegisterControl = FMKey.WaveSelectControl; FMKey.WaveSelect = Operator.WaveSelect; FMKey.IncomingData = FMKey.WaveSelect; LoadOPL2GridIndex (FMKey, OPL2Grid[]); FMKey.RegisterControl = FMKey.AttackControl; FMKey.Attack = Operator.Attack; FMKey.Decay = Operator.Decay; FMKey.IncomingData = FMKey.AttackBit * FMKey.Attack; FMKey.IncomingData = FMKey.IncomingData + FMKey.Decay; LoadOPL2GridIndex (FMKey, OPL2Grid[]); FMKey.RegisterControl = FMKey.SustainControl; FMKey.Sustain = Operator.Sustain; FMKey.Release = Operator.Release; FMKey.IncomingData = FMKey.SustainBit * FMKey.Sustain; FMKey.IncomingData = FMKey.IncomingData + FMKey.Release; LoadOPL2GridIndex (FMKey, OPL2Grid[]); } function LoadOPL2StereoRegister (OPL2 FMKey) { outp(FMKey.LeftStatusPort, FMKey.ActiveRegister); for (FMCounter = 1; FMCounter <= FMKey.StatusWriteDelay; FMCounter++) { FMKey.DelayCountdownCountdown = inp(FMKey.LeftStatusPort); } outp(FMKey.LeftDataPort, FMKey.IncomingLeftData); for (FMCounter = 1; FMCounter <= FMKey.DataWriteDelay; FMCounter++) { FMKey.DelayCountdown = inp(FMKey.LeftStatusPort); } outp(FMKey.RightStatusPort, FMKey.ActiveRegister); for (FMCounter = 1; FMCounter <= FMKey.StatusWriteDelay; FMCounter++) { FMKey.DelayCountdownCountdown = inp(FMKey.RightStatusPort); } outp(FMKey.RightDataPort, FMKey.IncomingRightData); for (FMCounter = 1; FMCounter <= FMKey.DataWriteDelay; FMCounter++) { FMKey.DelayCountdownCountdown = inp(FMKey.RightStatusPort); } } function LoadOPL2WaveEffect (OPL2 FMKey, OPL2Effect Effect, int OPL2Grid[]) { FMKey.RegisterControl = FMKey.FMControl; FMKey.Amplitude = FMKey.AmplitudeBit * Effect.AmplitudeFlag; FMKey.AmplitudeFlag = Effect.AmplitudeFlag; FMKey.IncomingData = FMKey.Amplitude; FMKey.Vibrato = FMKey.VibratoBit * Effect.VibratoFlag; FMKey.VibratoFlag = Effect.VibratoFlag; FMKey.IncomingData = FMKey.IncomingData + FMKey.Vibrato; FMKey.EG = FMKey.EGBit * Effect.EGFlag; FMKey.EGFlag = Effect.EGFlag; FMKey.IncomingData = FMKey.IncomingData + FMKey.EGBit; FMKey.KeyboardScale = FMKey.KeyboardScaleBit * Effect.KeyboardScaleFlag; FMKey.KeyboardScaleFlag = Effect.KeyboardScaleFlag; FMKey.IncomingData = FMKey.IncomingData + FMKey.KeyboardScale; FMKey.FMMultiple = Effect.FMMultiple; FMKey.IncomingData = FMKey.IncomingData + FMKey.FMMultiple; LoadOPL2GridIndex (FMKey, OPL2Grid[]); FMKey.RegisterControl = FMKey.WaveSelectControl; FMKey.WaveSelect = Effect.WaveSelect; FMKey.IncomingData = FMKey.WaveSelect; LoadOPL2GridIndex (FMKey, OPL2Grid[]); } function LoadOPL2WaveEnvelope (OPL2 FMKey, OPL2Envelope Envelope, OPL2Grid[]) { FMKey.RegisterControl = FMKey.AttackControl; FMKey.Attack = Envelope.Attack; FMKey.Decay = Envelope.Decay; FMKey.IncomingData = FMKey.AttackBit * FMKey.Attack; FMKey.IncomingData = FMKey.IncomingData + FMKey.Decay; LoadOPL2GridIndex (FMKey, OPL2Grid[]); FMKey.RegisterControl = FMKey.SustainControl; FMKey.Sustain = Operator.Sustain; FMKey.Release = Operator.Release; FMKey.IncomingData = FMKey.SustainBit * FMKey.Sustain; FMKey.IncomingData = FMKey.IncomingData + FMKey.Release; LoadOPL2GridIndex (FMKey, OPL2Grid[]); } function MonoLoadOPL2 (OPL2 FMKey, MonoGrid[]) { for (GridIndex = FMKey.MonoGridOffset; GridIndex <= FMKey.MonoGridLimit; GridIndex++) { FMKey.ActiveRegister = GridIndex; outp(FMKey.MonoStatusPort, FMKey.ActiveRegister); for (FMCounter = 1; FMCounter <= FMKey.StatusWriteDelay; FMCounter++) { FMKey.DelayCountdown = inp(FMKey.MonoStatusPort); } FMKey.IncomingMonoData = MonoGrid[FMKey.ActiveRegister]; outp(FMKey.MonoDataPort, FMKey.IncomingMonoData); for (FMCounter = 1; FMCounter <= FMKey.DataWriteDelay; FMCounter++) { FMKey.DelayCountdown = inp(FMKey.MonoStatusPort); } } } function OpenOPL2Operator (OPL2Operator Op, OPL2Effect Effect, OPL2Envelope Envelope) { Op.AmplitudeFlag = Effect.AmplitudeFlag; Op.VibratoFlag = Effect.VibratoFlag; Op.EGFlag = Effect.EGFlag; Op.KeyboardScaleFlag = Effect.KeyboardScaleFlag; Op.FMMultiple = Effect.FMMultiple; Op.WaveSelect = Effect.WaveSelect; Op.Attack = Envelope.Attack; Op.Decay = Envelope.Decay; Op.Sustain = Envelope.Sustain; Op.Release = Envelope.Release; } function OpenOPL2Patch (OPL2Patch Patch, OPL2Operator Op1, OPL2Operator Op2) { Patch.Op1AmplitudeFlag = Op1.AmplitudeFlag; Patch.Op2AmplitudeFlag = Op2.AmplitudeFlag; Patch.Op1VibratoFlag = Op1.VibratoFlag; Patch.Op2VibratoFlag = Op2.VibratoFlag; Patch.Op1EGFlag = Op1.EGFlag; Patch.Op2EGFlag = Op2.EGFlag; Patch.Op1KeyboardScaleFlag = Op1.KeyboardScaleFlag; Patch.Op2KeyboardScaleFlag = Op2.KeyboardScaleFlag; Patch.Op1FMMultiple = Op1.FMMultiple; Patch.Op2FMMultiple = Op2.FMMultiple; Patch.Op1WaveSelect = Op1.WaveSelect; Patch.Op2WaveSelect = Op2.WaveSelect; Patch.Op1Attack = Op1.Attack; Patch.Op2Attack = Op2.Attack; Patch.Op1Decay = Op1.Decay; Patch.Op2Decay = Op2.Decay; Patch.Op1Sustain = Op1.Sustain; Patch.Op2Sustain = Op2.Sustain; Patch.Op1Release = Op1.Release; Patch.Op2Release = Op2.Release; } function PlayOPL2MusicBar (Music Music, OPL2 FMKey, int OPLGrid[], char *Score, char *Frequency, char *Volume) { int FrequencyHalfIndex; if (FMKey.InterruptFlag == 1) { if (FMKey.TimerFlag2 == 1) { if (strlen(Volume) > 0) { Music.VolumeBarLimit = Music.VolumeStaffLimit + Music.VolumeBarIndex; for (VolumeIndex = 1; VolumeIndex <= Music.VolumeStaffLimit; VolumeIndex++) { FMKey.Volume = Volume[VolumeIndex]; FMKey.ActiveChannel = VolumeIndex; SetOPL2InstrumentVolume (FMKey, OPL2Grid[]); } } if (strlen(Frequency) > 0) { char Frequency1; char Frequency2; Music.FrequencyBarLimit = Music.FrequencyStaffLimit + Music.FrequencyBarIndex; for (FrequencyIndex = 1; FrequencyIndex <= Music.FrequencyStaffLimit; FrequencyIndex++) { Frequency1 = Frequency[Music.FrequencyBarIndex + FrequencyIndex]; Music.IncomingFrequency = Frequency1; Music.FrequencyHalf1 = 128 - Music.IncomingFrequency; FrequencyHalfIndex = Music.FrequencyBarLimit + FrequencyIndex; Frequency2 = Frequency[FrequencyBarIndex]; Music.FrequencyHalf2 = Frequency2; FMKey.Frequency = (Music.FrequencyHalf1 * 32) + Music.FrequencyHalf2; Music.FrequencyStaffLimit = Music.StaffLimit; if (Music.TimerFlag1 == 1) { ScoreSubject = strncpy(Score, 0, Music.BarIndex + FrequencyIndex - 1); ScorePredicate = strncpy(Score, Music.BarIndex + FrequencyIndex + 1); Score = strcpy(Score, ScoreSubject); Score = strcat(Score, Frequency1); Score = strcat(Score, ScorePredicate); ScoreSubject = strncpy(Score, 0, Music.BarIndex + FrequencyBarIndex - 1); ScorePredicate = strcpy(Score, Music.BarIndex + FrequencyBarIndex + 1); if (Music.FrequencyAuxillaryFlag == 1) { Score = strcpy(Score, ScoreSubject); Score = strcat(Score, Frequency2); Score = strcat(Score, ScorePredicate); } elseif (Music.FrequencyFlag == 0) { Score = strcpy(Score, ScoreSubject); for (FrequencyStaffIndex = 1; FrequencyStaffIndex <= (FrequencyIndex - 1); FrequencyStaffIndex++) { Score = strcat(Score, ""); } Score = strcat(Score, Frequency2); for (FrequencyStaffIndex = 1; FrequencyStaffIndex <= (Music.StaffLimit - FrequencyIndex); FrequencyStaffIndex++) { Score = strcat(Score, ""); } Score = strcat(Score, ScorePredicate); } Music.SongLimit = Music.SongLimit + Music.StaffLimit; Music.FrequencyAuxillaryFlag = 1; } FMKey.ActiveChannel = FrequencyIndex; LoadOPL2Frequency (FMKey, OPL2Grid[]); } Music.FrequencyAuxillaryFlag = 0; } } if (FMKey.TimerFlag1 == 1) { Music.BarLimit = Music.StaffLimit + Music.BarIndex; if (Music.SongLimit > Music.BarLimit) { Music.NoteLimit = Music.SongLimit - Music.BarLimit; Bar = strncpy(Score, Music.BarIndex, Music.StaffLimit); for (NoteIndex = 1; NoteIndex <= Music.NoteLimit; NoteIndex++) { Music.IncomingNote = Bar[NoteIndex]; if (Music.IncomingNote > 96) { Music.FrequencyHalf1 = 128 - Music.IncomingNote; FrequencyHalfIndex = Music.BarLimit + NoteIndex; Frequency = Score[FrequencyHalfIndex]; Music.FrequencyHalf2 = Frequency; FMKey.Frequency = (Music.FrequencyHalf1 * 32) + Music.FrequencyHalf2; } Music.Octave = Music.IncomingNote / 12; if (Music.Octave > 8) { Music.Octave = 0; } Music.Note = Music.IncomingNote - (Music.Octave * 12); if (Music.Note < 7) { if (Music.Note < 3) { if (Music.Note == 1) { FMKey.Frequency = FMKey.NoteCSharp; } elseif (Music.Note == 2) { FMKey.Frequency = FMKey.NoteD; } else { FMKey.Frequency = FMKey.NoteDSharp; } else { if (Music.Note == 3 ) { FMKey.Frequency = FMKey.NoteE; } elseif (Music.Note == 4) { FMKey.Frequency = FMKey.NoteF; } else { FMKey.Frequency = FMKey.NoteFSharp; } } elseif (Music.Note <= 12) { if (Music.Note < 9) { if (Music.Note = 7) { FMKey.Frequency = FMKey.NoteG; } elseif (Music.Note = 8) { FMKey.Frequency = FMKey.NoteGSharp; } else { FMKey.Frequency = FMKey.NoteA; } } else { if (Music.Note = 10) { FMKey.Frequency = FMKey.NoteASharp; } elseif (Music.Note = 11) { FMKey.Frequency = FMKey.NoteB; } else { FMKey.Frequency = FMKey.NoteC; } } } FMKey.Octave = Music.Octave; FMKey.ActiveChannel = NoteIndex; LoadOPL2Frequency (FMKey, OPL2Grid[]); } Music.BarIndex = Music.BarLimit; Music.BarIndex = Music.BarIndex + Music.StaffLimit; Music.BarIndex = Music.BarIndex + Music.FrequencyStaffLimit; } } FMKey.MonoGridOffset = FMKey.FrequencyControl; FMKey.MonoGridLimit = FMKey.FrequencyLimit; MonoLoadOPL2 (FMKey, OPLGrid[]); } } function RetreiveOPL2Status (OPL2 FMKey) { FMKey.Status = inp(FMKey.MonoStatusPort); FMKey.TimerFlag1 = FMKey.TimerStatusBit1 && FMKey.Status; FMKey.TimerFlag2 = FMKey.TimerStatusBit2 && FMKey.Status; FMKey.InterruptFlag = FMKey.InterruptBit && FMKey.Status; } function SetOPL2Tempo (OPLMusic Music, OPL2 FMKey) { Music.Note32Duration = (60 / Music.Tempo) * .125; FMKey.TimerPreset2 = Music.Note32Duration / FMKey.TimerResolution2; } function SetOPL2InstrumentVolume (OPL2 FMKey, char OPL2Grid[]) { FMKey.IncomingData = FMKey.KeyScaleRate * FMKey.KeyScaleBit; FMKey.IncomingData = FMKey.IncomingData + (FMKey.VolumeBit * FMKey.Volume); FMKey.RegisterControl = FMKey.VolumeControl; if (FMKey.SynthAlgorithmFlag == 1) { FMKey.ActiveOperator = 1; LoadOPL2GridIndex (FMKey, OPL2Grid[]); } else { FMKey.ActiveOperator = 1; LoadOPL2GridIndex (FMKey, OPL2Grid[]); FMKey.ActiveOperator = 2; LoadOPL2GridIndex (FMKey, OPL2Grid[]); } } function StereoLoadOPL2 (OPL2 FMKey, char StereoGrid[]) { for (GridIndex = FMKey.StereoGridOffset; GridIndex <= FMKey.StereoGridLimit; GridIndex++) { FMKey.ActiveRegister = GridIndex; outp(FMKey.LeftStatusPort, FMKey.ActiveRegister); for (FMCounter = 1; FMCounter <= FMKey.StatusWriteDelay; FMCounter++) { FMKey.DelayCountdown = inp(FMKey.LeftStatusPort); } FMKey.IncomingLeftData = StereoGrid[GridIndex]; outp(FMKey.LeftDataPort, FMKey.IncomingLeftData); for (FMCounter = 1; FMCounter <= FMKey.DataWriteDelay; FMCounter++) { FMKey.DelayCountdown = inp(FMKey.LeftStatusPort); } GridIndex = GridIndex + 1; FMKey.IncomingRightData = StereoGrid[GridIndex]; outp(FMKey.RightStatusPort, FMKey.ActiveRegister); for (FMCounter = 1; FMCounter <= FMKey.StatusWriteDelay; FMCounter++) { FMKey.DelayCountdown = inp(FMKey.RightStatusPort); } outp(FMKey.RightDataPort, FMKey.IncomingRightData); for (FMCounter = 1; FMCounter <= FMKey.DataWriteDelay; FMCounter++) { FMKey.DelayCountdown = inp(FMKey.RightStatusPort); } } }