{ I got FM-synth code for the PAS (originally for the SB). Here it is: } Program fmtest; uses sbfm, crt; const instrument: TFMInstrument = (SoundCharacteristic: ($11, $1); Level: ($8A, $40); AttackDecay: ($F0, $F0); SustainRelease: ($FF, $B3); WaveSelect: ($01, $00); FeedBack: $00; Filler: ($06, $00, $00, $00, $00, $00)); notes: array[0..12] of integer = ($157, $16B, $181, $198, $1B0, $1C1, $1E5, $202, $220, $241, $263, $287, $2AE); begin SbFMReset; SbFMSetVoice(0,@instrument); SbFMSetVoice(1,@instrument); SbFMSetVoice(11,@instrument); SbFMSetVoice(12,@instrument); SbFMKeyOn(0,notes[0],2); delay(250); SbFMKeyOn(1,notes[4],3); delay(250); SbFMKeyOn(1,notes[7],3); delay(250); SbFMKeyOn(1,notes[12],3); delay(1000); sbFMKeyOff(0); sbFMKeyOff(1); sbFMKeyOff(11); sbFMKeyOff(12); sbFMReset; end. Unit SbFM; interface type PFMInstrument = ^TFMInstrument; TFMInstrument = record SoundCharacteristic:array[0..1] of byte; Level: array[0..1] of byte; AttackDecay: array[0..1] of byte; SustainRelease: array[0..1] of byte; WaveSelect: array[0..1] of byte; Feedback: byte; filler: array[0..5] of byte; end; const SbIOAddr=$220; LeftFmAddress=0; RightFmAddress=2; FMADDRESS=$08; Procedure WriteFM(chip, addr, data: byte); Procedure SbFmReset; Procedure SbFMKeyOff(voice: integer); Procedure SbFMKeyOn(voice, freq, octave: integer); Procedure SbFMVoiceVolume(voice, vol: integer); procedure sbFMSetVoice(voicenum: integer; Ins: PFMInstrument); implementation Procedure WriteFM(chip, addr, data: byte); var ChipAddr: integer; t: byte; begin if chip>0 then chipaddr:=SbIOAddr + RightFMAddress else chipaddr:=sbIOAddr + LeftFMAddress; chipaddr:=SbIOAddr + FMAddress; asm push dx push ax push cx mov dx,chipaddr mov al,addr out dx,al in al,dx inc dx mov al,data out dx,al dec dx mov cx,4 @L: in al,dx loop @L pop cx pop ax pop dx end; end; Procedure SbFmReset; Begin WriteFM(0, 1, 0); WriteFM(1, 1, 0); end; Procedure SbFMKeyOff(voice: integer); var regnum: byte; chip: integer; begin chip:=voice div 11; regnum:=$B0 + (voice mod 11); WriteFM(chip, regnum, 0); end; Procedure SbFMKeyOn(voice, freq, octave: integer); var regnum, t: byte; chip: integer; begin chip:=voice div 11; regnum:=$A0 + (voice mod 11); WriteFM(chip, regnum, freq and $FF); regnum:=$B0 + (voice mod 11); t:=(freq shr 8) or (octave shl 2) or $20; WriteFM(chip, regnum, t); end; Procedure SbFMVoiceVolume(voice, vol: integer); var regnum: byte; chip: integer; begin chip:=voice div 11; regnum:=$40 + (voice mod 11); WriteFM(chip, regnum, vol); end; procedure sbFMSetVoice(voicenum: integer; Ins: PFMInstrument); var opcellnum: byte; celloffset, i, chip: integer; begin chip:=voicenum div 11; voicenum:=voicenum mod 11; celloffset:=(voicenum mod 3) + ((voicenum div 3) shr 3); opcellnum:=$20 + celloffset; WriteFM(chip, opcellnum, ins^.SoundCharacteristic[0]); inc(opcellnum, 3); WriteFM(chip, opcellnum, ins^.SoundCharacteristic[1]); opcellnum:=$40 + celloffset; WriteFM(chip, opcellnum, ins^.level[0]); inc(opcellnum, 3); WriteFM(chip, opcellnum, ins^.Level[1]); opcellnum:=$60 + celloffset; WriteFM(chip, opcellnum, ins^.AttackDecay[0]); inc(opcellnum, 3); WriteFM(chip, opcellnum, ins^.AttackDecay[1]); opcellnum:=$80 + celloffset; WriteFM(chip, opcellnum, ins^.SustainRelease[0]); inc(opcellnum, 3); WriteFM(chip, opcellnum, ins^.SustainRelease[1]); opcellnum:=$E0 + celloffset; WriteFM(chip, opcellnum, ins^.WaveSelect[0]); inc(opcellnum, 3); WriteFM(chip, opcellnum, ins^.WaveSelect[1]); opcellnum:=$C0 + voicenum; WriteFM(chip, opcellnum, ins^.feedback); end; end. { Message 1 is FMTEST.PAS Messages 2+3 are SBFM.PAS That's all. One thing: if you can make this work with more than two voices at a time, I'd be interested in improved code. I think that this code uses the AdLib compatibility, which is by no means impressive :-). }