flat assembler
Message board for the users of flat assembler.

Index > DOS > DOS WAV player (infos recovered from troll thread)

Author
Thread Post new topic Reply to topic
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 30 Dec 2008, 23:23
1. http://asmsource.8k.com/source16.htm

2. (seems to be MASM , heh)

Code:
;**************************************************************************
;**************************************************************************
;     PLAYWAV.ASM
;     .WAV player on PC-speaker      Just 761 bytes!
;
;     (c) 1995 White Falcon Software House and Sapikli TM.
;
;     You can use it or modify as you wish; just gimme the credits!
;**************************************************************************
;**************************************************************************

.286c

psp_start       equ     80h
CR              equ     0Dh
LF              equ     0Ah
speed_div       equ     12

code            segment byte public
                assume  cs:code, ds:code

                org     100h

playwav         proc    far

;**************************************************************************
; Main Program
;**************************************************************************

start:          call    Init
                mov     si,psp_start
                xor     cx,cx
                mov     cl,cs:[si]
                or      cl,cl
                jnz     PW1
                jmp     PW8
PW1:            add     cx,si
                inc     si
                inc     si
PW2:            or      word ptr cs:[si],2020h  ; '  '
                cmp     byte ptr cs:[si],2Fh    ; '/'
                jz      PW5
                cmp     byte ptr cs:[si],20h    ; ' '
                jz      PW5
                mov     name_addr,si
PW3:            inc     si
                cmp     byte ptr [si],20h       ; ' '
                jz      PW4
                cmp     si,cx
                jg      PW4
                jmp     short PW3
PW4:            mov     byte ptr [si],0
                mov     param_yes,1
                jmp     PW7
PW5:            cmp     word ptr cs:[si],732Fh  ; '/s'
                jnz     PW6
                mov     param_yes,1
                add     si,3
                call    ASCII2Bin
                mov     speed,dx
                jmp     PW7
PW6:            cmp     word ptr cs:[si],762Fh  ; '/v'
                jnz     PW7
                mov     param_yes,1
                add     si,3
                call    ASCII2Bin
                mov     volume,dx
PW7:            inc     si
                cmp     si,cx
                jge     PW8
                jmp     PW2
PW8:            cmp     param_yes,1
                jz      PW10
                lea     dx,msg_main
                mov     ah,9
                int     21h
                int     20h
PW9:            jmp     PW13

PW10:           mov     dx,name_addr
                mov     ax,3D00h
                int     21h
                jc      PW9
                mov     bx,ax
                lea     dx,puffer
                mov     cx,0EA60h
                mov     ah,3Fh
                int     21h
                jc      PW9
                mov     file_len,ax
                mov     ah,3Eh
                int     21h
                lea     di,puffer
                mov     cx,file_len
                cld
cikl2:          xor     ax,ax                   ; Conversion
                mov     al,[di]
                sub     ax,80h
                imul    volume
                idiv    volume_u
                cmp     ax,7Fh
                jle     PW11
                mov     ax,7Fh
PW11:           cmp     ax,0FF80h
                jge     PW12
                mov     ax,0FF80h
PW12:           add     ax,80h
                div     vol_div
                mov     ah,al
                shl     al,1
                add     al,ah
                inc     ax
                stosb
                loop    cikl2
                call    PlayIt
                int     20h
PW13:           lea     dx,msg_fileerr
                mov     ah,9
                int     21h
                int     20h

param_yes       db      0               ; Shows if there's any parameter given
speed           dw      0
speed_u         dw      64h             ; Speed unit = 100
volume          dw      5               ; Maximum volume: 10
volume_u        dw      2
vol_div         db      10h
data_2          db      0
name_addr       dw      149h            ; Offset of the filename to be loaded
file_len        dw      0               ; Length of the .WAV file
msg_fileerr     db      'File error: can''t read file', CR, LF, '$'
msg_main        db      CR, LF,'  Usage:  PLAYWAV [FILENAME] [OPTIONS]'
        db      CR, LF
        db      CR, LF,'  OPTIONS:'
        db      CR, LF,'  /S:n    Speed selection  [500]'
        db      CR, LF,'  /V:n    Volume. Range for n is 1-10.  [5]'
        db      CR, LF, '$'
playwav         endp


;**************************************************************************
; PlayIt:  Plays the sound
;**************************************************************************

PlayIt          proc    near
                pusha
                push    cs
                pop     ds
                cli
                mov     al,90h
                out     43h,al
                in      al,61h
                or      al,3                    ; Speaker data enable
                                                ; Timer2 to speaker enable
                out     61h,al
                lea     bx,puffer
                add     bx,2Ch
                mov     cx,file_len
                mov     al,[bx]

PI1:            out     42h,al
                push    cx
                mov     cx,speed
cikl1:          loop    cikl1
                pop     cx
                mov     al,[bx]
                dec     data_2
                jnz     PI2
                mov     data_2,2
                jmp     short PI1
PI2:            inc     bx
                loop    PI1

                in      al,61h
                and     al,0FDh                 ; Disable speaker
                out     61h,al
                sti
                popa
                ret
PlayIt          endp

;**************************************************************************
; ASCII2Bin:  Calculates the numeric value of a string located on [si]
; Returns number in DX.
;**************************************************************************

ASCII2Bin       proc    near
                push    ax
                push    cx
                xor     dx,dx
A2B1:           mov     al,[si]
                sub     al,30h                  ; '0'
                jl      A2B2
                cmp     al,9
                jg      A2B2
                cbw
                push    ax
                mov     ax,dx
                mov     cx,0Ah
                mul     cx
                mov     dx,ax
                pop     ax
                add     dx,ax
                inc     si
                jmp     short A2B1
A2B2:           pop     cx
                pop     ax
                ret
ASCII2Bin       endp

; Local variables for the speed-calculating
timer_lo        dw      0
timer_hi        dw      0
count_lo        dw      0
count_hi        dw      0
ctr_addr        equ     046Ch   ; Address of timer tick counter in BIOS table
calc_lo         dw      0
calc_hi         dw      0

;**************************************************************************
; Init:  Initializes global variables, counts speed
;**************************************************************************

Init            proc    near
                push    es
                push    0
                pop     es
                mov     bx,ctr_addr
                mov     ax,es:[bx]
                mov     dx,es:[bx+2]
                mov     timer_lo,ax
                mov     timer_hi,dx
init_1:         mov     ax,timer_lo
                mov     dx,timer_hi
                cmp     es:[bx],ax              ; Wait for a new timer tick
                jnz     init_2
                cmp     es:[bx+2],dx
                jz      init_1
init_2:         mov     ax,es:[bx]
                mov     dx,es:[bx+2]
                mov     timer_lo,ax
                mov     timer_hi,dx
                mov     dx,timer_hi
                in      al,61h
init_3:         inc     word ptr count_lo       ; Count port writes in silence
                adc     count_hi,0
                mov     ah,al
                out     61h,al
                mov     cx,9
cikl3:          loop    cikl3           ; Wait a few to simulate other operations
                mov     cx,timer_lo
                cmp     es:[bx],cx
                jz      init_3                  ; Repeat until a new timer tick
                mov     dx,count_hi
                mov     ax,count_lo
                mov     cx,7
                div     cx
                mov     calc_lo,ax
                mov     calc_hi,dx
                add     ax,5
                xor     dx,dx
                mov     cx,speed_div
                div     cx
                sub     ax,8
                mov     speed,ax
                call    DetectProc
                cmp     ax,486h
                jnz     init_4
                mov     ax,speed
                mov     cx,0Dh
                mul     cx
                mov     cx,0Ah
                div     cx
                mov     speed,ax
init_4:         pop     es
                ret
Init            endp

;**************************************************************************
; DetectProc:  returns the processor type in AX (BCD coded) e.g. 0286h
;**************************************************************************

DetectProc      proc    near
                pushf
                push    bx
                push    cx
                pushf
                pop     ax
                and     ax,0FFFh
                push    ax
                popf
                pushf
                pop     ax
                and     ax,0F000h
                cmp     ax,0F000h
                jnz     DP_1
                mov     ax,86h
                jmp     short DP_4
DP_1:           or      ax,0F000h
                push    ax
                popf
                pushf
                pop     ax
                and     ax,0F000h
                jnz     DP_2
                mov     ax,286h
                jmp     short DP_4
DP_2:           mov     bx,sp
                and     sp,0FFFCh

; This instructions must be complied this way 'cause if you set processor
; type to 386 or higher for these few bytes, you must use 32 bit linking.

        db 66h, 9Ch ;                   pushfd
        db 66h, 58h ;                   pop     eax
        db 66h, 8Bh, 0C8h ;             mov     ecx,eax
        db 66h, 35h, 0, 0, 4, 0 ;       xor     eax,00040000h
        db 66h, 50h ;                   push    eax
        db 66h, 9Dh ;                   popfd
        db 66h, 9Ch ;                   pushfd
        db 66h, 58h ;                   pop     eax
                mov     sp,bx
        db 66h, 33h, 0C1h ;             xor     eax,ecx
                jnz     DP_3
                mov     ax,386h
                jmp     DP_4
DP_3:           mov     ax,486h
DP_4:           pop     cx
                pop     bx
                popf
                ret
DetectProc      endp

puffer          equ this byte

code            ends

                end     start
    


3. http://www.frontiernet.net/~fys/playwav.htm

4. http://www.o-bizz.de/qbdown/qbsound/speaker.zip (Quak-BASIC, but works well, and easy to port, "PC" speaker)

5.
Code:
; assemble with NBASM 00.24.94 or above
;   ( http://www.frontiernet.net/~fys/newbasic.htm )
;
;  NBASM playwav
;  Converted to FASM by Dex
PgPort     equ 83h
AddPort    equ 02h
LenPort    equ 03h
ModeReg    equ 49h
Channel    equ 01h
BasePort   equ 220h
Freq       equ 11000


           org  100h

start:     push cs                      ; make sure ds=es=cs
           push cs                      ;
           pop  ds                      ;
           pop  es                      ;

           mov  dx,StartIt
           mov  ah,09
           int  21h

           mov  di,Buffer               ; clear buffer contents
           mov  cx,51200                ;
           xor  al,al                   ;
           rep                          ;
           stosb                        ;

           mov  ax,3D00h                ; open file
           mov  dx,File1                ;
           int  21h                     ;
           jnc  File1OK                 ; if no error then cont.
           mov  dx,FileErr              ;   else print error msg and exit
           mov  ah,09                   ;
           int  21h                     ;
           jmp  Done                    ;
File1OK:   mov  bx,ax                   ; put handle in bx
           mov  cx,43                   ; read it
           mov  dx,Buffer               ; save into buffer
           mov  ah,3Fh                  ;
           int  21h                     ;
           mov  cx,51200                ; read it
           mov  dx,Buffer               ; save into buffer
           mov  ah,3Fh                  ; 
           int  21h                     ;
           mov  [Length1],ax            ; save len of file
           mov  ah,3Eh                  ; close the file
           int  21h                     ;

           call ResetDSP
           or   ax,ax
           jz   RstOK
           mov  dx,ResetErrS
           jmp  RstOK1
RstOK:     mov  dx,ResetOKS
           mov  ah,09
           int  21h

           mov  al,0DDh                 ; Left = 13, Right = 13 (15-highest)
           call MstrVol                 ; L = Hi Nibble, R = Lo Nibble

           mov  al,0D1h                 ; turn speaker(s) on
           call WriteDSP

           xor  eax,eax
           xor  edx,edx
           mov  ax,cs
           mov  dx,Buffer
           shl  eax,04h
           add  eax,edx
           mov  [MemLoc],eax
           call DMAPlay

           mov  dx,AnyKey
           mov  ah,09
           int  21h
           xor  ah,ah
           int  16h

Done:      mov  ah,4Ch                  ; exit to DOS
           int  21h
           ;
RstOK1:    mov  ah,09
           int  21h
           jmp  Done
DMAPlay:    ;uses eax ebx edx

           dec  word [Length1]
           mov  byte [Page1],00h

           mov  al,(Channel+4)
           mov  dx,0Ah
           out  dx,al
           xor  al,al
           mov  dx,0Ch
           out  dx,al
           mov  al,ModeReg
           mov  dx,0Bh
           out  dx,al
           mov  eax,[MemLoc]
           mov  dx,AddPort
           out  dx,al
           xchg al,ah
           out  dx,al
           mov  eax,[MemLoc]
           mov  edx,eax
           and  eax,65536
           jz   MemLocN1
           inc  byte [Page1]
MemLocN1:  mov  eax,edx
           and  eax,131072
           jz   MemLocN2
           add  byte [Page1],02
MemLocN2:  mov  eax,edx
           and  eax,262144
           jz   MemLocN3
           add  byte [Page1],04
MemLocN3:  mov  eax,edx
           and  eax,524288
           jz   MemLocN4
           add  byte [Page1],08
MemLocN4:  mov  dx,PgPort
           mov  al,[Page1]
           out  dx,al
           mov  dx,LenPort
           mov  ax,[Length1]
           out  dx,al
           xchg al,ah
           out  dx,al
           mov  dx,0Ah
           mov  al,Channel
           out  dx,al

           mov  al,40h
           call WriteDSP
           xor  edx,edx
           mov  eax,1000000
           mov  ebx,Freq
           div  ebx
           mov  ebx,eax
           mov  eax,256
           sub  eax,ebx
           call WriteDSP
           mov  al,14h
           call WriteDSP
           mov  ax,[Length1]
           call WriteDSP
           xchg al,ah
           call WriteDSP

           ret


MstrVol:    ;uses ax dx
           push ax
           mov  dx,(BasePort+4)
           mov  al,22h
           out  dx,al
           pop  ax
           inc  dx
           out  dx,al
           ret


ResetDSP:   ; uses cx dx

           mov  dx,(BasePort+6)
           mov  al,01
           out  dx,al
           mov  cx,50
WaitIt1:   in   al,dx
           loop WaitIt1
           xor  al,al
           out  dx,al
           mov  cx,50
WaitIt2:   in   al,dx
           loop WaitIt2
           mov  ah,0FFh                 ; part of Return Code
           mov  dx,(BasePort+14) ; Japheth fix error, originally 6
           in   al,dx
           and  al,80h
           cmp  al,80h
           jne  ResetErr
           mov  dx,(BasePort+10)
           in   al,dx
           cmp  al,0AAh
           jne  ResetErr
ResetOK:   xor  ax,ax                   ; return ax = 0 if reset ok
ResetErr:  ret


WriteDSP:   ;uses ax dx
           push ax
           mov  dx,(BasePort+12)
WaitIt:    in   al,dx
           and  al,80h
           jnz  WaitIt
           pop  ax
           out  dx,al
           ret


StartIt    db  13,10,'PlayWav   A utility for Playing WAV files     Version  1.03'
           db  13,10,'Forever Young Software(r)   (C)opyright 1984-2007',13,10,36
File1      db  'test.wav',0
FileErr    db  13,10,'Error opening file...',36
ResetOKS   db  13,10,'Reset DSP was successful.',36
ResetErrS  db  13,10,'Error Reseting DSP...',36
AnyKey     db  13,10,'Press a key to exit.',36

Length1    dw  00h
MemLoc     dd  0000h
Page1      db  00h

Buffer     rb 51200   ; 50k buffer at the end of our code
    


Quote:
IMO the ResetDSP proc may have an error. The second "mov dx,(Baseport+6)" should be "mov dx,(Baseport+14)" to make the program read the SB status register. Reading the SB "reset" register is nonsense.


Quote:
To reset DSP you should do the following:

- write 0x01 to port DSP_RESET (BASEPORT+0x06)
- wait for 3 microseconds (that's the time it takes DSP to reinitialize itself)
- write 0x00 to port DSP_RESET (BASEPORT+0x06)
- wait for 3 microsecond for results
- read byte (I'll refer to it as DATA) from DSP_DATAAVAIL (BASEPORT+0x0E) and read byte (I'll refer to it as READ) from DSP_READ (BASEPORT+0x0A). If bit 7 is set in DATA and READ is 0xAA then DSP is detected at BASEPORT. If condition failed no DSP is detect at base port BASEPORT.


WARNING: most of the codes do address ISA SB sound cards and won't work with PCI cards
Post 30 Dec 2008, 23:23
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.