Assembly playing audio file TASM 16 bit

2020-05-09 17:43发布

Hello i'm writing a game for school project and i'm having problems to play an audio file. I was able to play the file but the problem is that then the program freezes and stop responding to the user

The music file code

proc read Near ; Read next sample
    push bx
    push cx
    push dx
    mov ah, 3Fh
    mov bx, [filehandle]
    mov cx, 1
    lea dx, [Buffer]
    int 21h
    jc errorcode
    mov al, [Buffer]
    xor ah, ah
    mov bx, 54
    mul bx
    ; mov ax, dx ; Result is in DX because we need to div by 65536 which is all of AX
    shr ax, 8
    pop dx
    pop cx
    pop bx
    ret
endp
proc br Near; Print line break
    push dx
    push ax
    mov dl, 10
    mov ah, 2
    int 21h
    mov dl, 13
    mov ah, 2
    int 21h
    pop ax
    pop dx
    ret
endp
proc PlayMusic Near
    mov ah, 3Dh
    xor al, al
    lea dx, [filename]
    int 21h
    mov [filehandle], ax
    call br
    mov al, 90h
    out 43h, al
in al, 61h
    or al, 3
    out 61h, al
    cli
    mov ax, 0
totalloop:
    call read ; Read file
    out 42h, al ; Send data
    mov bx, ax
    mov cx, [delay]
portloop:
    loop portloop
    mov ax, bx
    out 42h, ax ; Send data
    mov cx, [delay]
rloop:
    loop rloop
    call read
    jmp totalloop
    ret
errorcode:
    ; Close
    sti
    mov al, 86h
    out 43h, al
    mov ah, 3Eh
    mov bx, [filehandle]
    int 21h
    pop dx
    pop cx
    pop bx
    ret
endp PlayMusic

and after i call this proc i'm calling int 16h to read a key from the user but the music file blocks the IO someone have an idea what I need to do? sorry for my bad English by the way and i'm kind of new in assembly so i'm not so good

1条回答
beautiful°
2楼-- · 2020-05-09 18:16

What you want to do is "parallelize" your game code (without using threads). There are few options on how to do this:

  1. interleave the code

    This is the easiest way to implement. So you should have your game architecture like this:

    loop:handle input
         handle game logic
         render frame
         play sound (20-40ms)
         jmp loop
    

    This architecture will allow the game to run all its task in "parallel". If your tasks are slower you can interleave the music a bit more

    loop:handle input
         play sound (~10ms)
         handle game logic
         play sound (~10ms)
         render frame
         play sound (~10ms)
         jmp loop
    

    if any task is really slow then you need to interleave the sound into it directly otherwise you would have choppy sound. Here is an example of this (without sound):

    And this is with sound (but not a game):

    You need to make your keyboard test non blocking. Taken from my No Signal demo it is done like this:

        mov ah,1    ; non blocking key test
        int 16h
        jz keyr0
        sub ax,ax   ; blocking key test
        int 16h
        ; here handle the key press...
    keyr0:          ; here continues your code
    
  2. play the sound using PIT as generator

    I did not use this but IIRC the PIT can be configured to play a constant frequency with the speaker. So instead of setting Speaker on/off you just set its frequency per each frame or so ... This will play in the background during which time the CPU can do other stuff...

  3. play the sound in background using PIT as timer

    For much better timing and playing the sound in the background parallel to your game code you can move the sound playing to the PIT ISR entirely which can operate at 1193180.0/16bit_divider Hz so set the PIT to target sound sampling frequency. Set the ISR for it and fetch/play single bit in it....

    If you use PWM and multiple of sampling frequency you can turn Speaker into DAC playing even PCM *.wav files.

    In this case you do not have the sound code interleaved in the game loop at all.

DO NOT FORGET TO SET PIT FREQUENCY BACK TO 18.2 Hz BEFORE EXIT because MS-DOS and games use it for timing. Many games can be speed-up by changing the PIT frequency alone. Also when you change PIT frequency and ISR it is a good idea to call the original ISR with 18.2Hz frequency from your new ISR.

For more info about PC MS-DOS and games see:

  • PCGPE 1.0
  • WPCGPE 1.0 this should be *.hlp format (you need Windows6.1-KB917607 patch for Win7+ as they stopped supporting it)

This is the best for starting with assembly I know of:

but it is in Czech for Z80 CPU and I do not know of any translations ....

查看更多
登录 后发表回答