组装播放音频文件 TASM 16 位
Assembly playing audio file TASM 16 bit
您好,我正在为学校项目编写游戏,但在播放音频文件时遇到问题。
我能够播放文件,但问题是程序冻结并停止响应用户
音乐文件代码
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
有人知道我需要做什么吗?
顺便说一下,对不起我的英语不好
我是装配新手,所以我不太好
您想要做的是 "parallelize" 您的游戏代码(不使用线程)。关于如何执行此操作的选项很少:
交错代码
这是最容易实现的方法。所以你的游戏架构应该是这样的:
loop:handle input
handle game logic
render frame
play sound (20-40ms)
jmp loop
此架构将允许游戏 运行 在 "parallel" 中完成所有任务。如果你的任务比较慢,你可以多插入一点音乐
loop:handle input
play sound (~10ms)
handle game logic
play sound (~10ms)
render frame
play sound (~10ms)
jmp loop
如果任何任务真的很慢,那么您需要直接将声音插入其中,否则声音会断断续续。这是一个例子(没有声音):
这是有声的(但不是游戏):
- No Signal demo
您需要使您的键盘测试成为非阻塞的。取自我的无信号演示,它是这样完成的:
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
使用 PIT 作为发生器播放声音
我没有使用这个,但是 IIRC PIT 可以配置为使用扬声器播放恒定频率。因此,无需设置扬声器 on/off,您只需设置其每帧左右的频率...这将在后台播放,在此期间 CPU 可以执行其他东西...
使用 PIT 作为定时器在后台播放声音
为了更好的定时和在后台播放与游戏代码平行的声音,您可以将播放的声音完全移动到 PIT ISR,它可以在 1193180.0/16bit_divider Hz
运行,因此设置 PIT 到目标声音采样频率。为其设置 ISR 并在其中设置 fetch/play 单个位....
如果你使用PWM和采样频率的倍数你可以把Speaker变成DAC甚至播放PCM*.wav
文件。
在这种情况下,您根本不会在游戏循环中插入声音代码。
不要忘记在退出前将 PIT 频率设置回 18.2 Hz 因为 MS-DOS 和游戏用它来计时。许多游戏可以通过单独更改 PIT 频率来加速。此外,当您更改 PIT 频率和 ISR 时,最好从新的 ISR 调用频率为 18.2Hz 的原始 ISR。
有关 PC MS-DOS 和游戏的更多信息,请参阅:
- PCGPE 1.0
- WPCGPE 1.0 这应该是
*.hlp
格式(你需要 Windows6.1-KB917607
Win7+ 补丁,因为他们停止支持它)
这是我所知道的最适合入门的汇编:
但是 Z80 CPU 是捷克语,我不知道有任何翻译....
您好,我正在为学校项目编写游戏,但在播放音频文件时遇到问题。 我能够播放文件,但问题是程序冻结并停止响应用户
音乐文件代码
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 有人知道我需要做什么吗? 顺便说一下,对不起我的英语不好 我是装配新手,所以我不太好
您想要做的是 "parallelize" 您的游戏代码(不使用线程)。关于如何执行此操作的选项很少:
交错代码
这是最容易实现的方法。所以你的游戏架构应该是这样的:
loop:handle input handle game logic render frame play sound (20-40ms) jmp loop
此架构将允许游戏 运行 在 "parallel" 中完成所有任务。如果你的任务比较慢,你可以多插入一点音乐
loop:handle input play sound (~10ms) handle game logic play sound (~10ms) render frame play sound (~10ms) jmp loop
如果任何任务真的很慢,那么您需要直接将声音插入其中,否则声音会断断续续。这是一个例子(没有声音):
这是有声的(但不是游戏):
- No Signal demo
您需要使您的键盘测试成为非阻塞的。取自我的无信号演示,它是这样完成的:
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
使用 PIT 作为发生器播放声音
我没有使用这个,但是 IIRC PIT 可以配置为使用扬声器播放恒定频率。因此,无需设置扬声器 on/off,您只需设置其每帧左右的频率...这将在后台播放,在此期间 CPU 可以执行其他东西...
使用 PIT 作为定时器在后台播放声音
为了更好的定时和在后台播放与游戏代码平行的声音,您可以将播放的声音完全移动到 PIT ISR,它可以在
1193180.0/16bit_divider Hz
运行,因此设置 PIT 到目标声音采样频率。为其设置 ISR 并在其中设置 fetch/play 单个位....如果你使用PWM和采样频率的倍数你可以把Speaker变成DAC甚至播放PCM
*.wav
文件。在这种情况下,您根本不会在游戏循环中插入声音代码。
不要忘记在退出前将 PIT 频率设置回 18.2 Hz 因为 MS-DOS 和游戏用它来计时。许多游戏可以通过单独更改 PIT 频率来加速。此外,当您更改 PIT 频率和 ISR 时,最好从新的 ISR 调用频率为 18.2Hz 的原始 ISR。
有关 PC MS-DOS 和游戏的更多信息,请参阅:
- PCGPE 1.0
- WPCGPE 1.0 这应该是
*.hlp
格式(你需要Windows6.1-KB917607
Win7+ 补丁,因为他们停止支持它)
这是我所知道的最适合入门的汇编:
但是 Z80 CPU 是捷克语,我不知道有任何翻译....