      DOSSEG
      .MODEL SMALL
      .STACK 200h
      .CODE
      .386
      ASSUME CS:@CODE, DS:@CODE
      Ideal

哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪

OldInt  dd  ?

BaseAddress dw 220h

MixedSeg  dw  ?
SampleSeg dw  ?
SampleOff dw  0

FileName  db  "jamhot.sam",0   ;you need to put your filename here...
SamLength dw  ?

哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
      
PROC TurnOffSpeaker NEAR
    mov     al,0d3h         ;turn off speaker
    call    Sendcommand
    ret
ENDP TurnOffSpeaker

    ;al = command
PROC SendCommand NEAR
    push    dx
    push    ax
    mov     dx,[cs:BaseAddress]
    add     dx,0ch
sendcommandloop:
    in      al,dx
    or      al,al
    js      sendcommandloop
    pop     ax
    out     dx,al
    pop     dx
    ret
ENDP SendCommand

PROC TurnOnSpeaker NEAR
    mov     al,0d1h
    call    SendCommand
    ret
ENDP TurnOnSpeaker

    ;input- none 
    ;output al=0 successful
    ;       al=1 unsuccessful
    ;Destroys AX,DX,CX
    ;
PROC DspReset NEAR
    mov     dx,[cs:baseaddress]
    add     dx,06h
    mov     al,1
    out     dx,al
    mov     cx,1000
    push    di
    rep     lodsb         ;wait for at least 3鍿
    pop     di
    xor     al,al
    out     dx,al

    add     dx,8          ;check status (22eh)
    mov     cx,12000
waitforstat:
    in      al,dx
    dec     cx
    je      errorstat
    or      al,al
    js      WaitForStat

    mov     cx,10000
    sub     dx,4          ;(22ah)      
waitforstat2:
    in      al,dx
    dec     cx
    je      errorstat
    cmp     al,0aah
    jne     waitforstat2
    mov     al,0
    ret
errorstat:
    mov     al,1
    ret
ENDP DspReset

PROC SetUpInterrupt NEAR
    pusha
    push    ds

    mov   ax,0
    mov   ds,ax
    mov   bx,8*4                  ;interrupt 8
    mov   ax,[ds:bx]
    mov   [Word LOW  cs:OldInt],ax
    mov   ax,[ds:bx+2]
    mov   [Word HIGH cs:OldInt],ax

    cli
    mov   [Word ds:bx],offset TimerInt
    mov   [ds:bx+2],cs

    mov   al,36h
    out   43h,al                  ; timer program

    mov   ax,1193180/8000         ; # of ticks between interrupts
                                  ; Clock Freq / HZ
    out   40h,al
    mov   al,ah
    out   40h,al
    sti

    pop     ds
    popa
    ret
ENDP SetUpInterrupt
  
PROC RemoveInterrupt NEAR
    pusha
    push    ds
    
    cli
    mov ax,0
    mov ds,ax
    mov bx,8*4
    mov ax,[Word cs:OldInt]
    mov [ds:bx],ax
    mov ax,[Word cs:OldInt+2]
    mov [ds:bx+2],ax
    mov al,36h
    out 43h,al
    xor al,al
    out 40h,al
    out 40h,al
    sti
    
    pop     ds
    popa
    ret
ENDP  RemoveInterrupt

PROC TimerInt FAR
    pusha
    push    fs
    
    mov     fs,[cs:SampleSeg]
    mov     di,[cs:SampleOff]
    
    mov     al,10h + 0b            ;Direct 8-bit DAC command
    call    SendCommand

    mov     al,[fs:di]
    add     al,128            ;change SAM data (-128 to 127) to SB data 0-255
    call    SendCommand
    
    inc     [cs:SampleOff]
    mov     ax,[CS:SamLength]
    cmp     [cs:SampleOff],ax
    jb      @@NotOver
    mov     [cs:SampleOff],0

@@NotOver:
    mov     al,20h      ;acknowledge hardware interrupt
    out     20h,al

    pop     fs
    popa
    iret
ENDP TimerInt

  ; returns -1 if load not successful
PROC  LoadSample NEAR
    pusha
    push    ds

    mov     ax,cs
    mov     ds,ax
    mov     dx,offset FileName
    mov     ax,3D00h        ;open the file
    int     21h
    jc      @@Error

    mov     bx,ax
    xor     dx,dx             ;load at offset 0
    mov     cx,0ffffh         ;read in a whole segments worth
    mov     ds,[cs:SampleSeg]
    mov     ax,3F00h          ; Load in the sample
    int     21h

    mov     [cs:SamLength],ax

    mov     ax,3E00h          ;close the file
    int     21h

    ;*******  HERE'S THE PART WHERE THE SAMPLES ARE MIXED ! *******
    push    es
    mov     es,[cs:MixedSeg]
    mov     cx,[cs:SamLength]
    mov     bp,cx

    mov     di,1500
    mov     si,0
MixLoop:
    
    mov     al,[ds:si]
    sar     al,1        ;divide by 2, cause we're mixing 2 samples together
    mov     [es:si],al

    mov     al,[ds:di]
    sar     al,1
    add     [es:si],al

    inc     si
    inc     di
    cmp     di,bp
    jb      NotExceeded
    mov     di,0
NotExceeded:
    loop    MixLoop

    mov     [cs:SampleSeg],es

    pop     es
    pop     ds
    popa
    xor     ax,ax
    ret

@@Error:
    pop     ds
    popa
    mov     ax,-1
    ret
ENDP  LoadSample

哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪

START:
    mov   bx,ss
    add   bx,20h            ;put sample right after stack
    mov   [cs:SampleSeg],bx
    add   bx,1000h
    mov   [cs:MixedSeg],bx

    call  LoadSample
    or    al,al
    jne   ByeBye

    call  DspReset
    call  TurnOnSpeaker
    call  SetUpInterrupt    ;starts going after this line

    mov   ah,0
    int   16h               ;wait for a keypress
    
    call  RemoveInterrupt
    call  TurnOffSpeaker

ByeBye:    
    mov   ax,4c00h
    int   21h

END START
