Repository navigation
Expand file tree
/
Copy pathDMASOUND.ASM
More file actions
2771 lines (2198 loc) · 86.2 KB
/
Copy pathDMASOUND.ASM
File metadata and controls
2771 lines (2198 loc) · 86.2 KB
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
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ DMASOUND.ASM ÛÛ
;ÛÛ ÛÛ
;ÛÛ IBM Audio Interface Library ÛÛ
;ÛÛ ÛÛ
;ÛÛ Digital sound driver/emulator for Sound Blaster-type audio devices ÛÛ
;ÛÛ ÛÛ
;ÛÛ Version 2.00 of 09-Oct-91: Initial V2.0 version, derived from V1.05 ÛÛ
;ÛÛ 2.01 of 21-Nov-91: Autodetects Thunderboard as Sound Blaster ÛÛ
;ÛÛ Dual-buffer playback flag checks modified ÛÛ
;ÛÛ 2.02 of 14-Dec-91: PAS DMA timer pauses/resumes correctly ÛÛ
;ÛÛ 2.03 of 18-Dec-91: Standard SB speaker control fixed ÛÛ
;ÛÛ 2.04 of 13-Jan-92: Stereo .VOC file support added ÛÛ
;ÛÛ 2.05 of 20-Jan-92: I/O timeout w/beep added ÛÛ
;ÛÛ Sample rate high byte always cleared ÛÛ
;ÛÛ 2.06 of 18-Feb-92: IRQ delay during halt_DMA ÛÛ
;ÛÛ sysex_wait() calls replace loops ÛÛ
;ÛÛ Send >1 bytes during detection ÛÛ
;ÛÛ Do shutdown only if initialized ÛÛ
;ÛÛ 2.07 of 2-Apr-92: Set valid sample rate during detection ÛÛ
;ÛÛ 2.10 of 4-Apr-92: Ad Lib Gold support added ÛÛ
;ÛÛ AIL_format_VOC_file/_sound_buffer() added ÛÛ
;ÛÛ DMA word count checked in IRQ handlers ÛÛ
;ÛÛ 2.11 of 13-May-92: IRQ delay skipped if .VOC playback ended ÛÛ
;ÛÛ 2.12 of 29-May-92: PAS default volume reduced ÛÛ
;ÛÛ 2.13 of 29-Jun-92: PAS +/16 compatibility issues resolved ÛÛ
;ÛÛ ALG panning disabled in mono mode ÛÛ
;ÛÛ SBLASTER silence-packing problems fixed ÛÛ
;ÛÛ 2.14 of 17-Aug-92: CHECK_DMAC option added ÛÛ
;ÛÛ 2.15 of 15-Sep-92: WAIT_FALSE_IRQ option added ÛÛ
;ÛÛ 2.16 of 14-Nov-92: Alternative fix for unwanted SBlaster ÛÛ
;ÛÛ IRQs implemented ÛÛ
;ÛÛ DMA terminal count of 0 accepted ÛÛ
;ÛÛ ÛÛ
;ÛÛ Author: John Miles ÛÛ
;ÛÛ 8086 ASM source compatible with Turbo Assembler v2.0 or later ÛÛ
;ÛÛ ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ Copyright (C) 1991, 1992 Miles Design, Inc. ÛÛ
;ÛÛ ÛÛ
;ÛÛ Miles Design, Inc. ÛÛ
;ÛÛ 10926 Jollyville #308 ÛÛ
;ÛÛ Austin, TX 78759 ÛÛ
;ÛÛ (512) 345-2642 / FAX (512) 338-9630 / BBS (512) 454-9990 ÛÛ
;ÛÛ ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
MODEL MEDIUM,C ;Procedures far, data near by default
LOCALS __ ;Enable local labels with __ prefix
JUMPS ;Enable auto jump sizing
;
;External/configuration equates
;
FALSE equ 0
TRUE equ -1
PAS_FILTER equ FALSE ;TRUE to enable PAS PCM antialiasing
;(also degrades FM treble response)
CHECK_DMAC equ TRUE ;FALSE to inhibit checking for end-
;of-DMA conditions; may need to be
;turned off for proper operation with
;non-100% IBM-compatible systems and
;V86 host software
WAIT_FALSE_IRQ equ FALSE ;TRUE to wait 140 ms. after stopping
;DMA transfers -- original way to
;avoid certain Sound Blaster hardware
;glitches
DAC_STOPPED equ 0
DAC_PAUSED equ 1
DAC_PLAYING equ 2
DAC_DONE equ 3
;
;Macros, internal equates
;
INCLUDE ail.mac
INCLUDE ail.inc
IFDEF PAS
STEREO EQU 1
ENDIF
IFDEF SBSTD
SBLASTER EQU 1
ENDIF
IFDEF SBPRO
SBLASTER EQU 1
STEREO EQU 1
ENDIF
IFDEF ADLIBG
STEREO EQU 1
NEEDS_FORMAT EQU 1
ENDIF
IFDEF PAS
BI_OUTPUTMIXER equ 00h ;PAS equates
BI_L_PCM equ 06h
BI_R_PCM equ 0dh
INTRCTLRST equ 0b89h
AUDIOFILT equ 0b8ah
INTRCTLR equ 0b8bh
PCMDATA equ 0f88h
CROSSCHANNEL equ 0f8ah
TMRCTLR equ 138bh
SAMPLERATE equ 1388h
SAMPLECNT equ 1389h
MVState struc
_sysspkrtmr db 0 ; 42 System Speaker Timer Address
_systmrctlr db 0 ; 43 System Timer Control Register
_sysspkrreg db 0 ; 61 System Speaker Register
_joystick db 0 ; 201 Joystick Register
_lfmaddr db 0 ; 388 Left FM Synthesizer Address Register
_lfmdata db 0 ; 389 Left FM Synthesizer Data Register
_rfmaddr db 0 ; 38A Right FM Synthesizer Address Register
_rfmdata db 0 ; 38B Right FM Synthesizer Data Register
_dfmaddr db 0 ; 788 Dual FM Synthesizer Address Register
_dfmdata db 0 ; 789 Dual FM Synthesizer Data Register
db 0 ; reserved for future use
db 0 ; reserved for future use
_audiomixr db 0 ; B88 Audio Mixer Control Register
_intrctlrst db 0 ; B89 Interrupt Status Register write
_audiofilt db 0 ; B8A Audio Filter Control Register
_intrctlr db 0 ; B8B Interrupt Control Register write
_pcmdata db 0 ; F88 PCM data I/O register
db 0 ; F89 reserved for future use
_crosschannel db 0 ; F8A Cross Channel
db 0 ; F8B reserved for future use
_samplerate dw 0 ; 1388 Sample Rate Timer Register
_samplecnt dw 0 ; 1389 Sample Count Register
_spkrtmr dw 0 ; 138A Local Speaker Timer Address
_tmrctlr db 0 ; 138B Local Timer Control Register
_mdirqvect db 0 ; 1788 MIDI IRQ Vector Register
_mdsysctlr db 0 ; 1789 MIDI System Control Register
_mdsysstat db 0 ; 178A MIDI IRQ Status Register
_mdirqclr db 0 ; 178B MIDI IRQ Clear Register
_mdgroup1 db 0 ; 1B88 MIDI Group #1 Register
_mdgroup2 db 0 ; 1B89 MIDI Group #2 Register
_mdgroup3 db 0 ; 1B8A MIDI Group #3 Register
_mdgroup4 db 0 ; 1B8B MIDI Group #4 Register
MVState ends
ENDIF
VOC_MODE equ 0 ;Creative Voice File playback mode
BUF_MODE equ 1 ;Dual-buffer DMA playback mode
.CODE
dw OFFSET driver_index
db 'Copyright (C) 1991,1992 Miles Design, Inc.',01ah
driver_index:
dw AIL_DESC_DRVR,OFFSET describe_driver
dw AIL_DET_DEV,OFFSET detect_device
dw AIL_INIT_DRVR,OFFSET init_driver
dw AIL_SHUTDOWN_DRVR,OFFSET shutdown_driver
dw AIL_P_VOC_FILE,OFFSET play_VOC_file
dw AIL_START_D_PB,OFFSET start_d_pb
dw AIL_STOP_D_PB,OFFSET stop_d_pb
dw AIL_PAUSE_D_PB,OFFSET pause_d_pb
dw AIL_RESUME_D_PB,OFFSET cont_d_pb
dw AIL_VOC_PB_STAT,OFFSET get_VOC_status
dw AIL_SET_D_PB_VOL,OFFSET set_d_pb_vol
dw AIL_D_PB_VOL,OFFSET get_d_pb_vol
dw AIL_SET_D_PB_PAN,OFFSET set_d_pb_pan
dw AIL_D_PB_PAN,OFFSET get_d_pb_pan
dw AIL_INDEX_VOC_BLK,OFFSET index_VOC_blk
dw AIL_REG_SND_BUFF,OFFSET register_sb
dw AIL_SND_BUFF_STAT,OFFSET get_sb_status
IFDEF NEEDS_FORMAT
dw AIL_F_VOC_FILE,OFFSET format_VOC_file
dw AIL_F_SND_BUFF,OFFSET format_sb
ENDIF
dw -1
;
;Driver Description Table (DDT)
;Returned by describe_driver() proc
;
DDT LABEL WORD
min_API_version dw 200 ;Minimum API version required = 2.00
driver_type dw 2 ;Type 2: Sound Blaster DSP emulation
data_suffix db 'VOC',0 ;Supports .VOC files directly
device_name_o dw OFFSET devnames ;Pointer to list of supported devices
device_name_s dw ?
default_IO LABEL WORD ;Factory default I/O parameters
IFDEF PAS
dw -1 ;(determined from MVSOUND.SYS)
ELSEIFDEF ADLIBG
dw 388h
ELSE
dw 220h
ENDIF
default_IRQ LABEL WORD
IFDEF SBSTD
dw 7
ELSEIFDEF SBPRO
dw 7 ;(pre-prod. = 5; prod. = 7)
ELSEIFDEF PAS
dw -1 ;(determined from MVSOUND.SYS)
ELSEIFDEF ADLIBG
dw -1 ;(determined from control regs)
ENDIF
default_DMA LABEL WORD
IFDEF PAS
dw -1 ;(determined from MVSOUND.SYS)
ELSEIFDEF ADLIBG
dw -1 ;(determined from control regs)
ELSE
dw 1
ENDIF
default_DRQ dw -1
service_rate dw -1 ;No periodic service required
display_size dw 0 ;No display
devnames LABEL BYTE
IFDEF SBSTD
db 'Creative Labs Sound Blaster(TM) Digital Sound',0
db 'Media Vision Thunderboard(TM) Digital Sound',0
ELSEIFDEF SBPRO
db 'Creative Labs Sound Blaster Pro(TM) Digital Sound',0
ELSEIFDEF PAS
db 'Media Vision Pro Audio Spectrum(TM) Digital Sound',0
ELSEIFDEF ADLIBG
db 'Ad Lib(R) Gold Music Synthesizer Card',0
ENDIF
db 0 ;0 to end list of device names
;
;Default setup values & internal constants
;
default_vol LABEL WORD
IFDEF SBPRO
dw 110
ELSEIFDEF PAS
dw 80
ELSE
dw 127
ENDIF
default_pan dw 64
IFDEF SBLASTER
pack_opcodes db 14h,75h,77h,17h ;type 0-3, init xfer
db 14h,74h,76h,16h ;type 0-3, cont xfer
ENDIF
DMAPAG_offset db 07h,03h,01h,02h,-1,0bh,09h,0ah
IFDEF PAS
IF PAS_FILTER
filter_cutoff dw 17897,15909,11931,8948,5965,2982
filter_value db 00001b,00010b,01001b,10001b,11001b,00100b
ENDIF
ENDIF
IFDEF ADLIBG
selected_IRQ db 3,4,5,7,10,11,12,15
PCM_Hz dw 44100,22050,11025,7350
ADPCM_Hz dw 22050,11025,7350,5513
freq_bits db 00000000b,00001000b,00010000b,00011000b
pack_modes db 0,1,128,129,4,132
; m8 PCM m4 ADPCM s8 PCM s4 ADPCM m16 PCM s16 PCM
PRC_0_values db 01100110b,01100010b,01000110b,00100010b,01100110b,01000110b
PRC_1_values db 00000000b,00000000b,00100110b,01000010b,00000000b,00100110b
SFC_0_values db 00000101b,00000101b,10000101b,10000101b,01000101b,11000101b
SFC_1_values db 00000010b,00000010b,00000011b,00000011b,00000010b,01000011b
ENDIF
IFDEF STEREO
pan_graph db 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30
db 32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62
db 64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94
db 96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,127
db 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127
db 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127
db 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127
db 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127
ENDIF
sbuffer STRUC
pack_type dw ?
sample_rate dw ?
data dd ?
len_l dw ?
len_h dw ?
sbuffer ENDS
;
;Misc. data
;
IFDEF ADLIBG
CTRL_ADDR dw ?
CTRL_DATA dw ?
DSP_ADDR dw ?
DSP_DATA dw ?
mask_save dw ?
pack_mode dw ?
PRC_0_shadow dw ?
ENDIF
IFDEF SBPRO
MIXADDR dw ?
MIXDATA dw ?
ENDIF
IFDEF SBLASTER
DSP_RESET dw ? ;IO_Addr+06h
DSP_READ dw ? ;+0Ah
DSP_WRITE_STAT dw ? ;+0Ch
DSP_DATA_RDY dw ? ;+0Eh
ENDIF
DSP_IRQ dw ?
DSP_DMA dw ?
playing dw ?
main_volume dw ?
panpot dw ?
block_ptr dd ?
old_IRQ_o dw ?
old_IRQ_s dw ?
packing dw ?
stereo dw ?
current_rate dw ?
pack_byte dw ?
DMA_ptr dd ?
DMA_len_l dw ?
DMA_len_h dw ?
blk_len dw ?
iv_status dw ?
loop_ptr dd ?
loop_cnt dw ?
IRQ_confirm dw ?
buff_data_o dw 2 dup (?)
buff_data_s dw 2 dup (?)
buff_len_l dw 2 dup (?)
buff_len_h dw 2 dup (?)
buff_pack dw 2 dup (?)
buff_sample dw 2 dup (?)
buff_status dw 2 dup (?)
buffer_mode dw ?
DAC_status dw ?
current_buffer dw ?
MV_ftable dd ?
MV_stable dd ?
PIC0_val db ?
PIC1_val db ?
sample_cnt dw ?
spkr_status dw ?
old_freq dw ?
old_stereo dw ?
xblk_status dw ?
xblk_tc db ?
xblk_pack db ?
silence_flag db ?
init_OK dw 0
;****************************************************************************
;* *
;* Interface primitives *
;* *
;****************************************************************************
IFDEF SBLASTER
send_timeout PROC Data:BYTE ;Returns AX=0 if write failed
USES ds,si,di
mov cx,200h
mov dx,DSP_WRITE_STAT
__poll_cts: in al,dx
test al,80h
jz __cts
loop __poll_cts
mov ax,0
ret
__cts: mov al,[Data]
out dx,al
mov ax,-1
ret
ENDP
;****************************************************************************
read_timeout PROC ;Returns AX (-1 if no data ready)
USES ds,si,di
mov dx,DSP_DATA_RDY
mov cx,200h
__poll_rdy: in al,dx
test al,80h
jnz __rdy
loop __poll_rdy
mov ax,-1
ret
__rdy: mov dx,DSP_READ
in al,dx
mov ah,0
ret
ENDP
;****************************************************************************
send_byte PROC Data:BYTE ;Write byte with timeout
USES ds,si,di
mov dx,DSP_WRITE_STAT
mov cx,3
mov bx,0
__wait_free_1: sub bx,1
sbb cx,0
js __write_byte
in al,dx
or al,al
js __wait_free_1
__write_byte: mov al,[Data]
out dx,al
mov cx,3 ;wait until command received
mov bx,0
__wait_free_2: sub bx,1
sbb cx,0
js __exit
in al,dx
or al,al
js __wait_free_2
__exit: ret
ENDP
ELSEIFDEF ADLIBG ;Ad Lib Gold access routines must
;preserve DS,SI,DI!
;****************************************************************************
IO_wait PROC
mov cx,500
mov dx,CTRL_ADDR
__wait: in al,dx
and al,01000000b
loopnz __wait
ret
ENDP
;****************************************************************************
enable_ctrl PROC RegNum ;Enable access to control chip
mov dx,CTRL_ADDR
mov al,0ffh
out dx,al
ret
ENDP
;****************************************************************************
disable_ctrl PROC RegNum ;Disable access to control chip
call IO_wait
mov dx,CTRL_ADDR
mov al,0feh
out dx,al
ret
ENDP
;****************************************************************************
get_ctrl_reg PROC RegNum ;Get control chip register value
call IO_wait
mov dx,CTRL_ADDR
mov ax,[RegNum]
out dx,al
call IO_wait
mov dx,CTRL_DATA
in al,dx
ret
ENDP
;****************************************************************************
set_ctrl_reg PROC RegNum,Val ;Set control chip register value
call IO_wait
mov dx,CTRL_ADDR
mov ax,[RegNum]
out dx,al
call IO_wait
mov dx,CTRL_DATA
mov ax,[Val]
out dx,al
ret
ENDP
;****************************************************************************
MMA_wait PROC ;Wait at least 470 nsec.
mov cx,100
__kill_time: jmp $+2
loop __kill_time
ret
ENDP
;****************************************************************************
MMA_write PROC Chan,Reg,Val ;Write byte to MMA register
mov ax,[Reg]
mov dx,DSP_ADDR
out dx,al
call MMA_wait
mov dx,[Chan]
shl dx,1
add dx,DSP_DATA
mov ax,[Val]
out dx,al
call MMA_wait
ret
ENDP
ENDIF
;****************************************************************************
reset_DSP PROC ;Returns AX=0 if failure
USES ds,si,di
IFDEF PAS
mov ax,1
ELSEIFDEF ADLIBG
call MMA_write C,0,9,10000000b
call MMA_write C,0,9,01110110b
call MMA_write C,1,9,10000000b
call MMA_write C,1,9,01110110b
mov ax,01110110b
mov PRC_0_shadow,ax
mov ax,1
ELSEIFDEF SBLASTER
mov dx,DSP_RESET ;assert reset
mov al,1
out dx,al
mov cx,20
__wait: in al,dx ;wait > 3 uS
loop __wait
mov al,0 ;drop reset
out dx,al
mov si,10h ;try 16 times
__try_read: call read_timeout
cmp ax,0aah
je __exit ;(reset succeeded)
dec si
jnz __try_read
mov ax,0 ;return 0 if failed
ENDIF
__exit: ret
ENDP
;****************************************************************************
;* *
;* Internal procedures *
;* *
;****************************************************************************
sub_ptr PROC Off1,Seg1,Off2,Seg2
USES ds,si,di ;Return DX:AX = ptr 2 - ptr 1
mov ax,[Seg2]
mov dx,0
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1
shl ax,1
rcl dx,1
add ax,[Off2]
adc dx,0
mov bx,[Seg1]
mov cx,0
shl bx,1
rcl cx,1
shl bx,1
rcl cx,1
shl bx,1
rcl cx,1
shl bx,1
rcl cx,1
add bx,[Off1]
adc cx,0
sub ax,bx
sbb dx,cx
ret
ENDP
;****************************************************************************
block_type PROC ;Return AX=current block type
USES ds,si,di
lds si,block_ptr
lodsb
mov ah,0
ret
ENDP
;****************************************************************************
set_xblk PROC ;Set extended .VOC block parms
USES ds,si,di
lds si,block_ptr
cmp BYTE PTR [si],8
jne __exit ;(not an extended block)
mov al,[si+5] ;get extended voice parameters
mov xblk_tc,al ;high byte of TC = normal sample rate
mov ax,[si+6] ;get pack (AL) and mode (AH)
cmp ah,1 ;stereo?
jne __set_pack
or al,80h ;yes, make pack byte negative
__set_pack: mov xblk_pack,al
mov xblk_status,1 ;flag extended block override
__exit: ret
ENDP
;****************************************************************************
marker_num PROC ;Return AX=block's marker #
USES ds,si,di
lds si,block_ptr
cmp BYTE PTR [si],4
mov ax,-1
jne __exit ;(not a marker block)
mov ax,[si+4] ;return marker #
__exit: ret
ENDP
;****************************************************************************
IFDEF SBLASTER
DAC_spkr_on PROC
USES ds,si,di
cmp spkr_status,1
je __exit ;already on, exit
mov spkr_status,1
call send_byte C,0d1h
call sysex_wait C,8 ;112 ms delay (SB Dev Kit, p. 14-11)
__exit: ret
ENDP
;****************************************************************************
DAC_spkr_off PROC
USES ds,si,di
cmp spkr_status,0
je __exit ;already off, exit
mov spkr_status,0
call halt_DMA C,1
call send_byte C,0d3h
call sysex_wait C,16 ;224 ms delay (SB Dev Kit, p. 14-11)
__exit: ret
ENDP
ENDIF
;****************************************************************************
continue_DMA PROC
USES ds,si,di
IFDEF PAS
les di,MV_stable
mov al,es:[di]._audiofilt
or al,01000000b
mov dx,AUDIOFILT
out dx,al ;start the transfer
mov es:[di]._audiofilt,al
ELSEIFDEF ADLIBG
mov ax,PRC_0_shadow
or ax,00000001b ;set GO bit
call MMA_write C,0,9,ax
ELSEIFDEF SBLASTER
call send_byte C,0d4h
ENDIF
mov playing,1
ret
ENDP
;****************************************************************************
halt_DMA PROC WaitOpt
USES ds,si,di
IFDEF PAS
les di,MV_stable
mov al,es:[di]._audiofilt
and al,10111111b
mov dx,AUDIOFILT
out dx,al ;suspend the transfer
mov es:[di]._audiofilt,al
ELSEIFDEF ADLIBG
mov ax,PRC_0_shadow
and ax,11111110b ;clear GO bit
call MMA_write C,0,9,ax
ELSEIFDEF SBLASTER
IF NOT WAIT_FALSE_IRQ ;"new" way to avoid SB glitches
pushf ;save i-flag status
mov dx,DSP_WRITE_STAT ;register busy flag
mov cx,7
mov bx,0
__wait_busy: sub bx,1
sbb cx,0
js __send_halt
sti ;wait for busy status, abort if
jmp $+2 ;playback ends by itself
jmp $+2
jmp $+2
cmp playing,0
je __not_playing
cli
in al,dx
or al,al
jns __wait_busy
mov cx,32768 ;wait for free edge
__wait_free: dec cx
jz __send_halt
in al,dx
or al,al
js __wait_free
__send_halt: mov al,0d0h ;send halt DMA opcode
out dx,al
__not_playing: POP_F ;recover i-flag
ELSE
call send_byte C,0d0h
cmp WaitOpt,0 ;optional wait to absorb dummy IRQ
je __exit
cmp iv_status,0
jne __exit
lea ax,IRQ_test ;enable EOD interrupts from DSP
call IRQ_set_vect C,ax,cs
pushf
sti
call sysex_wait C,10 ;(140 milliseconds)
POP_F
call IRQ_rest_vect
ENDIF ;NOT WAIT_FALSE_IRQ
ENDIF ;DEF SBLASTER
__exit: mov playing,0
ret
ENDP
;****************************************************************************
IFNDEF SBLASTER
match_constant PROC TAddr,TSize,N ;Get entry index for nearest match to
USES ds,si,di ;constant N
cld
mov si,[TAddr]
mov bx,0ffffh
mov cx,0
mov di,0
__abs_delta: lods WORD PTR cs:[si]
sub ax,[N]
cwd
xor ax,dx
sub ax,dx
cmp ax,bx
ja __next
mov bx,ax
mov di,cx
__next: inc cx
cmp cx,[TSize]
jne __abs_delta
mov ax,di
ret
ENDP
ENDIF
;****************************************************************************
set_sample_rate PROC SB_Rate,Stereo ;Establish DSP sample rate
LOCAL freq
USES ds,si,di
pushf
cli ;make sure IRQ's are off
mov ax,[SB_Rate] ;f in Hz. = 1E6 / (256 - SB_Rate)
mov ah,0
mov bx,256
sub bx,ax
mov dx,0fh
mov ax,4240h
div bx
mov freq,ax
IFDEF PAS
mov ax,1
mov cx,freq
mov bx,[Stereo]
cmp cx,old_freq ;avoid clicks by sending
jne __new_parms ;new settings only when changed
cmp bx,old_stereo
je __exit
__new_parms: mov old_freq,cx
mov old_stereo,bx
mov dx,PCMDATA ;silence PCM output
mov al,80h
out dx,al
mov ax,34dch
mov dx,12h
div freq
mov cx,ax
mov al,00110110b ;timer 0, square wave, binary mode
mov dx,TMRCTLR
out dx,al
mov dx,SAMPLERATE
mov al,cl
out dx,al
jmp $+2
mov al,ch
out dx,al
IF PAS_FILTER
lea ax,filter_cutoff ;select filter for freq in Hz. / 2
mov cx,freq
shr cx,1
call match_constant C,ax,6,cx
mov si,ax ;SI = index into filter_value
les di,MV_stable
mov al,es:[di]._audiofilt
and al,11100000b
or al,filter_value[si]
mov dx,AUDIOFILT
out dx,al
mov es:[di]._audiofilt,al
ENDIF
ELSEIFDEF ADLIBG
mov ax,1
mov cx,freq
mov bx,[Stereo]
cmp cx,old_freq ;avoid Ad Lib Gold clicks by sending
jne __new_parms ;new settings only when changed
cmp bx,old_stereo
je __exit
__new_parms: mov old_freq,cx
mov old_stereo,bx
mov ax,pack_byte
and ax,10000111b
mov si,0
__find_pack: cmp pack_modes[si],al
je __pack_found
inc si
cmp si,6
jne __find_pack
mov si,0
__pack_found: mov pack_mode,si
lea ax,ADPCM_Hz
cmp si,1
je __find_freq
cmp si,3
je __find_freq
lea ax,PCM_Hz
__find_freq: cmp bx,0
je __lookup
shr cx,1 ;sample rate /= 2 for stereo
__lookup: call match_constant C,ax,4,cx
mov di,ax
call MMA_write C,0,9,10000000b ;reset both FIFOs
call MMA_write C,1,9,10000000b
call MMA_write C,0,11,0 ;write 4 dummy bytes to
call MMA_write C,0,11,0 ;allow proper FIFO DMA
call MMA_write C,0,11,0 ;initialization
call MMA_write C,0,11,0
mov al,freq_bits[di]
or al,PRC_0_values[si]
mov PRC_0_shadow,ax
call MMA_write C,0,9,ax
mov al,freq_bits[di]
or al,PRC_1_values[si]
call MMA_write C,1,9,ax
mov al,SFC_0_values[si]
call MMA_write C,0,12,ax
mov al,SFC_1_values[si]
call MMA_write C,1,12,ax
ELSEIFDEF SBLASTER
call send_byte C,40h
call send_byte C,[SB_Rate]
ENDIF
__exit: POP_F
ret
ENDP
;****************************************************************************
set_volume PROC ;Establish output lvl w/vol, pan
USES ds,si,di
IFDEF STEREO
mov si,127
sub si,panpot
mov al,pan_graph[si]