// This Code is for hardware function demonstration purposes only
// Leipzig 02-19-98 (c) 1998 marian GbR Leipzig

{ *** Analog Play ************************************************************************************* }

procedure Copy16BitStereo_ToAnalog (var Src, Dest : Pointer; DestBase: dWord; Size: LongInt); Assembler;
{ Src      = current. Address of Clientbuffer
  Dest     = current. Address in Card RAM
  DestBase = Base Address for Analog Play in Card RAM
  Size     = Count to tranf. Bytes
}
ASM
          pushad

      { load Source Address load }

          mov     ESI,[Src]
          mov     ESI,[ESI]

      { Destination Address load }

          mov     EDI,[Dest]
          mov     EDI,[EDI]                      { EDI = WritePtr }

      { Bytes to Destbuffer End check }

          mov     EAX,EDI
          sub     EAX,[DestBase]                 { EAX = ByteOffset to Chn.AudioData }
          mov     EDX,BufSize
          sub     EDX,EAX                        { EDX = Count Bytes to Buffer End }

          mov     EBX,Size
          cmp     EBX,EDX
          jae     @Transfer                      { if Size >= Bytes to Buffer End }
          mov     EDX,EBX

      { Audio Data from lpDataAct (Src) -> WritePtr (Dest) }

@Transfer:
          cld
          sub     EBX,EDX                        { sub Count Bytes of one REP Loop from all bytes }
          shr     EDX,2                          { EDX = Loop Counter for Src: Bytes -> dWords }
@TrnsLp:
          mov     ECX,WriteCycles
          cmp     EDX,ECX
          jae     @Cycle                         { if Count of possible. Loop Counts > WriteCycles }
          mov     ECX,EDX

@Cycle:   sub     EDX,ECX
          mov     EAX,[EDI]                      { PCI Read, to force PLX to free the local Bus }

@CycleLp: rep     movsd

          or      EDX,EDX                        { further Cycle necessary ? }
          jnz     @TrnsLp                        { yes }

          or      EBX,EBX                        { something else to transfer ? }
          jz      @Save

          mov     EDX,EBX
          mov     EDI,[DestBase]                 { EDI = Chn.AudioData (DestBase) }
          jmp     @Transfer

@Save:
      { Check, EDI = Buffer End  }

          mov     EAX,EDI
          sub     EAX,[DestBase]                 { EAX = Offset to AudioData (DestBase) }
          cmp     EAX,BufSize
          jne     @SaveDest
          mov     EDI,[DestBase]                 { EDI = Buffer Begin }

      { Save Destination and Source Pointers }

@SaveDest:
          mov     EBX,[Dest]
          mov     [EBX],EDI

@SaveSource:
          mov     EBX,[Src]
          mov     [EBX],ESI

          popad
end;

procedure Copy8BitStereo_ToAnalog (var Src, Dest: Pointer;  DestBase : dWord; Size: LongInt); Assembler;
{ Src      = current. Address of Clientbuffer
  Dest     = current. Address in Card RAM
  DestBase = Base Address for Analog Play in Card RAM
  Size     = Count to tranf. Bytes
}
ASM
          pushad

      { Source Address load }

          mov     ESI,[Src]
          mov     ESI,[ESI]

      { Destination Address load }

          mov     EDI,[Dest]
          mov     EDI,[EDI]                      { EDI = WritePtr }

      { Bytes to Destbuffer End check }

          mov     EAX,EDI
          sub     EAX,[DestBase]                 { EAX = ByteOffset to Chn.AudioData }
          mov     EDX,BufSize
          sub     EDX,EAX                        { EDX = Count Bytes to Buffer End }
          shr     EDX,1

          mov     EBX,Size
          cmp     EBX,EDX
          jae     @Transfer                      { if Size >= Bytes to Buffer End }
          mov     EDX,EBX

      { Audio Data from lpDataAct (Src) -> WritePtr (Dest) }

@Transfer:
          cld
          sub     EBX,EDX                        { Sub Count Bytes of one REP Loop from all bytes }
          push    EBX
          shr     EDX,1                          { EDX = Loop Counter for Src: Bytes -> dWords }
@TrnsLp:
          mov     ECX,WriteCycles
          cmp     EDX,ECX
          jae     @Cycle                         { if Count of possible. Loop Counts > WriteCycles }
          mov     ECX,EDX

@Cycle:   sub     EDX,ECX
          mov     EAX,[EDI]                      { PCI Read, to force PLX to free the local Bus }

@CycleLp:
          lodsb                                  { Sample left Channel }
          add     AL,80h
          xchg    AH,AL                          { AH = 8BitSample; AL = 0 }
          mov     BX,AX
          shl     EBX,16

          lodsb                                  { Sample left Channel }
          add     AL,80h
          xchg    AH,AL                          { AH = 8BitSample; AL = 0 }
          mov     BX,AX

          mov     EAX,EBX
          stosd
          loop    @CycleLp

          or      EDX,EDX                        { further Cycle necessary ? }
          jnz     @TrnsLp                        { yes }

          pop     EBX
          or      EBX,EBX                        { something else to transfer ? }
          jz      @Save

          mov     EDX,EBX
          mov     EDI,[DestBase]                 { EDI = Chn.AudioData (DestBase) }
          jmp     @Transfer

@Save:
      { Check, EDI = Buffer End }

          mov     EAX,EDI
          sub     EAX,[DestBase]                 { EAX = Offset to AudioData (DestBase) }
          cmp     EAX,BufSize
          jne     @SaveDest
          mov     EDI,[DestBase]                 { EDI = Buffer Begin }

      { Save Destination and Source Pointers }

@SaveDest:
          mov     EBX,[Dest]
          mov     [EBX],EDI

@SaveSource:
          mov     EBX,[Src]
          mov     [EBX],ESI

          popad
end;

{ *** Digital Play ************************************************************************************* }

procedure Copy16BitStereo_ToDigital (var Src, Dest: Pointer; DestBase : dWord; Size: LongInt); Assembler;
{ Src      = current. Address of Clientbuffer
  Dest     = current. Address in Card RAM
  DestBase = Base Address for Digital Play in Card RAM
  Size     = Count to tranf. Bytes
}
ASM
          pushad

      { Source Address load }

          mov     ESI,[Src]
          mov     ESI,[ESI]

      { Destination Address load }

          mov     EDI,[Dest]
          mov     EDI,[EDI]                      { EDI = WritePtr }

      { Bytes to Destbuffer End check }

          mov     EAX,EDI
          sub     EAX,[DestBase]                 { EAX = ByteOffset to Chn.AudioData }
          mov     EDX,BufSize
          sub     EDX,EAX                        { EDX = Count Bytes to Buffer End }
          shr     EDX,1                          { EDX / 2 because the double write progress in Src }

          mov     EBX,Size
          cmp     EBX,EDX
          jae     @Transfer                      { if Size >= Bytes to Buffer End }
          mov     EDX,EBX

      { Audio Data from lpDataAct (Src) -> WritePtr (Dest) }

@Transfer:
          cld
          sub     EBX,EDX                        { Sub Count Bytes of one REP Loop from all bytes }
          shr     EDX,2                          { EDX = Loop Counter for Src: Bytes -> dWords }
@TrnsLp:
          mov     ECX,WriteCycles/2
          cmp     EDX,ECX
          jae     @Cycle                         { if Count of possible. Loop Counts > WriteCycles }
          mov     ECX,EDX

@Cycle:   sub     EDX,ECX
          mov     EAX,[EDI]                      { PCI Read, to force PLX to free the local Bus }

@CycleLp: lodsw                                  { AX: left 16 Bit Sample }
          shl     EAX,16                         { shift Audiobits to higher Word  }
          stosd                                  { save left Sample to Dest }

          lodsw                                  { AX: right 16 Bit Sample }
          shl     EAX,16                         { shift Audiobits to higher Word  }
          stosd                                  { save right Sample to Dest }
          loop    @CycleLp

          or      EDX,EDX                        { further Cycle necessary ? }
          jnz     @TrnsLp                        { yes }

          or      EBX,EBX                        { something else to transfer ? }
          jz      @Save

          mov     EDX,EBX
          mov     EDI,[DestBase]                 { EDI = Chn.AudioData (DestBase) }
          jmp     @Transfer

@Save:
      { Check, EDI = Buffer End }

          mov     EAX,EDI
          sub     EAX,[DestBase]                 { EAX = Offset to AudioData (DestBase) }
          cmp     EAX,BufSize
          jne     @SaveDest
          mov     EDI,[DestBase]                 { EDI = Buffer Begin }

      { Save Destination and Source Pointers }

@SaveDest:
          mov     EBX,[Dest]
          mov     [EBX],EDI

@SaveSource:
          mov     EBX,[Src]
          mov     [EBX],ESI

          popad
end;

procedure Copy8BitStereo_ToDigital (var Src, Dest: Pointer; DestBase : dWord; Size: LongInt); Assembler;
{ Src      = current. Address of Clientbuffer
  Dest     = current. Address in Card RAM
  DestBase = Base Address for Digital Play in Card RAM
  Size     = Count to tranf. Bytes
}
ASM
          pushad

      { Source Address load }

          mov     ESI,[Src]
          mov     ESI,[ESI]

      { Destination Address load }

          mov     EDI,[Dest]
          mov     EDI,[EDI]                      { EDI = WritePtr }

      { Bytes to Destbuffer End check }

          mov     EAX,EDI
          sub     EAX,[DestBase]                 { EAX = ByteOffset to Chn.AudioData }
          mov     EDX,BufSize
          sub     EDX,EAX                        { EDX = Count Bytes to Buffer End }
          shr     EDX,2                          { EDX / 4 because 4x write progress in Src }

          mov     EBX,Size
          cmp     EBX,EDX
          jae     @Transfer                      { if Size >= Bytes to Buffer End }
          mov     EDX,EBX

      { Audio Data from lpDataAct (Src) -> WritePtr (Dest) }

@Transfer:
          cld
          sub     EBX,EDX                        { Sub Count Bytes of one REP Loop from all bytes }
          shr     EDX,1                          { EDX = Loop Counter for Src: Bytes -> Words }
@TrnsLp:
          mov     ECX,WriteCycles/2
          cmp     EDX,ECX
          jae     @Cycle                         { if Count of possible Loop Counts > WriteCycles }
          mov     ECX,EDX

@Cycle:   sub     EDX,ECX
          mov     EAX,[EDI]                      { PCI Read, to force PLX to free the local Bus }

@CycleLp: lodsb                                  { AL: left 8 Bit Sample }
          add     AL,$80                         { Midscale Correction }
          shl     EAX,24                         { Shift Audiobits to higher Word }
          stosd                                  { save left Sample to Dest }

          lodsb                                  { AL: right 8 Bit Sample }
          add     AL,$80                         { Midscale Correction }
          shl     EAX,24                         { shift Audiobits to higher Word }
          stosd                                  { save right Sample to Dest }
          loop    @CycleLp

          or      EDX,EDX                        { further Cycle necessary ? }
          jnz     @TrnsLp                        { yes }

          or      EBX,EBX                        { something else to transfer ? }
          jz      @Save

          mov     EDX,EBX
          mov     EDI,[DestBase]                 { EDI = Chn.AudioData (DestBase) }
          jmp     @Transfer

@Save:
      { Check, EDI = Buffer End }

          mov     EAX,EDI
          sub     EAX,[DestBase]                 { EAX = Offset to AudioData (DestBase) }
          cmp     EAX,BufSize
          jne     @SaveDest
          mov     EDI,[DestBase]                 { EDI = Buffer Begin }

      { Save Destination and Source Pointers }

@SaveDest:
          mov     EBX,[Dest]
          mov     [EBX],EDI

@SaveSource:
          mov     EBX,[Src]
          mov     [EBX],ESI

          popad
end;

procedure Copy24BitStereo_ToDigital (var Src, Dest: Pointer; DestBase : dWord; Size: LongInt); Assembler;
{ Src      = current. Address of Clientbuffer
  Dest     = current. Address in Card RAM
  DestBase = Base Address for Digital Play in Card RAM
  Size     = Count to tranf. Bytes
}
ASM
          pushad

      { Source Address load }

          mov     ESI,[Src]
          mov     ESI,[ESI]

      { Destination Address load }

          mov     EDI,[Dest]
          mov     EDI,[EDI]                      { EDI = WritePtr }

      { Size -> Stereosamples  }

          xor     EDX,EDX
          mov     EAX,Size                       { EAX = Count to trans. Bytes }
          mov     CX,6
          div     CX                             { AX = Count to trans. Stereosamples }
          movzx   EBX,AX                         { EBX = AX = Count to trans. Stereosamples }

      { Stereosamples to Destbuffer End check }

          mov     EAX,EDI
          sub     EAX,[DestBase]                 { EAX = ByteOffset to Chn.AudioData }
          mov     EDX,BufSize
          sub     EDX,EAX                        { EDX = Count Bytes to Buffer End }
          shr     EDX,3                          { ECX / 8 = Bytes -> 32 Bit StereoSamples }

          cmp     EBX,EDX
          jae     @Transfer                      { if Size >= Bytes to Buffer End }
          mov     EDX,EBX

      { Audio Data from lpDataAct (Src) -> WritePtr (Dest) }

@Transfer:
          cld
          sub     EBX,EDX                        { Sub Count Samples per Loop from Counts Samples overall }

@TrnsLp:
          mov     ECX,WriteCycles/2
          cmp     EDX,ECX
          jae     @Cycle                         { if Count of possible. Loop Counts > WriteCycles }
          mov     ECX,EDX

@Cycle:   sub     EDX,ECX
          mov     EAX,[EDI]                      { PCI Read, to force PLX to free the local Bus }

@CycleLp: lodsw                                  { AX = lower Bytes left Sample }
          shl     EAX,16                         { HiWord (EAX) = lower Bytes left Sample }
          lodsb                                  { AL = Higher Byte left Sample }
          ror     EAX,8                          { left Sample all in place }
          stosd                                  { left Sample save }

          lodsw                                  { AX = lower Bytes right Sample }
          shl     EAX,16                         { HiWord (EAX) = lower Bytes right Sample }
          lodsb                                  { AL = Higher Byte right Sample }
          ror     EAX,8                          { right Sample all in place }
          stosd                                  { right Sample save }
          loop    @CycleLp

          or      EDX,EDX                        { further Cycle necessary ? }
          jnz     @TrnsLp                        { yes }

          or      EBX,EBX                        { something else to transfer ? }
          jz      @Save

          mov     EDX,EBX
          mov     EDI,[DestBase]                 { EDI = Chn.AudioData (DestBase) }
          jmp     @Transfer

@Save:
      { Check, EDI = Buffer End }

          mov     EAX,EDI
          sub     EAX,[DestBase]                 { EAX = Offset to AudioData (DestBase) }
          cmp     EAX,BufSize
          jne     @SaveDest
          mov     EDI,[DestBase]                 { EDI = Buffer Begin }

      { Save Destination and Source Pointers }

@SaveDest:
          mov     EBX,[Dest]
          mov     [EBX],EDI

@SaveSource:
          mov     EBX,[Src]
          mov     [EBX],ESI

          popad
end;

{ *** Analog Record ******************************************************************************************* }

procedure Copy16BitStereo_FromAnalog (var Src, Dest: Pointer; SrcBase : dWord; Size: LongInt); Assembler;
{ Src      = current. Address in Card RAM
  Dest     = current. Address in Clientbuffer
  SrcBase  = Base Address for Analog Record  in Card RAM
  Size     = Count to tranf. Bytes
}
ASM
          pushad

      { Destination Address load }

          mov     EDI,[Dest]
          mov     EDI,[EDI]                      { EDI = WaveHdr^.lpDataAct }

      { Source Address (ReadPtr) load }

          mov     ESI,[Src]
          mov     ESI,[ESI]

      { Bytes to Destbuffer End check }

          mov     EAX,ESI
          mov     EDX,[SrcBase]                  { EDX = Chn.AudioData }
          sub     EAX,EDX                        { EAX = ByteOffset to Chn.AudioData }
          mov     ECX,BufSize
          sub     ECX,EAX                        { ECX = Count Bytes to Buffer End }

          mov     EBX,Size
          cmp     EBX,ECX
          jae     @Transfer                      { if Size >= Bytes to Buffer End }
          mov     ECX,EBX

      { Audio Data from lpDataAct (Src) -> WritePtr (Dest) }

@Transfer:
          sub     EBX,ECX                        { Sub Count Bytes of one REP Loop from all bytes }
          shr     ECX,2                          { Bytes -> dWords }
          cld
          rep     movsd

          or      EBX,EBX                        { something else to transfer ? }
          jz      @Save

          mov     ECX,EBX
          mov     ESI,EDX                        { ESI = Chn.AudioData (DestBase) }
          jmp     @Transfer

@Save:
      { Check, ESI = Buffer End }

          mov     EAX,ESI
          sub     EAX,EDX                        { EAX = Offset to AudioData (DestBase = EDX) }
          cmp     EAX,BufSize
          jne     @SaveDest
          mov     ESI,EDX                        { ESI = Buffer Begin }

      { Save Destination and Source Pointers }

@SaveDest:
          mov     EBX,[Dest]
          mov     [EBX],EDI

@SaveSource:
          mov     EBX,[Src]
          mov     [EBX],ESI

          popad
end;

procedure Copy8BitStereo_FromAnalog (var Src, Dest: Pointer; SrcBase : dWord; Size: LongInt); Assembler;
{ Src      = current. Address in Card RAM
  Dest     = current. Address in Clientbuffer
  SrcBase  = Base Address for Analog Record  in Card RAM
  Size     = Count to tranf. Bytes
}
ASM
          pushad

      { Destination Address load }

          mov     EDI,[Dest]
          mov     EDI,[EDI]                      { EDI = WaveHdr^.lpDataAct }

      { Source Address (ReadPtr) load }

          mov     ESI,[Src]
          mov     ESI,[ESI]

      { Bytes to Destbuffer End check }

          mov     EAX,ESI
          mov     EDX,[SrcBase]                  { EDX = Chn.AudioData }
          sub     EAX,EDX                        { EAX = ByteOffset to Chn.AudioData }
          mov     ECX,BufSize
          sub     ECX,EAX                        { ECX = Count Bytes to Buffer End }
          shr     ECX,1                          { double Read progress in Src related to Dest }

          mov     EBX,Size
          cmp     EBX,ECX
          jae     @Transfer                      { if Size >= Bytes to Buffer End }
          mov     ECX,EBX

      { Audio Data from lpDataAct (Src) -> WritePtr (Dest) }

@Transfer:
          sub     EBX,ECX                        { Sub Count Bytes of one REP Loop from all bytes }
          shr     ECX,1                          { Bytes -> Words }
          cld

@TrnsLp:  lodsd                                  { EAX = left (Lo) und right (Hi) Sample }
          xchg    AH,AL                          { Higher Part to AL }
          add     AL,$80                         { Midscale Correction }
          stosb

          shr     EAX,24                         { AL = Higher Part right Sample }
          add     AL,$80                         { Midscale Correction }
          stosb

          loop    @TrnsLp

          or      EBX,EBX                        { something else to transfer ? }
          jz      @Save

          mov     ECX,EBX
          mov     ESI,EDX                        { ESI = Chn.AudioData (DestBase) }
          jmp     @Transfer

@Save:
      { Check, ESI = Buffer End }

          mov     EAX,ESI
          sub     EAX,EDX                        { EAX = Offset to AudioData (DestBase = EDX) }
          cmp     EAX,BufSize
          jne     @SaveDest
          mov     ESI,EDX                        { ESI = Buffer Begin }

      { Save Destination and Source Pointers }

@SaveDest:
          mov     EBX,[Dest]
          mov     [EBX],EDI

@SaveSource:
          mov     EBX,[Src]
          mov     [EBX],ESI

          popad
end;

{ *** Digital Record ************************************************************************************ }

procedure Copy16BitStereo_FromDigital (var Src, Dest: Pointer; SrcBase : dWord; Size: LongInt); Assembler;
{ Src      = current. Address in Card RAM
  Dest     = current. Address in Clientbuffer
  SrcBase  = Base Address for Digital Record in Card RAM
  Size     = Count to tranf. Bytes
}
ASM
          pushad

      { Destination Address load }

          mov     EDI,[Dest]
          mov     EDI,[EDI]                      { EDI = WaveHdr^.lpDataAct }

      { Source Address (ReadPtr) load }

          mov     ESI,[Src]
          mov     ESI,[ESI]

      { Bytes to Srcbuffer End check }

          mov     EAX,ESI
          mov     EDX,[SrcBase]                  { EDX = Chn.AudioData }
          sub     EAX,EDX                        { EAX = ByteOffset to Chn.AudioData }
          mov     ECX,BufSize
          sub     ECX,EAX                        { ECX = Count Bytes to Buffer End }
          shr     ECX,1                          { double Read progress in Src related to Dest }

          mov     EBX,Size
          cmp     EBX,ECX
          jae     @Transfer                      { if Size >= Bytes to Buffer End }
          mov     ECX,EBX

      { Audio Data from lpDataAct (Src) -> WritePtr (Dest) }

@Transfer:
          sub     EBX,ECX                        { Sub Count Bytes of one REP Loop from all bytes }
          shr     ECX,2                          { CX = Loop Counter for DestBytes -> dWords }
          cld

@TrnsLp:  lodsd                                  { EAX = left Sample 32 Bit }
          shr     EAX,16                         { 32 Bit -> 16 Bit }
          stosw                                  { left Sample save }
          lodsd                                  { EAX = right Sample 32 Bit }
          shr     EAX,16                         { 32 Bit -> 16 Bit }
          stosw                                  { right Sample save }
          loop    @TrnsLp

          or      EBX,EBX                        { something else to transfer ? }
          jz      @Save

          mov     ECX,EBX
          mov     ESI,EDX                        { ESI = Chn.AudioData (DestBase) }
          jmp     @Transfer

@Save:
      { Check, ESI = Buffer End }

          mov     EAX,ESI
          sub     EAX,EDX                        { EAX = Offset to AudioData (DestBase = EDX) }
          cmp     EAX,BufSize
          jne     @SaveDest
          mov     ESI,EDX                        { ESI = Buffer Begin }

      { Save Destination and Source Pointers }

@SaveDest:
          mov     EBX,[Dest]
          mov     [EBX],EDI

@SaveSource:
          mov     EBX,[Src]
          mov     [EBX],ESI

          popad
end;

procedure Copy16BitMono_FromDigital (var Src, Dest: Pointer; SrcBase : dWord; Size: LongInt); Assembler;
{ Src      = current. Address in Card RAM
  Dest     = current. Address in Clientbuffer
  SrcBase  = Base Address for Digital Record in Card RAM
  Size     = Count to tranf. Bytes
}
ASM
          pushad

      { Destination Address load }

          mov     EDI,[Dest]
          mov     EDI,[EDI]                      { EDI = WaveHdr^.lpDataAct }

      { Source Address (ReadPtr) load }

          mov     ESI,[Src]
          mov     ESI,[ESI]

      { Bytes to Srcbuffer End check }

          mov     EAX,ESI
          mov     EDX,[SrcBase]                  { EDX = Chn.AudioData }
          sub     EAX,EDX                        { EAX = ByteOffset to Chn.AudioData }
          mov     ECX,BufSize
          sub     ECX,EAX                        { ECX = Count Bytes to Buffer End }
          shr     ECX,2                          { 4x Read progress in Src related to Dest }

          mov     EBX,Size
          cmp     EBX,ECX
          jae     @Transfer                      { if Size >= Bytes to Buffer End }
          mov     ECX,EBX

      { Audio Data from lpDataAct (Src) -> WritePtr (Dest) }

@Transfer:
          sub     EBX,ECX                        { Sub Count Bytes of one REP Loop from all bytes }
          shr     ECX,1                          { CX = Loop Counter for DestBytes -> Words }
          cld

@TrnsLp:  lodsd                                  { EAX = left Sample 32 Bit }
          shr     EAX,16                         { 32 Bit -> 16 Bit }
          stosw                                  { left Sample for Mono save }
          add     ESI,4                          { jump over right Sample in Src  }
          loop    @TrnsLp

          or      EBX,EBX                        { something else to transfer ? }
          jz      @Save

          mov     ECX,EBX
          mov     ESI,EDX                        { ESI = Chn.AudioData (DestBase) }
          jmp     @Transfer

@Save:
      { Check, ESI = Buffer End }

          mov     EAX,ESI
          sub     EAX,EDX                        { EAX = Offset to AudioData (DestBase = EDX) }
          cmp     EAX,BufSize
          jne     @SaveDest
          mov     ESI,EDX                        { ESI = Buffer Begin }

      { Save Destination and Source Pointers }

@SaveDest:
          mov     EBX,[Dest]
          mov     [EBX],EDI

@SaveSource:
          mov     EBX,[Src]
          mov     [EBX],ESI

          popad
end;

procedure Copy24BitStereo_FromDigital (var Src, Dest: Pointer; SrcBase : dWord; Size: LongInt); Assembler;
{ Src      = current. Address in Card RAM
  Dest     = current. Address in Clientbuffer
  SrcBase  = Base Address for Digital Record in Card RAM
  Size     = Count to tranf. Bytes
}
ASM
          pushad

      { Destination Address load }

          mov     EDI,[Dest]
          mov     EDI,[EDI]                      { EDI = WaveHdr^.lpDataAct }

      { Source Address (ReadPtr) load }

          mov     ESI,[Src]
          mov     ESI,[ESI]

      { Bytes to Srcbuffer End check }

          xor     EDX,EDX
          mov     EAX,Size                       { EAX = Count to trans. Bytes }
          mov     CX,6
          div     CX                             { AX = Count to trans. Stereosamples }
          movzx   EBX,AX                         { EBX = AX }

          mov     EAX,ESI
          mov     EDX,[SrcBase]                  { EDX = Chn.AudioData }
          sub     EAX,EDX                        { EAX = ByteOffset to Chn.AudioData }
          mov     ECX,BufSize
          sub     ECX,EAX                        { ECX = Count Bytes to Buffer End }
          shr     ECX,3                          { Bytes -> Stereosamples (32 Bit) }

          cmp     EBX,ECX
          jae     @Transfer                      { if Size (StereoSamples) >= StereoSamples to Buffer End }
          mov     ECX,EBX

      { Audio Data from lpDataAct (Src) -> WritePtr (Dest) }

@Transfer:
          sub     EBX,ECX                        { Sub Count Stereosamples of one REP Loop from overall count }
          cld

@TrnsLp:  lodsd                                  { EAX = left Sample 32 Bit }
          shr     EAX,8                          { 32 Bit -> 24 Bit }
          stosw                                  { left Sample Bits 0..15 save }
          shr     EAX,16
          stosb
          lodsd                                  { EAX = left Sample 32 Bit }
          shr     EAX,8                          { 32 Bit -> 24 Bit }
          stosw                                  { left Sample Bits 0..15 save }
          shr     EAX,16
          stosb
          loop    @TrnsLp

          or      EBX,EBX                        { something else to transfer ? }
          jz      @Save

          mov     ECX,EBX
          mov     ESI,EDX                        { ESI = Chn.AudioData (DestBase) }
          jmp     @Transfer

@Save:
      { Check, ESI = Buffer End }

          mov     EAX,ESI
          sub     EAX,EDX                        { EAX = Offset to AudioData (DestBase = EDX) }
          cmp     EAX,BufSize
          jne     @SaveDest
          mov     ESI,EDX                        { ESI = Buffer Begin }

      { Save Destination and Source Pointers }

@SaveDest:
          mov     EBX,[Dest]
          mov     [EBX],EDI

@SaveSource:
          mov     EBX,[Src]
          mov     [EBX],ESI

          popad
end;


