home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 17 / CD_ASCQ_17_101194.iso / dos / prg / geutsrce / digital.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-08-05  |  18.4 KB  |  917 lines

  1. UNIT Digital;
  2.  
  3.  
  4. INTERFACE
  5.  
  6.  
  7. USES Crt,Y360x480;
  8.  
  9.  
  10. CONST
  11.  UseXMS:BOOLEAN=True;
  12.  XMSError:Byte =0;
  13.  SpkrBaseTable:ARRAY[0..255] OF BYTE =
  14.         ($40,$40,$40,$40,$40,$40,$40,$40,$40,$40,$3F,$3F,$3F,$3F,$3F,$3F,
  15.          $3F,$3F,$3F,$3F,$3F,$3F,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,
  16.          $3D,$3D,$3D,$3D,$3D,$3D,$3D,$3D,$3D,$3C,$3C,$3C,$3C,$3C,$3C,$3C,
  17.          $3C,$3C,$3C,$3B,$3B,$3B,$3B,$3B,$3B,$3B,$3B,$3B,$3B,$3A,$3A,$3A,
  18.          $3A,$3A,$3A,$3A,$3A,$3A,$3A,$39,$39,$39,$39,$39,$39,$39,$39,$39,
  19.          $39,$38,$38,$38,$38,$38,$38,$38,$38,$37,$37,$37,$37,$37,$36,$36,
  20.          $36,$36,$35,$35,$35,$35,$34,$34,$34,$33,$33,$32,$32,$31,$31,$30,
  21.          $30,$2F,$2E,$2D,$2C,$2B,$2A,$29,$28,$27,$26,$25,$24,$23,$22,$21,
  22.          $20,$1F,$1E,$1D,$1C,$1B,$1A,$19,$18,$17,$16,$15,$14,$13,$12,$11,
  23.          $11,$10,$10,$0F,$0F,$0E,$0E,$0D,$0D,$0D,$0C,$0C,$0C,$0C,$0B,$0B,
  24.          $0B,$0B,$0A,$0A,$0A,$0A,$0A,$09,$09,$09,$09,$09,$09,$09,$09,$09,
  25.          $08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$08,$07,$07,$07,$07,
  26.          $07,$07,$07,$06,$06,$06,$06,$06,$06,$06,$06,$06,$06,$06,$05,$05,
  27.          $05,$05,$05,$05,$05,$05,$05,$05,$04,$04,$04,$04,$04,$04,$04,$04,
  28.          $04,$04,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$02,$02,$02,$02,
  29.          $02,$02,$02,$02,$02,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01);
  30.  
  31.  
  32. TYPE
  33.  BufferType=ARRAY[0..0] OF BYTE;
  34.  BufPointer=^BufferType;
  35.  DeviceType=(LPT1, LPT2, PcSpeaker, Adlib, SoundBlaster);
  36.  Card      =(Speaker,AdLibFM,SB_Norm,SB_Pro,SB_16);
  37.  EMMStructure          =RECORD
  38.                           BytesToMoveLo,
  39.                           BytesToMoveHi,
  40.                           SourceHandle,
  41.                           SourceOffsetLo,
  42.                           SourceOffsetHi,
  43.                           DestinationHandle,
  44.                           DestinationOffsetLo,
  45.                           DestinationOffsetHi  :WORD;
  46.                         END;
  47.  
  48.  
  49. VAR
  50.  DonePlaying  :BOOLEAN;
  51.  SpkrTable    :ARRAY[0..255] OF BYTE;
  52.  BufSize      :WORD;
  53.  XMSChoice    :BOOLEAN;
  54.  HeaSize      :BYTE;
  55.  SBPort       :WORD;
  56.  Size         :LongInt;
  57.  XMSPos       :LongInt;
  58.  TextBool     :BOOLEAN;
  59.  NoFilter     :BOOLEAN;
  60.  XMSRecord    :EMMStructure;
  61.  FileCounter  :LongInt;
  62.  Buffer,
  63.  XMSEntryPoint:Pointer;
  64.  BufferHandle,
  65.  BytesRead    :WORD;
  66.  CardType     :Card;
  67.  VolMax       :BYTE;
  68.  Segment,
  69.  Decalage     :WORD;
  70.  Counter      :WORD;
  71.  car          :Char;
  72.  ScrollSpeed  :BYTE;
  73.  Stringn      :STRING;
  74.  
  75.  
  76. FUNCTION  Hexa_Addr(Address:WORD):WORD;
  77. FUNCTION  NoXMS:BOOLEAN;
  78. PROCEDURE Init_Speaker;
  79. PROCEDURE End_Speaker;
  80. FUNCTION  AdLib_Test:BOOLEAN;
  81. FUNCTION  SB_Test:BOOLEAN;
  82. PROCEDURE Spk_On;
  83. PROCEDURE Spk_Off;
  84. FUNCTION  Mixer_Test:BOOLEAN;
  85. PROCEDURE SbProSetFilter(Filter:BOOLEAN);
  86. PROCEDURE VoiceMixerVol(Volume:BYTE);
  87. PROCEDURE InitializeAdLib;
  88. PROCEDURE SetOutPutDevice(DeviceName:DeviceType);
  89. PROCEDURE SetPlaySpeed(Speed:LONGINT);
  90. PROCEDURE PlayRAWSoundFile(FileName:STRING;SampleRate:WORD);
  91. PROCEDURE LoadPlayXMS(FileName:STRING;SampleRate:WORD);
  92. PROCEDURE CleanUp;
  93.  
  94.  
  95. IMPLEMENTATION
  96.  
  97.  
  98. TYPE
  99.  ZeroAndOne=0..1;
  100.  
  101.  
  102. VAR
  103.  DataLength       :WORD;
  104.  Bufferp          :BufPointer;
  105.  i                :BYTE;
  106.  LPTAddress       :WORD;
  107.  LPTPort          :ARRAY[1 .. 2] OF WORD ABSOLUTE $0040:$0008;
  108.  OldTimerInterrupt:Pointer;
  109.  OldINT9          :Pointer;
  110.  InterruptVector  :ARRAY[0..255] OF Pointer ABSOLUTE $0000:$0000;
  111.  VolReg           :BYTE;
  112.  Sauve            :ARRAY[0..331] OF BYTE;
  113.  X                :WORD;
  114.  
  115.  
  116. PROCEDURE CLI;ASSEMBLER;
  117. ASM
  118.   cli
  119. END;
  120.  
  121.  
  122. PROCEDURE STI;ASSEMBLER;
  123. ASM
  124.   sti
  125. END;
  126.  
  127.  
  128. FUNCTION Hexa_Addr(Address:WORD):WORD;
  129. BEGIN
  130.   Hexa_Addr:=(Address-512) Div 16*10+200;
  131. END;
  132.  
  133.  
  134. FUNCTION NoXMS:BOOLEAN;ASSEMBLER;
  135. LABEL JumpOver;
  136. ASM
  137.   push   es
  138.   mov    ax,4300h
  139.   int    2Fh
  140.   mov    bl,1
  141.   cmp    al,80h
  142.   jne    JumpOver
  143.   mov    ax,4310h
  144.   int    2Fh
  145.   mov    [word ptr XMSEntryPoint+0],BX
  146.   mov    [word ptr XMSEntryPoint+2],ES
  147.   mov    bl,0
  148.  JumpOver:
  149.   mov    al,bl
  150.   pop    es
  151. END;
  152.  
  153.  
  154. FUNCTION XMSMaxAvail:WORD;ASSEMBLER;
  155. LABEL JumpOver;
  156. ASM
  157.   mov    ah,08h
  158.   mov    XMSError,0
  159.   call   [dword ptr XMSEntryPoint]
  160.   or     ax,ax
  161.   jnz    JumpOver
  162.   mov    XMSError,bl
  163.  JumpOver:
  164. END;
  165.  
  166.  
  167. FUNCTION XMSGetMem(SizeInKB:WORD):WORD;ASSEMBLER;
  168. LABEL JumpOver;
  169. ASM
  170.   mov    ah,09h
  171.   mov    dx,SizeInKB
  172.   mov    XMSError,0
  173.   call   [dword ptr XMSEntryPoint]
  174.   or     ax,ax
  175.   jnz    JumpOver
  176.   mov    XMSError,bl
  177.  JumpOver:
  178.   mov    ax,dx
  179. END;
  180.  
  181.  
  182. PROCEDURE XMSFreeMem(Handle:WORD);ASSEMBLER;
  183. LABEL JumpOver;
  184. ASM
  185.   mov    ah,0Ah
  186.   mov    dx,Handle
  187.   mov    XMSError,0
  188.   call   [dword ptr XMSEntryPoint]
  189.   or     ax,ax
  190.   jnz    JumpOver
  191.   mov    XMSError,bl
  192.  JumpOver:
  193. END;
  194.  
  195.  
  196. PROCEDURE XMSMove(VAR EMMParamBlock:EMMStructure);ASSEMBLER;
  197. LABEL JumpOver;
  198. ASM
  199.   push   ds
  200.   push   es
  201.   push   ds
  202.   pop    es
  203.   mov    ah,0Bh
  204.   mov    XMSError,0
  205.   lds    si,EMMParamBlock
  206.   call   [dword ptr es:XMSEntryPoint]
  207.   or     ax,ax
  208.   jnz    JumpOver
  209.   mov    XMSError,bl
  210.  JumpOver:
  211.   pop    es
  212.   pop    ds
  213. END;
  214.  
  215.  
  216. FUNCTION Read_FM:BYTE;
  217. BEGIN
  218.   ASM
  219.     mov   dx ,388h
  220.     in    al ,dx
  221.     mov   @result,al
  222.   END;
  223. END;
  224.  
  225.  
  226. PROCEDURE Init_Speaker;ASSEMBLER;
  227. ASM
  228.   In    al ,61h
  229.   Or    al ,3
  230.   Out   61h,al
  231.   Mov   al ,0B6h
  232.   Out   43h,al
  233.   Mov   al ,0B0h
  234.   Out   43h,al
  235.   Mov   al ,034h
  236.   Out   43h,al
  237.   Xor   al ,al
  238.   Out   42h,al
  239.   Out   42h,al
  240.   Mov   al ,090h
  241.   Out   43h,al
  242. END;
  243.  
  244.  
  245. PROCEDURE End_Speaker;ASSEMBLER;
  246. ASM
  247.   In    al ,61h
  248.   And   al ,11111100b
  249.   Out   61h,al
  250. END;
  251.  
  252.  
  253. PROCEDURE Adlibw(Reg,Data:BYTE);ASSEMBLER;
  254. ASM
  255.   mov   dx ,388h
  256.   mov   al ,Reg
  257.   out   dx ,al
  258.   in    al ,dx
  259.   in    al ,dx
  260.   in    al ,dx
  261.   in    al ,dx
  262.   in    al ,dx
  263.   in    al ,dx
  264.   inc   dx
  265.   mov   al ,Data
  266.   out   dx ,al
  267.   in    al ,dx
  268.   in    al ,dx
  269.   in    al ,dx
  270.   in    al ,dx
  271.   in    al ,dx
  272.   in    al ,dx
  273.   in    al ,dx
  274.   in    al ,dx
  275.   in    al ,dx
  276.   in    al ,dx
  277.   in    al ,dx
  278.   in    al ,dx
  279.   in    al ,dx
  280.   in    al ,dx
  281.   in    al ,dx
  282.   in    al ,dx
  283.   in    al ,dx
  284.   in    al ,dx
  285.   in    al ,dx
  286.   in    al ,dx
  287.   in    al ,dx
  288.   in    al ,dx
  289.   in    al ,dx
  290.   in    al ,dx
  291.   in    al ,dx
  292.   in    al ,dx
  293.   in    al ,dx
  294.   in    al ,dx
  295.   in    al ,dx
  296.   in    al ,dx
  297.   in    al ,dx
  298.   in    al ,dx
  299.   in    al ,dx
  300.   in    al ,dx
  301.   in    al ,dx
  302. END;
  303.  
  304.  
  305. FUNCTION AdLib_Test:BOOLEAN;
  306. VAR
  307.  Res1,Res2,i:BYTE;
  308. BEGIN
  309.   AdLibw($01,$00);
  310.   AdLibw($04,$60);
  311.   AdLibw($04,$80);
  312.   Res1:=Read_FM;
  313.   AdLibw($02,$FF);
  314.   AdLibw($04,$21);
  315.   FOR i:=0 TO 200 DO;
  316.     Res2:=Read_FM;
  317.   AdLibw($04,$60);
  318.   AdLibw($04,$80);
  319.   IF (((Res1 AND $E0)=0) AND ((Res2 AND $E0)=$C0)) THEN
  320.   BEGIN
  321.     AdLib_Test:=True;
  322.     CardType  :=AdLibFM;
  323.   END
  324.   ELSE
  325.     AdLib_Test:=False;
  326. END;
  327.  
  328.  
  329. FUNCTION SB_Test:BOOLEAN;
  330. CONST
  331.  NrTimes  =10;
  332.  NrTimes2 =50;
  333. VAR
  334.  Found    :BOOLEAN;
  335.  Counter1,
  336.  Counter2 :WORD;
  337. BEGIN
  338.   SBPort  :=$210;
  339.   Found   :=False;
  340.   Counter1:=NrTimes;
  341.   WHILE (SBPort<=$260) AND NOT Found DO
  342.   BEGIN
  343.     Port[SBPort+$6]:=1;
  344.     Port[SBPort+$6]:=0;
  345.     Counter2:=NrTimes2;
  346.     WHILE (Counter2>0) AND (Port[SBPort+$E]<128) DO
  347.       Dec(Counter2);
  348.     IF (Counter2=0) OR (Port[SBPort+$A]<>$AA) THEN
  349.     BEGIN
  350.       Dec(Counter1);
  351.       IF (Counter1=0) THEN
  352.       BEGIN
  353.         Counter1:=NrTimes;
  354.         SBPort  :=SBPort+$10;
  355.       END
  356.     END
  357.     ELSE Found:=True;
  358.   END;
  359.   IF Found THEN
  360.   BEGIN
  361.     SB_Test:=True;
  362.     CardType:=SB_Norm;
  363.   END
  364.   ELSE SB_Test:=False;
  365. END;
  366.  
  367.  
  368. PROCEDURE Spk_On;
  369. BEGIN
  370.   REPEAT UNTIL Port[SBPort+$C]<$80;
  371.   Port[SBPort+$C]:=$D1;
  372. END;
  373.  
  374.  
  375. PROCEDURE Spk_Off;
  376. BEGIN
  377.   REPEAT UNTIL Port[SBPort+$C]<$80;
  378.   Port[SBPort+$C]:=$D3;
  379. END;
  380.  
  381.  
  382. PROCEDURE SbWriteMixerReg(Reg,Val:BYTE);ASSEMBLER;
  383. ASM
  384.   mov   dx ,SBPort
  385.   add   dx ,04h
  386.   mov   al ,Reg
  387.   out   dx ,al
  388.   add   dx ,01h
  389.   mov   al ,Val
  390.   out   dx ,al
  391. END;
  392.  
  393.  
  394. FUNCTION SbReadMixerReg(Reg:BYTE):BYTE;ASSEMBLER;
  395. ASM
  396.   mov   dx ,SBPort
  397.   add   dx ,04h
  398.   mov   al ,Reg
  399.   out   dx ,al
  400.   add   dx ,01h
  401.   in    al ,dx
  402. END;
  403.  
  404.  
  405. PROCEDURE VoiceMixerVol(Volume:BYTE);
  406. BEGIN
  407.   IF CardType=SB_Pro THEN
  408.     SbWriteMixerReg(VolReg,Volume OR (Volume SHL 4));
  409.   IF CardType=SB_16  THEN
  410.   BEGIN
  411.     SbWriteMixerReg(VolReg  ,Volume);
  412.     SbWriteMixerReg(VolReg+1,Volume);
  413.   END;
  414. END;
  415.  
  416.  
  417. FUNCTION Mixer_Test:BOOLEAN;
  418. BEGIN
  419. {  SbWriteMixerReg($00,$00); RESET}
  420.   Mixer_Test:=False;
  421.   SbWriteMixerReg($30,$0B);
  422.   IF SbReadMixerReg($30)=$0B THEN
  423.   BEGIN
  424.     Mixer_Test:=True;
  425.     CardType  :=SB_16;
  426.     VolReg    :=$30;
  427.     SbWriteMixerReg($30  ,$09);
  428.     SbWriteMixerReg($30+1,$09);
  429.     VolMax    :=31;
  430.   END
  431.   ELSE
  432.   BEGIN
  433.     SbWriteMixerReg($22,$F3);
  434.     IF SbReadMixerReg($22)=$F3 THEN
  435.     BEGIN
  436.       Mixer_Test:=True;
  437.       CardType  :=SB_Pro;
  438.       VolReg    :=$22;
  439.       SbWriteMixerReg($22,$99);
  440.       VolMax    :=15;
  441.     END;
  442.   END;
  443. END;
  444.  
  445.  
  446. PROCEDURE SbProSetFilter(Filter:BOOLEAN);
  447. VAR
  448.  i:BYTE;
  449. BEGIN
  450.   i:=SbReadMixerReg($0E);
  451.   SbWriteMixerReg($0E,(i AND NOT $20)+(BYTE(Filter) * $20));
  452. END;
  453.  
  454.  
  455. PROCEDURE InitializeAdlib;
  456. BEGIN
  457.   FOR i:=1 TO 255 DO
  458.     AdLibw(i,0);
  459.   Adlibw($01,$20);
  460.   Adlibw($C0,$01);
  461.   Adlibw($23,$27);
  462.   Adlibw($43,$00);
  463.   Adlibw($63,$FF);
  464.   Adlibw($83,$0F);
  465.   Adlibw($E3,$02);
  466.   Adlibw($A0,$0C);
  467.   Adlibw($B0,$3F);
  468. END;
  469.  
  470.  
  471. PROCEDURE OscilloKey;
  472. VAR
  473.  Xo:BYTE;
  474. BEGIN
  475.   Inc(X);
  476.   IF X>331 THEN X:=0;
  477.   Xo:=i;
  478.   IF Xo>255 THEN Xo:=255;
  479.   IF Xo<1   THEN Xo:=1;
  480.   YEcritPoint(X+14,sauve[X]+441,230);
  481.   YEcritPoint(X+14,sauve[X]+440,230);
  482.   YEcritPoint(X+14,Xo+441,231);
  483.   YEcritPoint(X+14,Xo+440,231);
  484.   sauve[X]:=Xo;
  485.     CASE car OF
  486.      #80:BEGIN
  487.            IF Counter<247*ScrollSpeed THEN
  488.            BEGIN
  489.              Inc(Counter);
  490.              YScroll(Counter DIV ScrollSpeed);
  491.            END;
  492.          END;
  493.      #72:BEGIN
  494.            IF Counter>20*ScrollSpeed THEN
  495.            BEGIN
  496.              Dec(Counter);
  497.              YScroll(Counter DIV ScrollSpeed);
  498.            END;
  499.          END;
  500.     END;
  501.     IF KeyPressed THEN car:=ReadKey;
  502. END;
  503.  
  504.  
  505. PROCEDURE PlayPCSpeaker;Interrupt;
  506. CONST
  507.  Counter:WORD=0;
  508. BEGIN
  509.   IF NOT(DonePlaying) THEN
  510.   BEGIN
  511.     IF Counter<=DataLength THEN
  512.     BEGIN
  513.       i:=bufferp^[Counter];
  514.       ASM
  515.         xor   al ,al
  516.         out   42h,al
  517.         mov   al ,i
  518.         mov   bx ,offset SpkrTable
  519.         xlat
  520.         out   42h,al
  521.       END;
  522.       Inc(Counter);
  523.     END
  524.     ELSE
  525.     BEGIN
  526.       DonePlaying:=True;
  527.       Counter    :=0;
  528.     END;
  529.   END;
  530.   ASM
  531.     mov   al ,020h
  532.     out   20h,al
  533.   END;
  534. END;
  535.  
  536.  
  537. PROCEDURE PlayLPT;Interrupt;
  538. CONST
  539.  Counter:WORD=0;
  540. BEGIN
  541.   IF NOT(DonePlaying) THEN
  542.   BEGIN
  543.     IF Counter<=DataLength THEN
  544.     BEGIN
  545.       i:=Bufferp^[Counter];
  546.       ASM
  547.         mov   dx, LPTAddress
  548.         mov   al, i
  549.         out   dx, al
  550.       END;
  551.       Inc(Counter);
  552.     END
  553.     ELSE
  554.     BEGIN
  555.       DonePlaying:=True;
  556.       Counter    :=0;
  557.     END;
  558.   END;
  559.   ASM
  560.     mov   al ,020h
  561.     out   20h,al
  562.   END;
  563. END;
  564.  
  565.  
  566. PROCEDURE PlayAdlib;Interrupt;
  567. CONST
  568.  Counter:WORD=0;
  569. VAR
  570.  j:BYTE;
  571. BEGIN
  572.   If Not(DonePlaying) Then
  573.   Begin
  574.     If Counter <= DataLength Then
  575.     Begin
  576.       i:=Bufferp^[Counter];
  577.       j:=i SHR 3;
  578.       ASM
  579.         mov   dx ,388h
  580.         mov   al ,043h
  581.         out   dx ,al
  582.         in    al ,dx
  583.         in    al ,dx
  584.         in    al ,dx
  585.         in    al ,dx
  586.         in    al ,dx
  587.         in    al ,dx
  588.         inc   dx
  589.         mov   al , j
  590.         out   dx ,al
  591.       END;
  592.       Inc(Counter);
  593.     END
  594.     ELSE
  595.     BEGIN
  596.       DonePlaying:=True;
  597.       Counter    :=0;
  598.     END;
  599.   END;
  600.   ASM
  601.     mov   al ,020h
  602.     out   20h,al
  603.   END;
  604. END;
  605.  
  606.  
  607. PROCEDURE PlaySoundBlaster;Interrupt;
  608. CONST
  609.  Counter:WORD=0;
  610. BEGIN
  611.   If Not(DonePlaying) Then
  612.   Begin
  613.     If Counter <= DataLength Then
  614.     Begin
  615.       i:=Bufferp^[Counter];
  616.       ASM
  617.         mov   dx ,SBPort
  618.         add   dx ,0Ch
  619.         mov   cx ,100h
  620.         mov   al ,010h
  621.         out   dx ,al
  622.        @L1:
  623.         in    al ,dx
  624.         or    al ,al
  625.         jns   @OK
  626.         loop  @L1
  627.         ret
  628.        @OK:
  629.         mov   al ,i
  630.         out   dx ,al
  631.       END;
  632.       Inc(Counter);
  633.     END
  634.     ELSE
  635.     BEGIN
  636.       DonePlaying:=True;
  637.       Counter    :=0;
  638.     END;
  639.   END;
  640.   ASM
  641.     mov   al ,020h
  642.     out   20h,al
  643.   END;
  644. END;
  645.  
  646.  
  647. PROCEDURE Set8253Channel(ProgramValue:WORD);
  648. BEGIN
  649.   Port[$43]:=54;
  650.   Port[$40]:=Lo(ProgramValue);
  651.   Port[$40]:=Hi(ProgramValue);
  652. END;
  653.  
  654.  
  655. PROCEDURE SetPlaySpeed(Speed:LONGINT);
  656. VAR
  657.  ProgramValue:WORD;
  658. BEGIN
  659.   ProgramValue:=1193180 DIV Speed;
  660.   Set8253Channel(ProgramValue);
  661. END;
  662.  
  663.  
  664. PROCEDURE SetDefaultTimerSpeed;
  665. BEGIN
  666.   Set8253Channel(0);
  667. END;
  668.  
  669.  
  670. FUNCTION LoadBuffer(VAR F:FILE;VAR BufP:BufPointer):WORD;
  671. VAR
  672.  NumRead:WORD;
  673. BEGIN
  674.   BlockRead(F,BufP^,BufSize,NumRead);
  675.   LoadBuffer:=NumRead;
  676. END;
  677.  
  678.  
  679. FUNCTION LoadBufferXMS(VAR BufP:BufPointer):WORD;
  680. VAR
  681.  XMSRecord    :EMMStructure;
  682.  NumberOfBytes:WORD;
  683.  NumRead      :WORD;
  684. BEGIN
  685.   NumRead:=BufSize;
  686.   IF (XMSPos+BufSize)>Size THEN
  687.     NumRead:=Size-XMSPos;
  688.   NumberOfBytes:=NumRead;
  689.   IF NumRead MOD 2=1 THEN
  690.     Inc(NumberOfBytes);
  691.   WITH XMSRecord DO
  692.   BEGIN
  693.     BytesToMoveLo      :=NumberOfBytes;
  694.     BytesToMoveHi      :=0;
  695.     SourceHandle       :=BufferHandle;
  696.     SourceOffsetLo     :=XMSPos MOD 65536;
  697.     SourceOffsetHi     :=XMSPos DIV 65536;
  698.     DestinationHandle  :=0;
  699.     DestinationOffsetLo:=Ofs(BufP^);
  700.     DestinationOffsetHi:=Seg(BufP^);
  701.   END;
  702.   XMSMove(XMSRecord);
  703.   IF XMSError<>0 THEN
  704.   BEGIN
  705.     FreeMem(BufP,BufSize);
  706.     Stringn:=' XMS-->RAM error detected';
  707.     XMSFreeMem(BufferHandle);
  708.     Exit;
  709.   END;
  710.   Inc(XMSPos,NumRead);
  711.   LoadBufferXMS:=NumRead;
  712. END;
  713.  
  714.  
  715. PROCEDURE PlayBuffer(BufPtr:BufPointer;BSize:WORD);
  716. BEGIN
  717.   Bufferp    :=BufPtr;
  718.   DataLength :=BSize-1;
  719.   DonePlaying:=False;
  720. END;
  721.  
  722.  
  723. PROCEDURE PlayBufferXMS(BufPtr:BufPointer;BSize:WORD);
  724. BEGIN
  725.   Bufferp    :=BufPtr;
  726.   DataLength :=BSize-1;
  727.   DonePlaying:=False;
  728. END;
  729.  
  730.  
  731. PROCEDURE InitializeData;
  732. CONST
  733.  CalledOnce:BOOLEAN=False;
  734. BEGIN
  735.   IF NOT(CalledOnce) THEN
  736.   BEGIN
  737.     DonePlaying      :=True;
  738.     OldTimerInterrupt:=InterruptVector[$08];
  739.     CalledOnce       :=True;
  740.   END;
  741.   FOR X:=0 TO 331 DO
  742.     sauve[X]:=128;
  743.   X:=0;
  744. END;
  745.  
  746.  
  747. PROCEDURE SetOutPutDevice(DeviceName:DeviceType);
  748. BEGIN
  749.   CLI;
  750.   CASE DeviceName OF
  751.     LPT1,LPT2   :BEGIN
  752.                    LPTAddress:=LPTPort[Ord(DeviceName)];
  753.                    InterruptVector[$08]:=@PlayLPT;
  754.                  END;
  755.     PCSpeaker   :BEGIN
  756.                    InterruptVector[$08]:=@PlayPCSpeaker;
  757.                  END;
  758.     Adlib       :BEGIN
  759.                    InterruptVector[$08]:=@PlayAdlib;
  760.                  END;
  761.     SoundBlaster:BEGIN
  762.                    InterruptVector[$08]:=@PlaySoundBlaster;
  763.                  END;
  764.     ELSE
  765.     BEGIN
  766.      { This Sound Device is not available.
  767.       Using the PC Speaker as the Sound Device...}
  768.       InterruptVector[$08]:=@PlayPCSpeaker;
  769.     END;
  770.   END;
  771.   STI;
  772. END;
  773.  
  774.  
  775. PROCEDURE SetTimerInterruptVectorDefault;
  776. BEGIN
  777.   CLI;
  778.   InterruptVector[$08]:=OldTimerInterrupt;
  779.   STI;
  780. END;
  781.  
  782.  
  783. PROCEDURE PlayRAWSoundFile(FileName:STRING;SampleRate:WORD);
  784. VAR
  785.  RawDataFile:FILE;
  786.  SoundBuffer:ARRAY[ZeroAndOne] OF BufPointer;
  787.  BufNum     :ZeroAndOne;
  788.  Size       :WORD;
  789. BEGIN
  790.   GetMem(SoundBuffer[0],BufSize);
  791.   GetMem(SoundBuffer[1],BufSize);
  792.   SetPlaySpeed(SampleRate);
  793.   Assign(RawDataFile,FileName);
  794.   Reset (RawDataFile,1);
  795.   IF HeaSize>0 THEN
  796.     Seek(RawDataFile,HeaSize);
  797.   BufNum:=0;
  798.   Size:=LoadBuffer(RawDataFile,SoundBuffer[BufNum]);
  799.   PlayBuffer(SoundBuffer[BufNum],Size);
  800.   car:=#80;
  801.   WHILE (NOT(EOF(RawDataFile)) AND (car<>#27)) DO
  802.   BEGIN
  803.     BufNum:=(BufNum+1) AND 1;
  804.     Size  :=LoadBuffer(RawDataFile,SoundBuffer[BufNum]);
  805.     REPEAT OscilloKey; UNTIL DonePlaying;
  806.     PlayBuffer(SoundBuffer[BufNum],Size);
  807.   END;
  808.   Close(RawDataFile);
  809.   REPEAT OscilloKey; UNTIL DonePlaying;
  810.   SetDefaultTimerSpeed;
  811.   FreeMem(SoundBuffer[1],BufSize);
  812.   FreeMem(SoundBuffer[0],BufSize);
  813. END;
  814.  
  815.  
  816. PROCEDURE LoadPlayXMS(FileName:STRING;SampleRate:WORD);
  817. VAR
  818.  RawDataFile:FILE;
  819.  SoundBuffer:ARRAY[ZeroAndOne] OF BufPointer;
  820.  BufNum     :ZeroAndOne;
  821.  SizeS      :WORD;
  822. BEGIN
  823.   XMSError:=0;
  824.   IF MaxAvail<16000 THEN
  825.   BEGIN
  826.     XMSError:=1;
  827.     Stringn:=' Not enough RAM memory for XMS buffer';
  828.     Exit;
  829.   END;
  830.   GetMem(Buffer,16000);
  831.   Assign(RawDataFile,FileName);
  832.   Reset (RawDataFile,1);
  833.   Size:=FileSize(RawDataFile);
  834.   IF XMSMaxAvail<=(Size+1023) SHR 10 THEN
  835.   BEGIN
  836.     FreeMem(Buffer,16000);
  837.     Close(RawDataFile);
  838.     XMSError:=2;
  839.     Stringn:=' Not enough XMS memory';
  840.     Exit;
  841.   END
  842.   ELSE
  843.   BEGIN
  844.     Seek(RawDataFile,0);
  845.     BufferHandle:=XMSGetMem((Size+1023) SHR 10);
  846.     FileCounter:=0;
  847.     REPEAT
  848.       BlockRead(RawDataFile,Buffer^,16000,BytesRead);
  849.       IF BytesRead MOD 2=1 THEN
  850.         Inc(BytesRead);
  851.       IF BytesRead<>0 THEN
  852.       BEGIN
  853.         WITH XMSRecord DO
  854.         BEGIN
  855.           BytesToMoveLo      :=BytesRead;
  856.           BytesToMoveHi      :=0;
  857.           SourceHandle       :=0;
  858.           SourceOffsetLo     :=Ofs(Buffer^);
  859.           SourceOffsetHi     :=Seg(Buffer^);
  860.           DestinationHandle  :=BufferHandle;
  861.           DestinationOffsetLo:=FileCounter MOD 65536;
  862.           DestinationOffsetHi:=FileCounter DIV 65536;
  863.         END;
  864.         XMSMove(XMSRecord);
  865.         IF XMSError<>0 THEN
  866.         BEGIN
  867.           FreeMem(Buffer,16000);
  868.           Close(RawDataFile);
  869.           Stringn:=' RAM-->XMS error detected';
  870.           XMSFreeMem(BufferHandle);
  871.           Exit;
  872.         END;
  873.         Inc(FileCounter,BytesRead);
  874.       END;
  875.     UNTIL BytesRead<>16000;
  876.   END;
  877.   Close(RawDataFile);
  878.   FreeMem(Buffer,16000);
  879.   GetMem(SoundBuffer[0],BufSize);
  880.   GetMem(SoundBuffer[1],BufSize);
  881.   SetPlaySpeed(SampleRate);
  882.   XMSPos:=0;
  883.   IF HeaSize>0 THEN
  884.     XMSPos:=HeaSize;
  885.   BufNum:=0;
  886.   SizeS:=LoadBufferXMS(SoundBuffer[BufNum]);
  887.   PlayBufferXMS(SoundBuffer[BufNum],SizeS);
  888.   car:=#80;
  889.   WHILE (NOT(XMSPos>=Size) AND (car<>#27)) DO
  890.   BEGIN
  891.     BufNum:=(BufNum+1) AND 1;
  892.     SizeS :=LoadBufferXMS(SoundBuffer[BufNum]);
  893.     REPEAT OscilloKey; UNTIL DonePlaying;
  894.     PlayBufferXMS(SoundBuffer[BufNum],SizeS);
  895.   END;
  896.   REPEAT OscilloKey; UNTIL DonePlaying;
  897.   SetDefaultTimerSpeed;
  898.   XMSFreeMem(BufferHandle);
  899.   FreeMem(SoundBuffer[1],BufSize);
  900.   FreeMem(SoundBuffer[0],BufSize);
  901. END;
  902.  
  903.  
  904. PROCEDURE CleanUp;
  905. BEGIN
  906.   SetDefaultTimerSpeed;
  907.   SetTimerInterruptVectorDefault;
  908. END;
  909.  
  910.  
  911. BEGIN
  912.   InitializeData;
  913.   CardType:=Speaker;
  914.   SBPort  :=$220;
  915.   VolMax  :=   9;
  916. END.
  917.