pc speaker internal sound - how to do?

Started by nrdev, May 25, 2009, 12:42:35 PM

Previous topic - Next topic

nrdev


.model tiny
.dosseg
.stack 512
.data
.code
.386

_main   proc    near

           org  100h
start:     push ds
           pop  es
           mov  si,offset SomeTune
           
           mov  dx,61h                  ; turn speaker on
           in   al,dx                   ;
           or   al,03h                  ;
           out  dx,al                   ;

           mov  dx,43h                  ; get the timer ready
           mov  al,0B6h                 ;
           out  dx,al                   ;

LoopIt:    lodsw                        ; load desired freq.
           or   ax,ax                   ; if freq. = 0 then done
           jz   short LDone             ;
           mov  dx,42h                  ; port to out
           out  dx,al                   ; out low order
           xchg ah,al                   ;
           out  dx,al                   ; out high order
           lodsw                        ; get duration
           mov  cx,ax                   ; put it in cx (16 = 1 second)
           call PauseIt                 ; pause it
           jmp  short LoopIt

LDone:     mov  dx,61h                  ; turn speaker off
           in   al,dx                   ;
           and  al,0FCh                 ;
           out  dx,al                   ;

           int  20h                     ; exit to DOS

_main endp

  ; this routine waits for specified milliseconds
PauseIt    proc near uses ax bx cx dx
           xor  dx,dx                   ; cx = 16 = 1 second
           mov  ax,62500
           mul  cx
           mov  cx,dx
           xor  dx,dx
           mov  bx,offset PFlag
           mov  ax,8300h
           mov  [bx],al                 ; clear flag
           int  15h
WaitForIt: cmp  PFlag,00h
           je   short WaitForIt
           ret
PauseIt    endp

PFlag      db  00h          ; flag for pauseit routine
SomeTune   dw  1397,08
           dw  1397,08
           dw  1397,08
           dw  1318,06
           dw  1244,16
           dw  1046,04
           dw  1108,04
           dw  1174,04
           dw  1244,04
           dw  1174,08
           dw  1244,08
           dw  1318,08
           dw  1396,08
           dw  1480,08
           dw  1568,16
           dw  00h,00h

end


This code is meant to play sound trough the pc speaker, it compiles without errors, but when I start this app, I get error from the system something like 'illegal instruction'. Can someone make this code work?

dedndave

if you are running under XP, the system does not allow direct I/O with the hardware
i know this is confusing, because they "allow" it with int 10h
when you talk to the vga board, the I/O is actually emulated by the OS
the program may work under win 98, for example, because it does allow this kind of I/O
use the search feature in this forum as well as google'ing the
web for ways to accomplish what you want to do

nrdev

I have tried to find solution on the net but there ain't any, is it possible to make this code work on XP?

Jimg

This is how you would do it in 32-bit windows xp-

.686
.model Flat, Stdcall
option Casemap :None   
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data
SomeTune   dw  1397,08
           dw  1397,08
           dw  1397,08
           dw  1318,06
           dw  1244,16
           dw  1046,04
           dw  1108,04
           dw  1174,04
           dw  1244,04
           dw  1174,08
           dw  1244,08
           dw  1318,08
           dw  1396,08
           dw  1480,08
           dw  1568,16
           dw  00h,00h
.code
program:
    lea esi,SomeTune
    .repeat
        movzx eax,word ptr [esi]
        .break .if eax==0
        movzx ecx,word ptr [esi+2]
        imul ecx,(1000/16)  ; an approximation to your original timing
        add esi,4
        invoke Beep,eax,ecx
    .until zero?
    ret
end program


Not the catchiest tune I've ever heard.

Note that Beep wants its timing in milliseconds, not sixteenths of a second, so your timing can be much tighter.

nrdev

how should I compile this code? If I make it 32-bit it will open/close, if I make it as 16-bit it returns error that is kernel is not a vaild lib.

FORTRANS

#5
Hi,

   I had a little trouble assembling it (I'm not too
familiar with .model), and I thought .model tiny
was for a *.COM program.  And you put in a
stack.  But once I got it to assemble, it terminates
as soon as it trys to execute an OUT.  So what
Dave says seems to be happening in a Win2k
full screen session.  Timer ports are protected?

Steve N.

Edit:
   Sorry, that does not seem to be the problem.
Stepping through the program in DEBUG shows
a bad case of pilot error over here.

SRN

Edit #2

   I had to get rid of the "ORG 100h" and put in a
".STARTUP" to get things working.  So I get sound,
but my Win2k system does not process INT 15
correctly.  Maybe yours does, good luck.

SRN

Edit #3

   I booted up to another OS and the program now
runs.  So fix up the directives at the top, and use
EXE2BIN to make it a COM executable.  Your code
seems to work then.

QuoteNot the catchiest tune I've ever heard.

   I'll go along with that.

SRN

Jimg

Sorry, I forgot to say, assemble as a console program.  (32-bit, not dos 16-bit)

Jimg

e.g., save the code in tst.asm, and make a batch file like-

if exist "tst.obj" del "tst.obj"
if exist "tst.exe" del "tst.exe"
\masm32\bin\ml /c /coff "tst.asm"
\masm32\bin\Link /SUBSYSTEM:CONSOLE "tst.obj"


Sorry, I just realized we're in the 16-bit forum.  Please ignore everything I said unless you want to do it in normal 32-bit windows mode rather than dos, which you implied by saying you wanted it to run under windows xp, not dos.

So I guess the answer to your question-
QuoteI have tried to find solution on the net but there ain't any, is it possible to make this code work on XP?
is no, you can't make the original code work directly in XP.