-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpcmadlb2.asm
240 lines (192 loc) · 3.8 KB
/
pcmadlb2.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
; Written by Leonardo Ono (ono.leo@gmail.com)
; 10 nov 2020
; Target OS: DOS
; use: nasm pcmadlb2.asm -o pcmadlb2.com -f bin
;
; update: 14 feb 2020 - this program uses timer 0
; 10 nov 2020 - finally it works thanks to Jim Leonard.
;
; Reference: http://www.dcee.net/Files/Programm/Sound/adldigi.arj
; Thanks to Jim Leonard for 'wait until 952h timer ticks' routine
cpu 8086
bits 16
org 100h
start:
call reset_all_registers
; bl = register
; bh = value
mov bl, 20h
mov bh, 21h
call write_adlib
mov bl, 60h
mov bh, 0f0h
call write_adlib
mov bl, 80h
mov bh, 0f0h
call write_adlib
mov bl, 0c0h
mov bh, 01h
call write_adlib
mov bl, 0e0h
mov bh, 0
call write_adlib
mov bl, 43h
mov bh, 3fh
call write_adlib
mov bl, 0b0h
mov bh, 1h
call write_adlib
mov bl, 0a0h
mov bh, 8fh
call write_adlib
mov bl, 0b0h
mov bh, 2eh
call write_adlib
; --- wait until 952h (2386) timer ticks have passed --
; --- kindly provided by Jim Leonard --
cli ;disable interrupts
mov al,0 ;reprogram timer
out 43h,al ;timer-0 count-mode
in al,40h ;read low-byte count
mov bl,al ;save in BL
in al,40h ;read high-byte count
mov bh,al ;save in BH
.delay3:
mov al,0 ;reprogram timer
out 43h,al ;timer-0 count-mode
in al,40h ;read low-byte count
mov cl,al ;save in CL
in al,40h ;read high-byte count
mov ch,al ;save in CH
neg cx
add cx, bx ;compute clocks gone by
cmp cx,2386
jb .delay3
sti
; ---
mov bl, 0b0h
mov bh, 20h
call write_adlib
mov bl, 0a0h
mov bh, 0h
call write_adlib
call start_fast_clock
; --- start playback ---
call get_current_time
mov [last_time + 2], dx
mov [last_time], ax
mov si, 0
.loop:
; send byte audio sample
mov bh, [sound_data + si]
mov bl, 255
sub bl, bh ; lowest value has the highest volume
mov bh, bl
mov cl, 2
shr bh, cl ; convert to 6-bit sample
; bl = register
; bh = value
mov bl, 40h
; mov bh, -- -> bh already has the 6-bit sample
call write_adlib
.delay:
call get_current_time
cmp dx, [last_time + 2]
jne .break_delay
cmp ax, [last_time]
jbe .delay
.break_delay:
mov [last_time + 2], dx
mov [last_time], ax
mov ah, 1
int 16h
jnz .exit
inc si
cmp si, 51529
jb .loop
.exit:
call stop_fast_clock
mov ax, 4c00h
int 21h
reset_all_registers:
mov bl, 0h
mov bh, 0
.next_register:
; bl = register
; bh = value
call write_adlib
inc bl
cmp bl, 0f5h
jbe .next_register
.end:
ret
; bl = register
; bh = value
write_adlib:
push ax
push bx
push cx
push dx
push bp
push si
push di
mov dx, 388h
mov al, bl
out dx, al
mov cx, 6
.delay_1:
in al, dx
loop .delay_1
mov dx, 389h
mov al, bh
out dx, al
mov dx, 388h
mov cx, 35
.delay_2:
in al, dx
loop .delay_2
pop di
pop si
pop bp
pop dx
pop cx
pop bx
pop ax
ret
; count = 1193180 / sampling_rate
; sampling_rate = 4000 cycles per second
; count = 1193180 / 4000 = 298 (in decimal) = 12a (in hex)
start_fast_clock:
cli
mov al, 36h
out 43h, al
mov al, 2ah ; low 2ah
out 40h, al
mov al, 1h ; high 01h
out 40h, al
sti
ret
stop_fast_clock:
cli
mov al, 36h
out 43h, al
mov al, 0
out 40h, al
mov al, 0
out 40h, al
sti
ret
; dx:ax = get current time
get_current_time:
cli
push es
mov ax, 0
mov es, ax
mov ax, [es:46ch]
mov dx, [es:46ch + 2]
pop es
sti
ret
last_time dd 0
sound_data:
incbin "kingsv.wav" ; 51.529 bytes