summaryrefslogtreecommitdiff
path: root/piano/MYDZQ.ASM
blob: 7b1ccfa3db73a6be8bc0bd026e186b7bab7bebe2 (plain)
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
;;; Record:C-R, Play:C-P, Save:C-S, Load:C-L
        
RECKEY equ 12h
SAVEKEY equ 13h
PLAYKEY equ 10h
LOADKEY equ 0ch
P8255A_CTL equ 0e48bh
P8255A_A equ 0e488h
P8255A_B equ 0e489h
        
data segment
;;; data1: sine wave
        data1 db 80h,96h,0aeh,0c5h,0d8h,0e9h,0f5h,0fdh
              db 0ffh,0fdh,0f5h,0e9h,0d8h,0c5h,0aeh,96h
              db 80h,66h,4eh,38h,25h,15h,09h,04h
	      db 00h,04h,09h,15h,25h,38h,4eh,66h
;;; time: 8253 initial value
        time db 120,106,94,89,79,70,63,59
        
        msg db 'Press 1,2,3,4,5,6,7,8,ESC:',0dh,0ah,'$'
        keys db 'qwertyuasdfghjzxcvbnm'
        initval db ?
        tmpval db ?
        note dw 0
        raisetune dw ?
        recording db 0
;;; a big buffer for recording
        BUFSIZE equ 200h
        datasize dw 0
        buffer db BUFSIZE dup(?)
;;; File param
        fnmax db 0ffh
        fnlen db ?
        filename db 0ffh dup (?)
        handle dw ?
        prompt db 'Filename: ', '$'
;;; The Graphical Interface
        pianoui db 'aaabbbbcddddeeefffgggghiiiijkkkklll', 0
                db 'aaabbbbcddddeeefffgggghiiiijkkkklll', 0
                db 'aaabbbbcddddeeefffgggghiiiijkkkklll', 0
                db 'aaabbbbcddddeeefffgggghiiiijkkkklll', 0
                db 'aaabbbbcddddeeefffgggghiiiijkkkklll', 0
                db 'aaabbbbcddddeeefffgggghiiiijkkkklll', 0
                db 'aaaaaccccceeeeefffffhhhhhjjjjjlllll', 0
                db 'aaaaaccccceeeeefffffhhhhhjjjjjlllll', 0
                db 'aaaaaccccceeeeefffffhhhhhjjjjjlllll', 0
                db 'aaaaaccccceeeeefffffhhhhhjjjjjlllll', 0
        db 0ffh
        colors db 01111111b, 00001000b, 01111111b, 00001000b, 01111111b, 01111111b
                db 00001000b, 01111111b, 00001000b, 01111111b, 00001000b, 01111111b
        showcode db 0
        
data ends

stack segment stack
mysp db 100h dup (?)
sttop equ $-mysp
stack ends

code segment
        assume cs:code,ds:data
        extrn _transkey: near
        extrn _get_showcode: near
start:  mov ax,data
	mov ds,ax
        mov es,ax
        mov ax, stack
        mov ss, ax
        mov sp, sttop
        call graphic_init
        mov dx, 0510h
        call showui
        call ledoff

sss:    mov ah,0
	int 16h              ; getkey

	cmp al, 1bh
        jne TREC             ; ESC=>exit
        mov ax, 4c00h
        int 21h
        ;; program ends
TREC:
        cmp al, RECKEY
        jne TSAVE
        mov recording, 1
        mov datasize, 0
        call ledon
        jmp sss
TSAVE:
        cmp al, SAVEKEY
        jne TLOAD
        mov recording, 0
        call savetofile
        call ledoff
        jmp sss
TLOAD:
        cmp al, LOADKEY
        jne TPLAY
        call loadfile
        jmp sss
TPLAY:
        cmp al, PLAYKEY
        jne TSPACE
        call playaudio
        jmp sss
TSPACE:
        cmp al, ' '
        jne TBACKSP
        cmp recording, 1
        jne sss                 ; ignore it
        mov bx, datasize
        mov buffer[bx], 0
        inc datasize
        jmp sss
TBACKSP:
        cmp al, 08              ; backspace
        jne OTHERKEY
        cmp datasize, 0
        js nodec
        dec datasize            ; sub datasize by 1 regardless of the state
nodec:
        jmp sss
        
OTHERKEY:
        mov raisetune, 0
        cmp al, 'A'
        jl sss
        cmp al, 'Z'
        jg lowerletter
        mov raisetune, 1
        or al, 00100000b
                
lowerletter:    
        mov di, offset keys
        mov cx, 21
        repnz scasb
        jz trans                ; key found
        jmp sss
trans:  
        sub di, offset keys
        dec di               ; index = di-keys-1
        push di
        call _transkey
        add sp, 2
        cmp ax, -1
        jnz proctune
        jmp sss

proctune:       
        cmp ax, 16  ;; ax>=16 => high tune
        jl mediumlow
        and al, 00000111b
        mov note, al
        mov bx, offset time
        xlat
        shr al, 1
        jmp tune
mediumlow:
        cmp ax, 8  ;; ax>=8 => medium tune
        jl lowt
        and al, 00000111b
        mov note, al
        mov bx, offset time
        xlat
        jmp tune
lowt:
        and al, 00000111b
        mov note, al
        mov bx, offset time
        xlat
        shl al, 1
tune:
        cmp raisetune, 1
        jne process
        cbw
        push ax
        call raisehalf

process:
        mov initval, al
        ;; show ui
        push raisetune
        push note
        call _get_showcode
        mov showcode, al
        mov dx, 0510h
        call showui
        ;; record
        cmp recording, 1
        jne norec
        mov al, initval
        mov bx, datasize
        mov buffer[bx], al
        inc datasize
norec:
        mov al, initval
        mov tmpval, al
        call playtune
	jmp sss
        
exit:
        mov ah,4ch
	int 21h

playtune proc near
;;; play sound according to the init value of 8253
;;; initval store in tmpval
        push cx
        push si
        push dx
        
        mov cx,60               ; 60 waves
ddd:	mov si,0
lll:	mov al,data1[si]     ;取正弦波数据
        mov dx,0e490h
	out dx,al            ;放音
	call delay           ;调延时子程序
	inc si
	cmp si,32            ;是否取完32个数据
	jl lll               ;若没有,则继续
	loop ddd             ;总循环次数60是否完,没有,则继续

        pop dx
        pop si
        pop cx
        ret
playtune endp
        
delay proc near
;;; delay and play according to tmpval
ccc:    ;mov bx,offset time
        mov dx,0e483h        ;置8253通道0为方式0工作
	mov al,10h
	out dx,al
        mov dx, P8255A_CTL
	mov al,90h            ; a in, method 0
	out dx,al
	mov al,tmpval
        mov dx,0e480h
	out dx,al            ; output the initial value to 8253
kkk:    mov dx, P8255A_A
	in  al,dx            ;从8255A口读一字节
	test al,01           ;判PA0口是否为1
	jz  kkk              ;若不为1,则转KKK
	ret                  ;子程序返回
delay  endp

raisehalf proc near
;; al: initial value
;; output the new initial value to ax
;; 2^(1/12) = 1.0594631
;; first mul 10000, then div 10595
        push dx
        push cx
        cbw
        mov cx, 10000
        mul cx
        mov cx, 10595
        div cx
        pop cx
        pop dx
        ret
raisehalf endp

graphic_init proc near
        xor ah, ah
        mov al, 3
        int 10h
        mov ah, 6
        xor al, al
        mov bh, 00100000b
        mov ch, 0
        mov cl, 0
        mov dh, 24
        mov dl, 79
        int 10h
        ret
graphic_init endp
        
showui proc near
;;; show code stored in mem
;;; dh, dl: line, column

;;; initialize cursor
        push ax
        push bx
        push cx
        push si

        mov si, offset pianoui
        mov cx, 1
        push dx
show_loop:
        cmp byte ptr [si], 0ffh
        jz show_end
        cmp byte ptr [si], 0
        jnz show_cont
        pop dx
        inc dh
        push dx
        inc si
        jmp show_loop
show_cont:
        ;; set cursor
        xor bx, bx
        mov ah, 2
        int 10h

        mov al, [si]
        cmp byte ptr showcode, al
        jz set_color
        sub al, 'a'
        mov bx, offset colors
        xlat
        mov bl, al
        jmp show_sp
set_color:
        mov bl, 00011000b
show_sp:
        mov ah, 9
        mov al, ' '
        xor bh, bh
        int 10h

        inc dl
        inc si
        jmp show_loop
show_end:
        pop dx
        pop si
        pop cx
        pop bx
        pop ax
        ret
showui endp
        
playaudio proc near
        mov cx, datasize
        cmp cx, BUFSIZE
        ja pret
        mov bx, offset buffer
playloop:
        mov al, [bx]
        mov tmpval, al
        call playtune
        inc bx
        loop playloop
pret:   
        ret
playaudio endp
        
savetofile proc near
        call getfilename
        ;; create file
        mov ah, 3ch
        xor cx, cx
        mov dx, offset filename
        int 21h
        mov handle, ax
        ;; save data
        mov cx, datasize
        add cx, 2
        mov dx, offset datasize
        mov bx, handle
        mov ah, 40h
        int 21h
        ;; close file
        mov ah, 3eh
        int 21h
        ret
savetofile endp

loadfile proc near
        call getfilename
        ;; open file
        mov ah, 3dh
        mov dx, offset filename
        mov al, 0
        int 21h
        mov handle, ax
        ;; read
        mov dx, offset datasize
        mov bx, ax
        mov ah, 3fh
        mov cx, BUFSIZE
        int 21h
        ;; close
        mov ah, 3fh
        int 21h
        ret
loadfile endp
        
getfilename proc near
        mov ah, 2
        mov bh, 0
        mov dx, 1410h
        int 10h
        mov dx, offset prompt
        mov ah, 9
        int 21h
        mov dx, offset fnmax
        mov ah, 0ah
        int 21h
        mov bx, offset filename
        mov al, fnlen
        cbw
        add bx, ax
        mov byte ptr [bx], 0
        ret
getfilename endp

ledon proc near
        mov dx, P8255A_CTL
        mov al, 10000000b       ; method 0, b out
        out dx, al
        mov dx, P8255A_B
        mov al, 1
        out dx, al
        ret
ledon endp

ledoff proc near
        mov dx, P8255A_CTL
        mov al, 10000000b       ; method 0, b out
        out dx, al
        mov dx, P8255A_B
        mov al, 0
        out dx, al
        ret
ledoff endp
        
code   ends
        end  start