-
Notifications
You must be signed in to change notification settings - Fork 3
/
JASMDJ.ASM
3750 lines (3470 loc) · 151 KB
/
JASMDJ.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
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
; This module contains soundcard IRQ handlers, DMA routines, mixing routines
; as well as some time-critical GUS routines and AC97 access code.
;
; N„m„ ei mit„„n (kovin) optimisoituja rutiineja ole, PERKELE!
;
; Modified by BSpider for NASM on 5th Sep 2006
%idefine offset
%include "segments.inc"
%include "judascfg.inc"
%include "judasgus.inc"
%include "judasac.inc"
%define MONO 0
%define EIGHTBIT 0
%define STEREO 1
%define SIXTEENBIT 2
%define VM_OFF 0
%define VM_ON 1
%define VM_LOOP 2
%define VM_16BIT 4
%define DEV_NOSOUND 0
%define DEV_SB 1
%define DEV_SBPRO 2
%define DEV_SB16 3
%define DEV_GUS 4
%define DEV_AC97 5
%define DEV_HDA 6
%define DEV_FILE 7
%define CACHESLOTS 16
%define IPMINUS1 -1
%define IP0 0
%define IP1 1
%define IP2 2
; predefined to 0
struc CACHESLOT
GDC_Pos resd 1
GDC_Length resd 1
endstruc
; predefined to 0
struc DMACHANNEL
DMA_PagePort resw 1
DMA_AdrPort resw 1
DMA_LenPort resw 1
DMA_MaskPort resw 1
DMA_ModePort resw 1
DMA_ClearPort resw 1
DMA_Mask resb 1
DMA_UnMask resb 1
DMA_Unused resw 1
endstruc
; predefined to 0
struc CHANNEL
Chn_Pos resd 1
Chn_Repeat resd 1
Chn_End resd 1
Chn_Sample resd 1
Chn_Freq resd 1
Chn_FractPos resw 1
Chn_MasterVol resb 1
Chn_Panning resb 1
Chn_Vol resw 1
Chn_VoiceMode resb 1
Chn_PrevVM resb 1
Chn_PrevPos resd 1
Chn_LastValL resd 1
Chn_LastValR resd 1
Chn_SmoothVolL resd 1
Chn_SmoothVolR resd 1
endstruc
; not predefined
struc AUDIO_PCI_DEV
.vender_id resw 1
.device_id resw 1
.sub_vender_id resw 1
.sub_device_id resw 1
.device_bus_number resw 1
.irq resb 1
.pin resb 1
.command resw 1
.base0 resd 1
.base1 resd 1
.base2 resd 1
.base3 resd 1
.base4 resd 1
.base5 resd 1
.device_type resd 1
.mem_mode resd 1
.hda_mode resd 1
; memory allocated for BDL and PCM buffers
.bdl_buffer resd 1
.pcmout_buffer0 resd 1
.pcmout_buffer1 resd 1
.hda_buffer resd 1
.pcmout_bufsize resd 1
.pcmout_bdl_entries resd 1
.pcmout_bdl_size resd 1
.pcmout_dmasize resd 1
.pcmout_dma_lastgoodpos resd 1
.pcmout_dma_pos_ptr resd 1
; AC97 only properties
.ac97_vra_supported resd 1
; HDA modified structure will be placed here.
.codec_mask resd 1
.codec_index resd 1
.afg_root_nodenum resw 1
.afg_num_nodes resd 1
.afg_nodes resd 1
.def_amp_out_caps resd 1
.def_amp_in_caps resd 1
.dac_node resd 1
.out_pin_node resd 1
.adc_node resd 1
.in_pin_node resd 1
.input_items resd 1
.pcm_num_vols resd 1
.pcm_vols resd 1
.format_val resd 1
.dacout_num_bits resd 1
.dacout_num_channels resd 1
.stream_tag resd 1
.supported_formats resd 1
.supported_max_freq resd 1
.supported_max_bits resd 1
.freq_card resd 1
.chan_card resd 1
.bits_card resd 1
.codec_id1 resw 1
.codec_id2 resw 1
.device_name resb 128
.codec_name resb 128
endstruc
%define DEVICE_INTEL 0 ; AC97 device Intel ICH compatible
%define DEVICE_SIS 1 ; AC97 device SIS compatible
%define DEVICE_INTEL_ICH4 2 ; AC97 device Intel ICH4 compatible
%define DEVICE_NFORCE 3 ; AC97 device nForce compatible
%define DEVICE_HDA_INTEL 4 ; HDA audio device for Intel and others
%define DEVICE_HDA_ATI 5
%define DEVICE_HDA_ATIHDMI 6
%define DEVICE_HDA_NVIDIA 7
%define DEVICE_HDA_SIS 8
%define DEVICE_HDA_ULI 9
%define DEVICE_HDA_VIA 10
; register calling convention for WATCOM C++
global judas_code_lock_start_
global judas_code_lock_end_
global judas_update_
global judas_get_ds_
global sb_handler_
global sb_aihandler_
global sb16_handler_
global gus_handler_
global gus_peek_
global gus_poke_
global gus_dmawait_
global gus_dmainit_
global gus_dmaprogram_
global gus_startchannels_
global fmixer_
global qmixer_
global safemixer_
global normalmix_
global ipmix_
global qmix_linear_
global qmix_cubic_
global dma_program_
; stack calling convention for anything else
global _judas_code_lock_start
global _judas_code_lock_end
global _judas_update
global _judas_get_ds
global _sb_handler
global _sb_aihandler
global _sb16_handler
global _gus_handler
global _gus_peek
global _gus_poke
global _gus_dmawait
global _gus_dmainit
global _gus_dmaprogram
global _gus_startchannels
global _fmixer
global _qmixer
global _safemixer
global _normalmix
global _ipmix
global _qmix_linear
global _qmix_cubic
global _dma_program
extern _judas_ds;word
extern _judas_initialized;byte
extern _judas_mixmode;byte
extern _judas_samplesize;byte
extern _judas_clipbuffer;dword
extern _judas_zladdbuffer;dword
extern _judas_zerolevell;dword
extern _judas_zerolevelr;dword
extern _judas_cliptable;dword
extern _judas_volumetable;dword
extern _judas_mixrate;dword
extern _judas_channel;dword
extern _judas_mixroutine;dword
extern _judas_mixersys;dword
extern _judas_device;dword
extern _judas_port;dword
extern _judas_irq;dword
extern _judas_dma;dword
extern _judas_irqcount;dword
extern _judas_bufferlength;dword
extern _judas_buffermask;dword
extern _judas_bpmcount;dword
extern _judas_bpmtempo;byte
extern _judas_player;dword
extern _judas_mixpos;dword
extern _dma_address;dword
extern ___djgpp_base_address;dword
extern _judas_clipped;byte
extern _audio_pci;AUDIO_PCI_DEV
extern _hda_civ ; dword
extern _hda_lpib ; dword
%ifdef djgpp
section .text
%else
segment _TEXT
%endif
judas_get_ds_:
_judas_get_ds:
mov AX, DS
mov [_judas_ds], AX
ret
judas_code_lock_start_:
_judas_code_lock_start:
; this code is constant - TASM declaration of .const
align 4
DMAChannels:
istruc DMACHANNEL
at DMA_PagePort, dw 87h
at DMA_AdrPort, dw 0h
at DMA_LenPort, dw 1h
at DMA_MaskPort, dw 0ah
at DMA_ModePort, dw 0bh
at DMA_ClearPort, dw 0ch
at DMA_Mask, db 4h
at DMA_UnMask, db 0h
at DMA_Unused, dw 0h
iend
istruc DMACHANNEL
at DMA_PagePort, dw 83h
at DMA_AdrPort, dw 2h
at DMA_LenPort, dw 3h
at DMA_MaskPort, dw 0ah
at DMA_ModePort, dw 0bh
at DMA_ClearPort, dw 0ch
at DMA_Mask, db 5h
at DMA_UnMask, db 1h
at DMA_Unused, dw 0h
iend
istruc DMACHANNEL
at DMA_PagePort, dw 81h
at DMA_AdrPort, dw 4h
at DMA_LenPort, dw 5h
at DMA_MaskPort, dw 0ah
at DMA_ModePort, dw 0bh
at DMA_ClearPort, dw 0ch
at DMA_Mask, db 6h
at DMA_UnMask, db 2h
at DMA_Unused, dw 0h
iend
istruc DMACHANNEL
at DMA_PagePort, dw 82h
at DMA_AdrPort, dw 6h
at DMA_LenPort, dw 7h
at DMA_MaskPort, dw 0ah
at DMA_ModePort, dw 0bh
at DMA_ClearPort, dw 0ch
at DMA_Mask, db 7h
at DMA_UnMask, db 3h
at DMA_Unused, dw 0h
iend
istruc DMACHANNEL
at DMA_PagePort, dw 8fh
at DMA_AdrPort, dw 0c0h
at DMA_LenPort, dw 0c2h
at DMA_MaskPort, dw 0d4h
at DMA_ModePort, dw 0d6h
at DMA_ClearPort, dw 0d8h
at DMA_Mask, db 4h
at DMA_UnMask, db 0h
at DMA_Unused, dw 0h
iend
istruc DMACHANNEL
at DMA_PagePort, dw 8bh
at DMA_AdrPort, dw 0c4h
at DMA_LenPort, dw 0c6h
at DMA_MaskPort, dw 0d4h
at DMA_ModePort, dw 0d6h
at DMA_ClearPort, dw 0d8h
at DMA_Mask, db 5h
at DMA_UnMask, db 1h
at DMA_Unused, dw 0h
iend
istruc DMACHANNEL
at DMA_PagePort, dw 89h
at DMA_AdrPort, dw 0c8h
at DMA_LenPort, dw 0cah
at DMA_MaskPort, dw 0d4h
at DMA_ModePort, dw 0d6h
at DMA_ClearPort, dw 0d8h
at DMA_Mask, db 6h
at DMA_UnMask, db 2h
at DMA_Unused, dw 0h
iend
istruc DMACHANNEL
at DMA_PagePort, dw 8ah
at DMA_AdrPort, dw 0cch
at DMA_LenPort, dw 0ceh
at DMA_MaskPort, dw 0d4h
at DMA_ModePort, dw 0d6h
at DMA_ClearPort, dw 0d8h
at DMA_Mask, db 7h
at DMA_UnMask, db 3h
at DMA_Unused, dw 0h
iend
align 4
shittable dd 0, 60, 56, 52, 48, 44, 40, 36
dd 32, 28, 24, 20, 16, 12, 8, 4
%ifdef djgpp
section .data
%else
segment _DATA
%endif
align 4
gdc:
%rep CACHESLOTS
istruc CACHESLOT
at GDC_Pos, dd 0
at GDC_Length, dd 0
iend
%endrep
align 4
loopcount dd 0
fractadd dd 0
integeradd dd 0
smpend dd 0
smpsubtract dd 0
samples dd 0
totalwork dd 0
postproc dd 0
cptr dd 0
dptr dd 0
fptr dd 0
ipminus1 dd 0
ip0 dd 0
ip1 dd 0
ip2 dd 0
leftvol dd 0
rightvol dd 0
SmoothVolL dd 0
SmoothVolR dd 0
saved_reg dd 0
mix_exec db 0
gus_dmainprogress db 0
ac97_buffer0_set db 0
ac97_buffer1_set db 0
%ifdef djgpp
section .text
%else
segment _TEXT
%endif
align 4
;DMA functions. DMA polling is really fucked up: if reading the
;position too often (> 100 Hz) one may get bogus values. This is
;compensated by reading two values, and if their offset is too big or
;they're outside the buffer, the position is read again.
;
;Actually GUS fucks up just in the same way when reading the channel
;position. Shit, what is wrong with the hardware?!
;
;Previously I though that EMM386 causes these fuckups, but no, it
;wasn't so. However, under DPMI there's no fuckups!
;
;It would be really nice & simple to just update one bufferhalf at a
;time in the soundcard interrupt, but I think it's important to give
;the user full control of the sound updating, even at the expense of
;PAIN!!!
dma_program_asm:
push EBX
push EDX
push EAX
call dma_program_
pop EAX
pop EDX
pop EBX
ret
; void dma_program(unsigned char mode, unsigned offset, unsigned length)
dma_program_:
_dma_program:
push EAX
push EDX
push EBX
mov EAX, [esp + 4 + 12]
mov EDX, [esp + 8 + 12]
mov EBX, [esp + 12 + 12]
push ESI
push EDI
push ECX
mov ECX, EAX ;ECX = mode
mov EDI, EDX ;EDI = offset
mov ESI, [_judas_dma] ;Get channel num
cmp ESI, 4
jae dma16_program
shl ESI, 4 ;16 = dma struc len
add ESI, offset DMAChannels ;Ptr now ready
mov DX, [ESI + DMA_MaskPort]
mov AL, [ESI + DMA_Mask]
out DX, AL ;Mask the DMA channel
xor AL, AL
mov DX, [ESI + DMA_ClearPort]
out DX, AL ;Clear byte ptr.
mov DX, [ESI + DMA_ModePort]
mov AL, CL ;Get mode
or AL, [ESI + DMA_UnMask] ;Or with channel num
out DX, AL ;Set DMA mode
mov DX, [ESI + DMA_LenPort]
dec EBX ;EBX = length
mov AL, BL
out DX, AL ;Set length low and
mov AL, BH ;high bytes
out DX, AL
mov DX, [ESI + DMA_AdrPort]
mov EBX, [_dma_address] ;Get DMA buffer address
add EBX, EDI ;Add offset
mov AL, BL
out DX, AL ;Set offset
mov AL, BH
out DX, AL
mov DX, [ESI + DMA_PagePort]
shr EBX, 16
mov AL, BL
out DX, AL ;Set page
mov DX, [ESI + DMA_MaskPort]
mov AL, [ESI + DMA_UnMask]
out DX, AL ;Unmask the DMA channel
pop ECX
pop EDI
pop ESI
pop EBX
pop EDX
pop EAX
ret
dma16_program: shl ESI, 4 ;16 = dma struc len
add ESI, offset DMAChannels ;Ptr now ready
mov DX, [ESI + DMA_MaskPort]
mov AL, [ESI + DMA_Mask]
out DX, AL ;Mask the DMA channel
xor AL, AL
mov DX, [ESI + DMA_ClearPort]
out DX, AL ;Clear byte ptr.
mov DX, [ESI + DMA_ModePort]
mov AL, CL ;Get mode
or AL, [ESI + DMA_UnMask] ;Or with channel num
out DX, AL ;Set DMA mode
mov DX, [ESI + DMA_LenPort]
shr EBX, 1
dec EBX
mov AL, BL
out DX, AL ;Set length low and
mov AL, BH ;high bytes
out DX, AL
mov DX, [ESI + DMA_AdrPort]
mov EBX, [_dma_address] ;Get DMA buffer address
add EBX, EDI ;Add offset
shr EBX, 1 ;Because of 16-bitness
mov AL, BL
out DX, AL ;Set offset
mov AL, BH
out DX, AL
mov DX, [ESI + DMA_PagePort]
shr EBX, 15
mov AL, BL
out DX, AL ;Set page
mov DX, [ESI + DMA_MaskPort]
mov AL, [ESI + DMA_UnMask]
out DX, AL ;Unmask the DMA channel
pop ECX
pop EDI
pop ESI
pop EBX
pop EDX
pop EAX
ret
dma_query_: cli
push EBX
push ECX
push EDX
push ESI
mov ESI, [_judas_dma]
cmp ESI, 4
jae dma16_query
shl ESI, 4 ;16 = dma struc len
add ESI, offset DMAChannels ;Ptr now ready
xor EAX, EAX
mov DX, [ESI + DMA_ClearPort] ;Clear flip-flop
out DX, AL
mov DX, [ESI + DMA_AdrPort]
dqloop1: xor EAX, EAX
in AL, DX
xchg AL, AH
in AL, DX
xchg AL, AH
sub AX, word [_dma_address] ;Subtract page offset
mov EBX, EAX ;EBX = position 1
in AL, DX
xchg AL, AH
in AL, DX
xchg AL, AH
sub AX, word [_dma_address] ;Subtract page offset
mov ECX, EAX ;ECX = position 2
cmp EBX, [_judas_bufferlength] ;Outside buffer?
jae dqloop1
mov EAX, EBX
sub EAX, ECX
cmp EAX, 64
jg dqloop1
cmp EAX, -64
jl dqloop1
mov EAX, EBX
pop ESI
pop EDX
pop ECX
pop EBX
sti
ret
dma16_query: shl ESI, 4 ;16 = dma struc len
add ESI, offset DMAChannels ;Ptr now ready
mov DX, [ESI + DMA_ClearPort] ;Clear flip-flop
xor EAX, EAX
out DX, AL
mov DX, [ESI + DMA_AdrPort]
mov ESI, [_dma_address]
and ESI, 1ffffh
dqloop2: xor EAX, EAX
in AL, DX
xchg AL, AH
in AL, DX
xchg AL, AH
shl EAX, 1
sub EAX, ESI ;Subtract page offset
mov EBX, EAX ;EBX = position 1
xor EAX, EAX
in AL, DX
xchg AL, AH
in AL, DX
xchg AL, AH
shl EAX, 1
sub EAX, ESI ;Subtract page offset
mov ECX, EAX ;ECX = position 2
cmp EBX, [_judas_bufferlength] ;Outside buffer?
jae dqloop2
mov EAX, EBX
sub EAX, ECX
cmp EAX, 64
jg dqloop2
cmp EAX, -64
jl dqloop2
mov EAX, EBX
pop ESI
pop EDX
pop ECX
pop EBX
sti
ret
;Generic send-EOI routine.
send_eoi: inc dword [_judas_irqcount]
cmp dword [_judas_irq], 8
jae highirq
mov AL, 20h
out 20h, AL
ret
highirq: mov AL, 20h
out 0a0h, AL
mov AL, 00001011b
out 0a0h, AL
in AL, 0a0h
or AL, AL
jnz sb_noeoi
mov AL, 20h
out 20h, AL
sb_noeoi: ret
;Soundblaster IRQ handlers, one for singlecycle, one for 8bit autoinit
;and one for 16bit autoinit.
sb_handler_:
_sb_handler:
pushad
push DS
mov AX, [CS:_judas_ds]
mov DS, AX
mov EDX, [_judas_port]
add EDX, 0eh
in AL, DX
sub EDX, 2h
sb_wait1: in AL, DX
or AL, AL
js sb_wait1
mov AL, 14h
out DX, AL
sb_wait2: in AL, DX
or AL, AL
js sb_wait2
mov AX, 0fff0h
out DX, AL
sb_wait3: in AL, DX
or AL, AL
js sb_wait3
mov AL, AH
out DX, AL
sti
call send_eoi
pop DS
popad
iretd
sb_aihandler_:
_sb_aihandler:
pushad
push DS
mov AX, [CS:_judas_ds]
mov DS, AX
mov EDX, [_judas_port]
add EDX, 0eh
in AL, DX
sti
call send_eoi
pop DS
popad
iretd
sb16_handler_:
_sb16_handler:
pushad
push DS
mov AX, [CS:_judas_ds]
mov DS, AX
mov EDX, [_judas_port]
add EDX, 0fh
in AL, DX
sti
call send_eoi
pop DS
popad
iretd
;GUS IRQ handler
gus_handler_:
_gus_handler:
pushad
push DS
mov AX, [CS:_judas_ds]
mov DS, AX
gus_irqloop: mov EDX, [_judas_port]
add EDX, GF1_IRQ_STAT
in AL, DX
test AL, DMA_TC_IRQ
jz near gus_irqdone
mov EDX, [_judas_port] ;Acknowledge the DMA
add EDX, GF1_REG_SELECT ;interrupt
mov AL, DMA_CONTROL
out DX, AL
mov EDX, [_judas_port]
add EDX, GF1_DATA_HI
in AL, DX
dec byte [gus_dmainprogress]
mov ESI, offset gdc
mov ECX, CACHESLOTS
gusirq_seekslot:cmp dword [ESI + GDC_Length], 0
jnz gusirq_slotfound
add ESI, CACHESLOT_size ;type CACHESLOT in TASM
dec ECX
jnz gusirq_seekslot
jmp gus_irqloop
gusirq_slotfound:
mov EBX, [ESI + GDC_Pos] ;DMA offset
shr EBX, 4
mov CL, DMA_ENABLE | DMA_R0 | DMA_TWOS_COMP | DMA_IRQ_ENABLE
test byte [_judas_mixmode], SIXTEENBIT
jz gus_dma_eight2
mov CL, DMA_ENABLE | DMA_R0 | DMA_DATA_16 | DMA_IRQ_ENABLE
gus_dma_eight2: cmp dword [_judas_dma], 4
jb gus_nohighdma2
or CL, DMA_WIDTH_16
shr EBX, 1
gus_nohighdma2: mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
mov AL, SET_DMA_ADDRESS
out DX, AL
mov EDX, [_judas_port]
add EDX, GF1_DATA_LOW
mov AX, BX
out DX, AX
mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
mov AL, DMA_CONTROL
out DX, AL
mov EDX, [_judas_port]
add EDX, GF1_DATA_HI
mov AL, CL
out DX, AL
mov EBX, [ESI + GDC_Length]
mov dword [ESI + GDC_Length], 0
mov EDX, [ESI + GDC_Pos] ;DMA offset
mov EAX, 48h ;DMA mode
call dma_program_asm ;Program it!
jmp gus_irqloop
gus_irqdone: sti
call send_eoi
pop DS
popad
iretd
;Various GUS functions
; to be called from C with stack calling convention
gus_peek_:
_gus_peek:
mov EAX, [esp + 4]
push EBX
mov EBX, EAX
mov AL, SET_DRAM_LOW
mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
out DX, AL
mov AX, BX
mov EDX, [_judas_port]
add EDX, GF1_DATA_LOW
out DX, AX
mov AL, SET_DRAM_HIGH
mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
out DX, AL
shr EBX, 16
mov AL, BL
mov EDX, [_judas_port]
add EDX, GF1_DATA_HI
out DX, AL
mov EDX, [_judas_port]
add EDX, GF1_DRAM
in AL, DX
pop EBX
ret
gus_peek_asm:
push EBX
mov EBX, EAX
mov AL, SET_DRAM_LOW
mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
out DX, AL
mov AX, BX
mov EDX, [_judas_port]
add EDX, GF1_DATA_LOW
out DX, AX
mov AL, SET_DRAM_HIGH
mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
out DX, AL
shr EBX, 16
mov AL, BL
mov EDX, [_judas_port]
add EDX, GF1_DATA_HI
out DX, AL
mov EDX, [_judas_port]
add EDX, GF1_DRAM
in AL, DX
pop EBX
ret
; to be called from C with stack calling convention
gus_poke_:
_gus_poke:
push EAX
push EDX
mov EAX, [esp + 4 + 8]
mov EDX, [esp + 8 + 8]
push EBX
push EDX
mov EBX, EAX
mov AL, SET_DRAM_LOW
mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
out DX, AL
mov AX, BX
mov EDX, [_judas_port]
add EDX, GF1_DATA_LOW
out DX, AX
mov AL, SET_DRAM_HIGH
mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
out DX, AL
shr EBX, 16
mov AL, BL
mov EDX, [_judas_port]
add EDX, GF1_DATA_HI
out DX, AL
mov EDX, [_judas_port]
add EDX, GF1_DRAM
pop EAX
out DX, AL
pop EBX
pop EDX
pop EAX
ret
gus_poke_asm:
push EBX
push EDX
mov EBX, EAX
mov AL, SET_DRAM_LOW
mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
out DX, AL
mov AX, BX
mov EDX, [_judas_port]
add EDX, GF1_DATA_LOW
out DX, AX
mov AL, SET_DRAM_HIGH
mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
out DX, AL
shr EBX, 16
mov AL, BL
mov EDX, [_judas_port]
add EDX, GF1_DATA_HI
out DX, AL
mov EDX, [_judas_port]
add EDX, GF1_DRAM
pop EAX
out DX, AL
pop EBX
ret
gus_startchannels_:
_gus_startchannels:
push EBX ;This routine starts
push ECX ;the two channels
push EDX ;as quickly as possible.
mov EBX, [_judas_port]
add EBX, GF1_PAGE
mov ECX, [_judas_port]
add ECX, GF1_DATA_HI
mov EDX, [_judas_port]
add EDX, GF1_REG_SELECT
mov AL, SET_CONTROL
out DX, AL
test byte [_judas_mixmode], SIXTEENBIT
jz gus_start8
mov EDX, EBX
mov AL, 0
out DX, AL
mov EDX, ECX
mov AL, VC_LOOP_ENABLE | VC_DATA_TYPE
out DX, AL
mov EDX, EBX
mov AL, 1
out DX, AL
mov EDX, ECX
mov AL, VC_LOOP_ENABLE | VC_DATA_TYPE
out DX, AL
pop EDX
pop ECX
pop EBX
ret
gus_start8: mov EDX, EBX
xor AL, AL
out DX, AL
mov EDX, ECX
mov AL, VC_LOOP_ENABLE
out DX, AL
mov EDX, EBX
mov AL, 1
out DX, AL
mov EDX, ECX
mov AL, VC_LOOP_ENABLE
out DX, AL
pop EDX
pop ECX
pop EBX
ret
; to be called from assembly for DJGPP (note - didn't have time to make it faster and more clear :)
gus_dmaprogram_asm:
push EDX
push EAX
call gus_dmaprogram_
pop EAX
pop EDX
ret
; to be called from C for DJGPP stack based convention
gus_dmaprogram_:
_gus_dmaprogram:
push EAX
push EDX
mov EAX, [esp + 4 + 8]
mov EDX, [esp + 8 + 8]
or EDX, EDX ;Zero length fucks up!
jz gus_skipdma
pushad
cli
cmp byte [gus_dmainprogress], 0 ;Do we have to cache the
je gus_dontcache ;block?
mov EBX, offset gdc
mov ECX, CACHESLOTS
gus_seekslot: cmp dword [EBX + GDC_Length], 0
je gus_slotfound
add EBX, CACHESLOT_size ;type CACHESLOT in TASM
dec ECX
jnz gus_seekslot
sti
popad
gus_skipdma: pop EDX
pop EAX
ret
gus_slotfound: mov [EBX + GDC_Pos], EAX
mov [EBX + GDC_Length], EDX
inc byte [gus_dmainprogress]
sti
popad
pop EDX
pop EAX
ret
gus_dontcache: sti
inc byte [gus_dmainprogress]
mov ESI, EAX
mov EDI, EDX
mov EBX, ESI ;DMA offset
shr EBX, 4
mov CL, DMA_ENABLE | DMA_R0 | DMA_TWOS_COMP | DMA_IRQ_ENABLE
test byte [_judas_mixmode], SIXTEENBIT
jz gus_dma_eight
mov CL, DMA_ENABLE | DMA_R0 | DMA_DATA_16 | DMA_IRQ_ENABLE
gus_dma_eight: cmp dword [_judas_dma], 4