组装播放音频文件TASM 16位

时间:2018-01-29 17:41:23

标签: audio assembly x86 dos tasm

您好我正在为学校项目编写游戏,而且我在播放音频文件时遇到问题。  我能够播放该文件但问题是该程序冻结并停止响应用户

音乐文件代码

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

在我调用此proc之后我调用int 16h从用户读取密钥但音乐文件阻止了IO 有人知道我需要做什么吗? 抱歉,我的英语不好  我在装配方面有点新意,所以我不太好。

1 个答案:

答案 0 :(得分:1)

您要做的是“并行化”您的游戏代码(不使用线程)。关于如何执行此操作的选项很少:

  1. 交错代码

    这是最简单的实施方式。所以你应该拥有这样的游戏架构:

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

    这种架构允许游戏以“并行”方式运行其所有任务。如果您的任务较慢,则可以将音乐交错一点

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

    如果任何任务真的很慢,那么你需要将声音直接插入其中,否则你会发出不稳定的声音。这是一个例子(没有声音):

    这是声音(但不是游戏):

    您需要使键盘测试无阻塞。从我的无信号演示中获取它是这样的:

        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. 使用PIT作为生成器播放声音

    我没有使用此功能,但 IIRC PIT 可配置为与扬声器播放恒定频率。因此,不是设置扬声器开/关,而是设置每帧左右的频率......这将在后台播放,在此期间 CPU 可以执行其他操作......

  3. 使用PIT作为计时器在后台播放声音

    为了更好的计时和在与游戏代码平行的背景中播放声音,您可以将播放的声音完全移至PIT ISR,这可以在1193180.0/16bit_divider Hz运行,因此设置 PIT < / strong>以目标声音采样频率为目标。为它设置 ISR 并在其中获取/播放单个位....

    如果您使用PWM和多个采样频率,您可以将扬声器变为 DAC ,甚至可以播放 PCM *.wav文件。

    在这种情况下,你根本没有在游戏循环中交错的声音代码。

  4. 请勿忘记在退出前将频率设置为18.2 Hz ,因为 MS-DOS 并且游戏将其用于计时。通过仅改变 PIT 频率,可以加快许多游戏的速度。此外,当您更改PIT频率和ISR时,最好从新ISR呼叫频率为18.2Hz的原始ISR。

    有关PC MS-DOS和游戏的详细信息,请参阅:

    • PCGPE 1.0
    • WPCGPE 1.0这应该是*.hlp格式(Win7 +需要Windows6.1-KB917607补丁,因为他们停止支持它)

    这是从我知道的装配开始的最佳选择:

    Z80 CPU 是捷克语,我不知道有任何翻译......