Difference between revisions of "GMBLAST Assembler Code Documentation"
From SCI Wiki
Jump to navigationJump to searchm (1 revision) |
Latest revision as of 15:58, 5 August 2013
The GMBLAST.DRV is a third party General MIDI SCI1 driver that adds Sound Blaster digital sound effects. It was written by Michael C. Maggio. The following is his documentation on the assembler code of the driver
; offsets should be relative to CS:0000, ; but debug loads things at 0100 regardless, ; so all code addresses are 100 greater than they ought to be /* Main */ 0B43:0100 E9A705 JMP 06AA -d 0100 06b5 0B43:0100 E9 A7 05 00 21 43 65 87-01 04 64 75 64 65 25 47 ....!Ce...dude%G 0B43:0110 65 6E 65 72 61 6C 20 4D-49 44 49 20 66 6F 72 20 eneral MIDI for 0B43:0120 52 6F 6C 61 6E 64 20 4D-50 55 20 69 6E 74 65 72 Roland MPU inter 0B43:0130 66 61 63 65 98 BA DC FE-00 02 00 00 76 31 2E 30 face........v1.0 0B43:0140 33 FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF 3............... 0B43:0150 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:0160 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:0170 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:0180 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:0190 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:01A0 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:01B0 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:01C0 FF 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:01D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:01E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:01F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0200 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0210 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0220 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0230 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0240 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0250 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0260 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0270 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0280 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0290 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:02A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:02B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:02C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:02D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:02E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:02F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0300 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0310 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0320 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0330 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0340 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0350 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0360 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0370 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0380 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0390 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:03A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:03B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:03C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:03D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:03E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:03F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0400 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0410 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0420 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0430 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0440 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0450 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0460 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0470 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0480 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0490 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:04A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:04B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:04C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:04D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:04E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:04F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0500 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0510 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0520 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0530 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0540 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0550 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0560 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0570 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0580 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0590 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:05A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:05B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:05C0 00 00 0F 01 FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:05D0 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:05E0 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:05F0 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:0600 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:0610 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:0620 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0B43:0630 FF FF FF FF 01 01 01 01-01 01 01 01 01 01 01 01 ................ 0B43:0640 01 01 01 01 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0650 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0660 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0670 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0B43:0680 00 00 00 00 00 00 08 0A-84 09 2C 08 B6 05 C9 05 ..........,..... 0B43:0690 17 06 B6 05 85 06 18 07-B6 05 DE 07 B7 05 96 08 ................ 0B43:06A0 D2 08 B6 05 B6 05 B6 05-18 09 52 D1 E5 2E 8B 96 ..........R..... 0B43:06B0 86 05 FF D2 5A CB ....Z. -q ; function address table at cs:0586 0A08 – get_device_info() 0984 – init_device() (10b4) 082C – shutdown_device() 05B6 – do_nothing() 05C9 – note_off() 0617 – note_on() 05B6 – do_nothing() 0685 0718 05B6 – do_nothing() 07DE 05B7 0896 08D2 05B6 – do_nothing() (0a5d) 05B6 – do_nothing() (0b09) 05B6 – do_nothing() (0b1f) 0918 driver() – 06aa { 0B43:06AA 52 PUSH DX 0B43:06AB D1E5 SHL BP,1 ; get near address from table and jump into it 0B43:06AD 2E CS: 0B43:06AE 8B968605 MOV DX,[BP+0586] 0B43:06B2 FFD2 CALL DX 0B43:06B4 5A POP DX 0B43:06B5 CB RETF } /* Driver functions */ do_nothing() – 06b6 { 0B43:06B6 C3 RET } 06b7 { 0B43:06B7 2E CS: 0B43:06B8 A08505 MOV AL,[0585] 0B43:06BB 32E4 XOR AH,AH 0B43:06BD 80F9FF CMP CL,FF 0B43:06C0 7501 JNZ 06C3 0B43:06C2 C3 RET 0B43:06C3 2E CS: 0B43:06C4 880E8505 MOV [0585],CL 0B43:06C8 C3 RET } note_off() – 06c9 { 0B43:06C9 50 PUSH AX 0B43:06CA 56 PUSH SI 0B43:06CB 51 PUSH CX 0B43:06CC 3C09 CMP AL,09 0B43:06CE 7515 JNZ 06E5 0B43:06D0 86E9 XCHG CH,CL 0B43:06D2 8BF1 MOV SI,CX 0B43:06D4 86E9 XCHG CH,CL 0B43:06D6 83E67F AND SI,+7F 0B43:06D9 2E CS: 0B43:06DA 8AACC101 MOV CH,[SI+01C1] 0B43:06DE 80FDFF CMP CH,FF 0B43:06E1 7430 JZ 0713 0B43:06E3 EB27 JMP 070C 0B43:06E5 8BF0 MOV SI,AX 0B43:06E7 83E60F AND SI,+0F 0B43:06EA 2E CS: 0B43:06EB 80BC7405FF CMP BYTE PTR [SI+0574],FF 0B43:06F0 7421 JZ 0713 0B43:06F2 2E CS: 0B43:06F3 02AC4405 ADD CH,[SI+0544] 0B43:06F7 B4F4 MOV AH,F4 0B43:06F9 2E CS: 0B43:06FA 80BC440580 CMP BYTE PTR [SI+0544],80 0B43:06FF 7202 JB 0703 0B43:0701 B40C MOV AH,0C 0B43:0703 80FD80 CMP CH,80 0B43:0706 7204 JB 070C 0B43:0708 02EC ADD CH,AH 0B43:070A EBF7 JMP 0703 ; call send_message(90, 00) 0B43:070C B490 MOV AH,90 0B43:070E B100 MOV CL,00 0B43:0710 E8F401 CALL 0907 0B43:0713 59 POP CX 0B43:0714 5E POP SI 0B43:0715 58 POP AX 0B43:0716 C3 RET } note_on() – 0717 { 0B43:0717 50 PUSH AX 0B43:0718 56 PUSH SI 0B43:0719 51 PUSH CX 0B43:071A 57 PUSH DI 0B43:071B 3C09 CMP AL,09 0B43:071D 751A JNZ 0739 0B43:071F 86E9 XCHG CH,CL 0B43:0721 8BF1 MOV SI,CX 0B43:0723 86E9 XCHG CH,CL 0B43:0725 83E67F AND SI,+7F 0B43:0728 2E CS: 0B43:0729 8AACC101 MOV CH,[SI+01C1] 0B43:072D 80FDFF CMP CH,FF 0B43:0730 744E JZ 0780 0B43:0732 8BF0 MOV SI,AX 0B43:0734 83E60F AND SI,+0F 0B43:0737 EB27 JMP 0760 0B43:0739 8BF0 MOV SI,AX 0B43:073B 83E60F AND SI,+0F 0B43:073E 2E CS: 0B43:073F 80BC7405FF CMP BYTE PTR [SI+0574],FF 0B43:0744 743A JZ 0780 0B43:0746 2E CS: 0B43:0747 02AC4405 ADD CH,[SI+0544] 0B43:074B B4F4 MOV AH,F4 0B43:074D 2E CS: 0B43:074E 80BC440580 CMP BYTE PTR [SI+0544],80 0B43:0753 7202 JB 0757 0B43:0755 B40C MOV AH,0C 0B43:0757 80FD80 CMP CH,80 0B43:075A 7204 JB 0760 0B43:075C 02EC ADD CH,AH 0B43:075E EBF7 JMP 0757 0B43:0760 50 PUSH AX 0B43:0761 B080 MOV AL,80 0B43:0763 2E CS: 0B43:0764 F6A46405 MUL BYTE PTR [SI+0564] 0B43:0768 8BF9 MOV DI,CX 0B43:076A 83E77F AND DI,+7F 0B43:076D 03F8 ADD DI,AX 0B43:076F 58 POP AX 0B43:0770 2E CS: 0B43:0771 8A8DC202 MOV CL,[DI+02C2] 0B43:0775 2E CS: 0B43:0776 C684340501 MOV BYTE PTR [SI+0534],01 ; call send_message(90,*di+02c2) 0B43:077B B490 MOV AH,90 0B43:077D E88701 CALL 0907 0B43:0780 5F POP DI 0B43:0781 59 POP CX 0B43:0782 5E POP SI 0B43:0783 58 POP AX 0B43:0784 C3 RET } 0785 { 0B43:0785 50 PUSH AX 0B43:0786 56 PUSH SI 0B43:0787 8BF0 MOV SI,AX 0B43:0789 83E60F AND SI,+0F 0B43:078C 80E17F AND CL,7F 0B43:078F 80FD07 CMP CH,07 0B43:0792 7543 JNZ 07D7 0B43:0794 2E CS: 0B43:0795 888C0405 MOV [SI+0504],CL ; if *04c3 = 00, return 0B43:0799 2E CS: 0B43:079A 803EC30400 CMP BYTE PTR [04C3],00 0B43:079F 7502 JNZ 07A3 0B43:07A1 EB72 JMP 0815 0B43:07A3 2E CS: 0B43:07A4 028C5405 ADD CL,[SI+0554] 0B43:07A8 80F980 CMP CL,80 0B43:07AB 720C JB 07B9 0B43:07AD B17F MOV CL,7F 0B43:07AF 2E CS: 0B43:07B0 80BC540580 CMP BYTE PTR [SI+0554],80 0B43:07B5 7202 JB 07B9 0B43:07B7 B101 MOV CL,01 0B43:07B9 8AE8 MOV CH,AL ; set al = *04c2 0B43:07BB 2E CS: 0B43:07BC A0C204 MOV AL,[04C2] 0B43:07BF F6E1 MUL CL 0B43:07C1 B10F MOV CL,0F 0B43:07C3 F6F1 DIV CL 0B43:07C5 8AC8 MOV CL,AL 0B43:07C7 8AC5 MOV AL,CH 0B43:07C9 B507 MOV CH,07 0B43:07CB 0AC9 OR CL,CL 0B43:07CD 7541 JNZ 0810 0B43:07CF 0AE4 OR AH,AH 0B43:07D1 743D JZ 0810 0B43:07D3 FEC1 INC CL 0B43:07D5 EB39 JMP 0810 0B43:07D7 80FD0A CMP CH,0A 0B43:07DA 750E JNZ 07EA 0B43:07DC 2E CS: 0B43:07DD 388C1405 CMP [SI+0514],CL 0B43:07E1 7432 JZ 0815 0B43:07E3 2E CS: 0B43:07E4 888C1405 MOV [SI+0514],CL 0B43:07E8 EB26 JMP 0810 0B43:07EA 80FD40 CMP CH,40 0B43:07ED 750E JNZ 07FD 0B43:07EF 2E CS: 0B43:07F0 388C2405 CMP [SI+0524],CL 0B43:07F4 741F JZ 0815 0B43:07F6 2E CS: 0B43:07F7 888C2405 MOV [SI+0524],CL 0B43:07FB EB13 JMP 0810 0B43:07FD 80FD7B CMP CH,7B 0B43:0800 7513 JNZ 0815 0B43:0802 2E CS: 0B43:0803 80BC340500 CMP BYTE PTR [SI+0534],00 0B43:0808 740B JZ 0815 0B43:080A 2E CS: 0B43:080B C684340500 MOV BYTE PTR [SI+0534],00 0B43:0810 B4B0 MOV AH,B0 0B43:0812 E8F200 CALL 0907 0B43:0815 5E POP SI 0B43:0816 58 POP AX 0B43:0817 C3 RET } 0B43:0818 50 PUSH AX 0B43:0819 56 PUSH SI 0B43:081A 51 PUSH CX 0B43:081B 53 PUSH BX 0B43:081C 3C09 CMP AL,09 0B43:081E 7453 JZ 0873 0B43:0820 8BF0 MOV SI,AX 0B43:0822 83E60F AND SI,+0F 0B43:0825 2E CS: 0B43:0826 388CC404 CMP [SI+04C4],CL 0B43:082A 7447 JZ 0873 0B43:082C 2E CS: 0B43:082D 888CC404 MOV [SI+04C4],CL 0B43:0831 8BF1 MOV SI,CX 0B43:0833 83E67F AND SI,+7F 0B43:0836 2E CS: 0B43:0837 8A8C4100 MOV CL,[SI+0041] 0B43:083B 2E CS: 0B43:083C 8AACC100 MOV CH,[SI+00C1] 0B43:0840 2E CS: 0B43:0841 8ABC4101 MOV BH,[SI+0141] 0B43:0845 2E CS: 0B43:0846 8A9C4202 MOV BL,[SI+0242] 0B43:084A 8BF0 MOV SI,AX 0B43:084C 83E60F AND SI,+0F 0B43:084F 2E CS: 0B43:0850 889C6405 MOV [SI+0564],BL 0B43:0854 32DB XOR BL,BL 0B43:0856 2E CS: 0B43:0857 80BC7405FF CMP BYTE PTR [SI+0574],FF 0B43:085C 7502 JNZ 0860 0B43:085E FEC3 INC BL 0B43:0860 2E CS: 0B43:0861 888C7405 MOV [SI+0574],CL 0B43:0865 80F9FF CMP CL,FF 0B43:0868 750B JNZ 0875 0B43:086A B4B0 MOV AH,B0 0B43:086C B57B MOV CH,7B 0B43:086E 32C9 XOR CL,CL 0B43:0870 E89400 CALL 0907 0B43:0873 EB64 JMP 08D9 0B43:0875 2E CS: 0B43:0876 3AAC4405 CMP CH,[SI+0544] 0B43:087A 7412 JZ 088E 0B43:087C 2E CS: 0B43:087D 88AC4405 MOV [SI+0544],CH 0B43:0881 51 PUSH CX 0B43:0882 B4B0 MOV AH,B0 0B43:0884 B57B MOV CH,7B 0B43:0886 32C9 XOR CL,CL 0B43:0888 E87C00 CALL 0907 0B43:088B 59 POP CX 0B43:088C FEC3 INC BL 0B43:088E 0ADB OR BL,BL 0B43:0890 7507 JNZ 0899 0B43:0892 2E CS: 0B43:0893 3ABC5405 CMP BH,[SI+0554] 0B43:0897 7411 JZ 08AA 0B43:0899 2E CS: 0B43:089A 88BC5405 MOV [SI+0554],BH 0B43:089E 51 PUSH CX 0B43:089F 2E CS: 0B43:08A0 8A8C0405 MOV CL,[SI+0504] 0B43:08A4 B507 MOV CH,07 0B43:08A6 E8DCFE CALL 0785 0B43:08A9 59 POP CX 0B43:08AA B4C0 MOV AH,C0 0B43:08AC E85800 CALL 0907 0B43:08AF 0ADB OR BL,BL 0B43:08B1 7426 JZ 08D9 0B43:08B3 B4B0 MOV AH,B0 0B43:08B5 B50A MOV CH,0A 0B43:08B7 2E CS: 0B43:08B8 8A8C1405 MOV CL,[SI+0514] 0B43:08BC 80E17F AND CL,7F 0B43:08BF E84500 CALL 0907 0B43:08C2 D1E6 SHL SI,1 0B43:08C4 2E CS: 0B43:08C5 8A8CD404 MOV CL,[SI+04D4] 0B43:08C9 80E17F AND CL,7F 0B43:08CC 2E CS: 0B43:08CD 8AACD504 MOV CH,[SI+04D5] 0B43:08D1 80E57F AND CH,7F 0B43:08D4 B4E0 MOV AH,E0 0B43:08D6 E82E00 CALL 0907 0B43:08D9 5B POP BX 0B43:08DA 59 POP CX 0B43:08DB 5E POP SI 0B43:08DC 58 POP AX 0B43:08DD C3 RET 0B43:08DE 50 PUSH AX 0B43:08DF 56 PUSH SI 0B43:08E0 8BF0 MOV SI,AX 0B43:08E2 83E60F AND SI,+0F 0B43:08E5 D1E6 SHL SI,1 0B43:08E7 2E CS: 0B43:08E8 388CD404 CMP [SI+04D4],CL 0B43:08EC 7507 JNZ 08F5 0B43:08EE 2E CS: 0B43:08EF 38ACD504 CMP [SI+04D5],CH 0B43:08F3 740F JZ 0904 0B43:08F5 2E CS: 0B43:08F6 888CD404 MOV [SI+04D4],CL 0B43:08FA 2E CS: 0B43:08FB 88ACD504 MOV [SI+04D5],CH 0B43:08FF B4E0 MOV AH,E0 0B43:0901 E80300 CALL 0907 0B43:0904 5E POP SI 0B43:0905 58 POP AX 0B43:0906 C3 RET send_message(ax) - 0907 { 0B43:0907 53 PUSH BX 0B43:0908 8AD0 MOV DL,AL 0B43:090A 0AD4 OR DL,AH ; call send_midi_byte(*0584) 0B43:090C 2E CS: 0B43:090D 88168405 MOV [0584],DL 0B43:0911 8ADA MOV BL,DL 0B43:0913 E85200 CALL 0968 0B43:0916 80FCC0 CMP AH,C0 0B43:0919 740A JZ 0925 0B43:091B 80FCD0 CMP AH,D0 0B43:091E 7405 JZ 0925 ; call send_midi_byte(ch) 0B43:0920 8ADD MOV BL,CH 0B43:0922 E84300 CALL 0968 ; call send_midi_byte(cl) 0B43:0925 8AD9 MOV BL,CL 0B43:0927 E83E00 CALL 0968 0B43:092A 5B POP BX 0B43:092B C3 RET } shutdown_device() - 092c { 0B43:092C 53 PUSH BX ; call mpu_reset() 0B43:092D E8E000 CALL 0A10 0B43:0930 5B POP BX 0B43:0931 C3 RET } mpu_command(bl) - 0932 { 0B43:0932 9C PUSHF 0B43:0933 FA CLI 0B43:0934 50 PUSH AX 0B43:0935 51 PUSH CX 0B43:0936 52 PUSH DX 0B43:0937 B9FFFF MOV CX,FFFF ; get data ready value from port 0331 0B43:093A BA3103 MOV DX,0331 0B43:093D EC IN AL,DX ; if al == 40, jump to 094a 0B43:093E A840 TEST AL,40 0B43:0940 7408 JZ 094A 0B43:0942 49 DEC CX 0B43:0943 83F900 CMP CX,+00 0B43:0946 75F5 JNZ 093D 0B43:0948 EB19 JMP 0963 ; write data to port 0331 0B43:094A 8AC3 MOV AL,BL 0B43:094C EE OUT DX,AL 0B43:094D B9FFFF MOV CX,FFFF ; read value from port 0331 0B43:0950 EC IN AL,DX 0B43:0951 D0C0 ROL AL,1 0B43:0953 7306 JNB 095B 0B43:0955 49 DEC CX 0B43:0956 83F900 CMP CX,+00 0B43:0959 75F5 JNZ 0950 ; get value from port 0330 0B43:095B BA3003 MOV DX,0330 0B43:095E EC IN AL,DX ; does nothing 0B43:095F 3CFE CMP AL,FE 0B43:0961 7400 JZ 0963 0B43:0963 5A POP DX 0B43:0964 59 POP CX 0B43:0965 58 POP AX 0B43:0966 9D POPF 0B43:0967 C3 RET } send_midi_byte(bl) - 0968 { 0B43:0968 9C PUSHF 0B43:0969 FA CLI 0B43:096A 50 PUSH AX 0B43:096B 51 PUSH CX 0B43:096C 52 PUSH DX ; set status port number = 331 0B43:096D BA3103 MOV DX,0331 ; initialize timeout counter 0B43:0970 B9FF00 MOV CX,00FF ; read status from port 331 0B43:0973 EC IN AL,DX ; if ready (0x40) jump to 098b to write data 0B43:0974 A840 TEST AL,40 0B43:0976 7413 JZ 098B ; cx-- 0B43:0978 49 DEC CX 0B43:0979 D0C0 ROL AL,1 0B43:097B 7207 JB 0984 ; clear any incoming data from data port 0B43:097D BA3003 MOV DX,0330 0B43:0980 EC IN AL,DX ; set port back to status (331) 0B43:0981 BA3103 MOV DX,0331 ; loop back 0B43:0984 83F901 CMP CX,+01 0B43:0987 7DEA JGE 0973 ; still not ready, so return 0B43:0989 EB06 JMP 0991 ; write data in BL to port 330 0B43:098B BA3003 MOV DX,0330 0B43:098E 8AC3 MOV AL,BL 0B43:0990 EE OUT DX,AL ; return 0B43:0991 5A POP DX 0B43:0992 59 POP CX 0B43:0993 58 POP AX 0B43:0994 9D POPF 0B43:0995 C3 RET } 0996(cl) { 0B43:0996 53 PUSH BX 0B43:0997 51 PUSH CX 0B43:0998 56 PUSH SI ; set al = *04c2 0B43:0999 2E CS: 0B43:099A A0C204 MOV AL,[04C2] ; set ah = 00 0B43:099D 32E4 XOR AH,AH ; if cl == ff, return 0B43:099F 80F9FF CMP CL,FF 0B43:09A2 742A JZ 09CE ; set *04c2 = cl 0B43:09A4 2E CS: 0B43:09A5 880EC204 MOV [04C2],CL ; if *04c3 == 00, return 0B43:09A9 2E CS: 0B43:09AA 803EC30400 CMP BYTE PTR [04C3],00 0B43:09AF 741D JZ 09CE 0B43:09B1 50 PUSH AX 0B43:09B2 B001 MOV AL,01 0B43:09B4 BE0100 MOV SI,0001 0B43:09B7 B507 MOV CH,07 0B43:09B9 2E CS: 0B43:09BA 8A8C0405 MOV CL,[SI+0504] 0B43:09BE 80F9FF CMP CL,FF 0B43:09C1 7403 JZ 09C6 ; call 0785 0B43:09C3 E8BFFD CALL 0785 0B43:09C6 FEC0 INC AL 0B43:09C8 46 INC SI 0B43:09C9 3C0A CMP AL,0A 0B43:09CB 75EC JNZ 09B9 0B43:09CD 58 POP AX 0B43:09CE 5E POP SI 0B43:09CF 59 POP CX 0B43:09D0 5B POP BX 0B43:09D1 C3 RET } 09d2 { 0B43:09D2 32E4 XOR AH,AH 0B43:09D4 2E CS: 0B43:09D5 A0C304 MOV AL,[04C3] 0B43:09D8 80F9FF CMP CL,FF 0B43:09DB 7501 JNZ 09DE 0B43:09DD C3 RET 0B43:09DE 50 PUSH AX 0B43:09DF 51 PUSH CX 0B43:09E0 80F900 CMP CL,00 0B43:09E3 751A JNZ 09FF 0B43:09E5 2E CS: 0B43:09E6 C606C30400 MOV BYTE PTR [04C3],00 0B43:09EB B001 MOV AL,01 0B43:09ED B4B0 MOV AH,B0 0B43:09EF B507 MOV CH,07 0B43:09F1 B100 MOV CL,00 ; do { ; call 0907 0B43:09F3 E811FF CALL 0907 ; a++ 0B43:09F6 FEC0 INC AL ; loop while al == 09 0B43:09F8 3C09 CMP AL,09 0B43:09FA 75F7 JNZ 09F3 } 0B43:09FC 59 POP CX 0B43:09FD 58 POP AX 0B43:09FE C3 RET ; set *04c3 = 01 0B43:09FF 2E CS: 0B43:0A00 C606C30401 MOV BYTE PTR [04C3],01 ; set cl = *04c2 0B43:0A05 2E CS: 0B43:0A06 8A0EC204 MOV CL,[04C2] ; call 0996 0B43:0A0A E889FF CALL 0996 0B43:0A0D 59 POP CX 0B43:0A0E 58 POP AX 0B43:0A0F C3 RET } mpu_reset() - 0a10 { 0B43:0A10 53 PUSH BX ; call mpu_command(ff) 0B43:0A11 B3FF MOV BL,FF 0B43:0A13 E81CFF CALL 0932 0B43:0A16 5B POP BX 0B43:0A17 C3 RET } 0a18 { 0B43:0A18 56 PUSH SI 0B43:0A19 8BF0 MOV SI,AX 0B43:0A1B 83E60F AND SI,+0F 0B43:0A1E 80FCE0 CMP AH,E0 0B43:0A21 7516 JNZ 0A39 0B43:0A23 D1E6 SHL SI,1 0B43:0A25 2E CS: 0B43:0A26 8B84D404 MOV AX,[SI+04D4] 0B43:0A2A 3DFFFF CMP AX,FFFF 0B43:0A2D 7453 JZ 0A82 0B43:0A2F 86E0 XCHG AH,AL 0B43:0A31 D0EC SHR AH,1 0B43:0A33 7302 JNB 0A37 0B43:0A35 0C80 OR AL,80 0B43:0A37 EB49 JMP 0A82 0B43:0A39 80FCC0 CMP AH,C0 0B43:0A3C 7507 JNZ 0A45 0B43:0A3E 2E CS: 0B43:0A3F 8A84C404 MOV AL,[SI+04C4] 0B43:0A43 EB3D JMP 0A82 0B43:0A45 80FCB0 CMP AH,B0 0B43:0A48 7535 JNZ 0A7F 0B43:0A4A 80FD4B CMP CH,4B 0B43:0A4D 7430 JZ 0A7F 0B43:0A4F 80FD01 CMP CH,01 0B43:0A52 7507 JNZ 0A5B 0B43:0A54 2E CS: 0B43:0A55 8A84F404 MOV AL,[SI+04F4] 0B43:0A59 EB27 JMP 0A82 0B43:0A5B 80FD07 CMP CH,07 0B43:0A5E 7507 JNZ 0A67 0B43:0A60 2E CS: 0B43:0A61 8A840405 MOV AL,[SI+0504] 0B43:0A65 EB1B JMP 0A82 0B43:0A67 80FD0A CMP CH,0A 0B43:0A6A 7507 JNZ 0A73 0B43:0A6C 2E CS: 0B43:0A6D 8A841405 MOV AL,[SI+0514] 0B43:0A71 EB0F JMP 0A82 0B43:0A73 80FD40 CMP CH,40 0B43:0A76 7507 JNZ 0A7F 0B43:0A78 2E CS: 0B43:0A79 8A842405 MOV AL,[SI+0524] 0B43:0A7D EB03 JMP 0A82 0B43:0A7F B8FFFF MOV AX,FFFF 0B43:0A82 5E POP SI 0B43:0A83 C3 RET } init_device() - 0a84 { 0B43:0A84 56 PUSH SI ; call mpu_reset() 0B43:0A85 E888FF CALL 0A10 ; call mpu_command(3f) 0B43:0A88 BB3F00 MOV BX,003F 0B43:0A8B E8A4FE CALL 0932 0B43:0A8E E86300 CALL 0AF4 ; call mpu_command(3f) 0B43:0A91 BB3F00 MOV BX,003F 0B43:0A94 E89BFE CALL 0932 0B43:0A97 E85A00 CALL 0AF4 ; call mpu_command(3f) 0B43:0A9A BB3F00 MOV BX,003F 0B43:0A9D E892FE CALL 0932 0B43:0AA0 E85100 CALL 0AF4 0B43:0AA3 E84E00 CALL 0AF4 0B43:0AA6 8BF0 MOV SI,AX 0B43:0AA8 BF0000 MOV DI,0000 0B43:0AAB 26 ES: 0B43:0AAC 8A1C MOV BL,[SI] 0B43:0AAE 2E CS: 0B43:0AAF 889D4100 MOV [DI+0041],BL 0B43:0AB3 47 INC DI 0B43:0AB4 46 INC SI 0B43:0AB5 81FF8104 CMP DI,0481 0B43:0AB9 75F0 JNZ 0AAB 0B43:0ABB 2E CS: 0B43:0ABC 8A1E4102 MOV BL,[0241] 0B43:0AC0 2E CS: 0B43:0AC1 881E5D05 MOV [055D],BL 0B43:0AC5 26 ES: 0B43:0AC6 8A0C MOV CL,[SI] 0B43:0AC8 46 INC SI 0B43:0AC9 26 ES: 0B43:0ACA 8A2C MOV CH,[SI] 0B43:0ACC 46 INC SI 0B43:0ACD 83F900 CMP CX,+00 0B43:0AD0 7414 JZ 0AE6 0B43:0AD2 26 ES: 0B43:0AD3 8A1C MOV BL,[SI] 0B43:0AD5 46 INC SI ; call send_midi_byte(??) 0B43:0AD6 E88FFE CALL 0968 0B43:0AD9 80FBF7 CMP BL,F7 0B43:0ADC 7506 JNZ 0AE4 0B43:0ADE E81300 CALL 0AF4 0B43:0AE1 E81000 CALL 0AF4 0B43:0AE4 E2EC LOOP 0AD2 ; call 0996(0c) 0B43:0AE6 B10C MOV CL,0C 0B43:0AE8 E8ABFE CALL 0996 ; set ax = 0984 0B43:0AEB B88409 MOV AX,0984 ; set cx = 0801 0B43:0AEE B101 MOV CL,01 0B43:0AF0 B508 MOV CH,08 0B43:0AF2 5E POP SI 0B43:0AF3 C3 RET } 0B43:0AF4 50 PUSH AX 0B43:0AF5 52 PUSH DX 0B43:0AF6 57 PUSH DI 0B43:0AF7 BA3103 MOV DX,0331 0B43:0AFA BF0075 MOV DI,7500 0B43:0AFD EC IN AL,DX 0B43:0AFE 4F DEC DI 0B43:0AFF 83FF00 CMP DI,+00 0B43:0B02 75F9 JNZ 0AFD 0B43:0B04 5F POP DI 0B43:0B05 5A POP DX 0B43:0B06 58 POP AX 0B43:0B07 C3 RET get_device_info() - 0b08 { ; don’t use sfx 0B43:0B08 B401 MOV AH,01 ; use sfx # 0B08 B401 mov ah,11 ; load GM map 0B43:0B0A B004 MOV AL,04 0B43:0B0C B50C MOV CH,0C 0B43:0B0E B120 MOV CL,20 0B43:0B10 C3 RET } /* added for GM Blast driver */ ; genmidi.drv uses 04c2,04c3 the same way that ; mtblast.drv uses 015e,0160 ; mtblast.drv uses 08c7-0912, difference of 0x024a ; (reflected as 07c7-0812 or 0a11-0a5c in code) ; 0B11-0B5C = 76 bytes of 0’s 0B43:0B11 0000 ADD [BX+SI],AL 0B43:0B13 0000 ADD [BX+SI],AL 0B43:0B15 0000 ADD [BX+SI],AL 0B43:0B17 0000 ADD [BX+SI],AL 0B43:0B19 0000 ADD [BX+SI],AL 0B43:0B1B 0000 ADD [BX+SI],AL 0B43:0B1D 0000 ADD [BX+SI],AL 0B43:0B1F 0000 ADD [BX+SI],AL 0B43:0B21 0000 ADD [BX+SI],AL 0B43:0B23 0000 ADD [BX+SI],AL 0B43:0B25 0000 ADD [BX+SI],AL 0B43:0B27 0000 ADD [BX+SI],AL 0B43:0B29 0000 ADD [BX+SI],AL 0B43:0B2B 0000 ADD [BX+SI],AL 0B43:0B2D 0000 ADD [BX+SI],AL 0B43:0B2F 0000 ADD [BX+SI],AL 0B43:0B31 0000 ADD [BX+SI],AL 0B43:0B33 0000 ADD [BX+SI],AL 0B43:0B35 0000 ADD [BX+SI],AL 0B43:0B37 0000 ADD [BX+SI],AL 0B43:0B39 0000 ADD [BX+SI],AL 0B43:0B3B 0000 ADD [BX+SI],AL 0B43:0B3D 0000 ADD [BX+SI],AL 0B43:0B3F 0000 ADD [BX+SI],AL 0B43:0B41 0000 ADD [BX+SI],AL 0B43:0B43 0000 ADD [BX+SI],AL 0B43:0B45 0000 ADD [BX+SI],AL 0B43:0B47 0000 ADD [BX+SI],AL 0B43:0B49 0000 ADD [BX+SI],AL 0B43:0B4B 0000 ADD [BX+SI],AL 0B43:0B4D 0000 ADD [BX+SI],AL 0B43:0B4F 0000 ADD [BX+SI],AL 0B43:0B51 0000 ADD [BX+SI],AL 0B43:0B53 0000 ADD [BX+SI],AL 0B43:0B55 0000 ADD [BX+SI],AL 0B43:0B57 0000 ADD [BX+SI],AL 0B43:0B59 0000 ADD [BX+SI],AL 0B43:0B5B 0000 ADD [BX+SI],AL ; 10b2-10b3 (formerly 00ef-00f0) = sb port (220) ; 0a1a (formerly 07d0) = sample loaded (01) or unloaded (00) ; 0a40-0a41 (formerly 07f6-07f7) = size of audio data ; 0a49 (formerly 07ff) = sb irq ; 0a4e (formerly 0804) = timer constant load_sample(ax,cl,ch) - 0b5d { ; ax = some address ; cl = must be non-zero to play ; ch = ? ; if cl == 0, return 0B43:0B5D 80F900 CMP CL,00 0B43:0B60 7501 JNZ 0B63 0B43:0B62 C3 RET ; if *04c2 == 0, return 0B43:0B63 2E CS: 0B43:0B64 803E5E0100 CMP BYTE PTR [04c2],00 0B43:0B69 7501 JNZ 0B6C 0B43:0B6B C3 RET ; if *04c3 == 0, return 0B43:0B6C 2E CS: 0B43:0B6D 803E600100 CMP BYTE PTR [04c3],00 0B43:0B72 7501 JNZ 0B75 0B43:0B74 C3 RET 0B43:0B75 53 PUSH BX 0B43:0B76 51 PUSH CX 0B43:0B77 52 PUSH DX ; set *cs:07d1 = ch 0B43:0B78 2E CS: 0B43:0B79 882ED107 MOV [07D1],CH ; set *cs:07d2 = 00 0B43:0B7D 2E CS: 0B43:0B7E C606D20700 MOV BYTE PTR [07D2],00 ; set bx = ax (input address) 0B43:0B83 8BD8 MOV BX,AX ; loop until we find first address that does not contain 0xFE ; (who knows why?) { ; bx++ 0B43:0B85 43 INC BX ; if *bx == fe, loop back to 0b85 0B43:0B86 803FFE CMP BYTE PTR [BX],FE 0B43:0B89 74FA JZ 0B85 } ; bx++ 0B43:0B8B 43 INC BX ; bx now points to address after last 0xFE ; which I believe is the sampling rate ; set cx = *bx (sampling rate, it would seem) 0B43:0B8C 8B0F MOV CX,[BX] ; if cx >= 0f34 (3892 dec), jump to 0b9c 0B43:0B8E 81F9340F CMP CX,0F34 0B43:0B92 7308 JNB 0B9C ; no timer constant ; set *0804 = 00 (timer constant) 0B43:0B94 2E CS: 0B43:0B95 C606040800 MOV BYTE PTR [0804],00 ; jump to 0bad 0B43:0B9A EB11 JMP 0BAD ; compute timer constant ; set dx,ax = 0f4240 (1000000 dec) 0B43:0B9C BA0F00 MOV DX,000F 0B43:0B9F B84042 MOV AX,4240 ; ax = 0f4240 / cx 0B43:0BA2 F7F1 DIV CX ; set ah = ff - al 0B43:0BA4 32E4 XOR AH,AH 0B43:0BA6 2AE0 SUB AH,AL ; set *0804 = ah (timer constant) 0B43:0BA8 2E CS: 0B43:0BA9 88260408 MOV [0804],AH ; it looks like we’re computing and saving some kind of offsets into the sample... ; set ax = *bx+2 (???) 0B43:0BAD 8B4702 MOV AX,[BX+02] ; set *07d5 = *07db = ds 0B43:0BB0 8CD9 MOV CX,DS 0B43:0BB2 2E CS: 0B43:0BB3 890ED507 MOV [07D5],CX 0B43:0BB7 2E CS: 0B43:0BB8 890EDB07 MOV [07DB],CX ; set cx = bx + *bx+04 (???) 0B43:0BBC 8BCB MOV CX,BX 0B43:0BBE 034F04 ADD CX,[BX+04] ; set dx = cs 0B43:0BC1 8BD1 MOV DX,CX ; set *07d3 = cx + 8 0B43:0BC3 83C108 ADD CX,+08 0B43:0BC6 2E CS: 0B43:0BC7 890ED307 MOV [07D3],CX ; set cx = bx + *bx+6 0B43:0BCB 8BCB MOV CX,BX 0B43:0BCD 034F06 ADD CX,[BX+06] ; set *07d9 = cx + 8 0B43:0BD0 83C108 ADD CX,+08 0B43:0BD3 2E CS: 0B43:0BD4 890ED907 MOV [07D9],CX 0B43:0BD8 83E908 SUB CX,+08 0B43:0BDB 2BCA SUB CX,DX 0B43:0BDD 2E CS: 0B43:0BDE 890ED707 MOV [07D7],CX 0B43:0BE2 8BC8 MOV CX,AX 0B43:0BE4 2B4F06 SUB CX,[BX+06] 0B43:0BE7 2E CS: 0B43:0BE8 890EDD07 MOV [07DD],CX 0B43:0BEC 2BC1 SUB AX,CX 0B43:0BEE 2E CS: 0B43:0BEF A30908 MOV [0809],AX 0B43:0BF2 83C308 ADD BX,+08 ; set *0805,*0807 = ds,bx (address of sample ???) 0B43:0BF5 2E CS: 0B43:0BF6 8C1E0508 MOV [0805],DS 0B43:0BFA 2E CS: 0B43:0BFB 891E0708 MOV [0807],BX ; set *07d0 = 01 (sample loaded?) 0B43:0BFF 2E CS: 0B43:0C00 C606D00701 MOV BYTE PTR [07D0],01 0B43:0C05 5A POP DX 0B43:0C06 59 POP CX 0B43:0C07 5B POP BX 0B43:0C08 C3 RET } stop_sample() - 0c09 { ; set *07d1 = 00 0B43:0C09 2E CS: 0B43:0C0A C606D10700 MOV BYTE PTR [07D1],00 ; set *07d2 = 01 0B43:0C0F 2E CS: 0B43:0C10 C606D20701 MOV BYTE PTR [07D2],01 ; call 112e 0B43:0C15 E81605 CALL 112E ; set *07d0 = 00 (sample unloaded) 0B43:0C18 2E CS: 0B43:0C19 C606D00700 MOV BYTE PTR [07D0],00 0B43:0C1E C3 RET } play_sample() - 0c1f { ; set *07d1 = ch 0B43:0C1F 2E CS: 0B43:0C20 882ED107 MOV [07D1],CH ; if 07d0 != 01 (sample not loaded?), jump to 0c2f (skip playing sample) 0B43:0C24 2E CS: 0B43:0C25 803ED00701 CMP BYTE PTR [07D0],01 0B43:0C2A 7503 JNZ 0C2F ; call 108b 0B43:0C2C E85C04 CALL 108B ; clear al (success) 0B43:0C2F 32C0 XOR AL,AL ; if *0800 != 0000, jump to 0c3b 0B43:0C31 2E CS: 0B43:0C32 833E000800 CMP WORD PTR [0800],+00 0B43:0C37 7502 JNZ 0C3B ; otherwise, set al = 01 (failure) 0B43:0C39 B001 MOV AL,01 ; clear ah 0B43:0C3B 32E4 XOR AH,AH 0B43:0C3D C3 RET } write_to_port(al,dx) - 0c3e { ; al = data ; dx = port number ; carry flag set on error ; set cx = 0x0200 (loop ctr) 0B43:0C3E B90002 MOV CX,0200 ; set ah = al 0B43:0C41 8AE0 MOV AH,AL ; waits until status bit is clear { ; get data from port dx 0B43:0C43 EC IN AL,DX ; if bit 7 of al is 0, jump to 0c4d 0B43:0C44 0AC0 OR AL,AL 0B43:0C46 7905 JNS 0C4D ; loop back 0B43:0C48 E2F9 LOOP 0C43 } ; sb never ready – set carry flag and return 0B43:0C4A F9 STC 0B43:0C4B EB04 JMP 0C51 ; set al = ah 0B43:0C4D 8AC4 MOV AL,AH ; write al to port 0B43:0C4F EE OUT DX,AL ; clear carry (successful write) 0B43:0C50 F8 CLC 0B43:0C51 C3 RET } read_from_port() - 0c52 { ; carry flag set on error, ; byte value returned in al 0B43:0C52 52 PUSH DX ; set dx = 0x22e (for read status) 0B43:0C53 2E CS: 0B43:0C54 8B16EF00 MOV DX,[00EF] 0B43:0C58 80C20E ADD DL,0E ; set cx = 0200 (loop ctr) 0B43:0C5B B90002 MOV CX,0200 ; wait until status bit is set { 0B43:0C5E EC IN AL,DX ; if bit 7 of al is 0, jump to 0c68 0B43:0C5F 0AC0 OR AL,AL 0B43:0C61 7805 JS 0C68 ; loop back 0B43:0C63 E2F9 LOOP 0C5E } ; sb never ready - set carry flag and return 0B43:0C65 F9 STC 0B43:0C66 EB05 JMP 0C6D ; read from port 0x22a 0B43:0C68 80EA04 SUB DL,04 0B43:0C6B EC IN AL,DX ; clear carry (successful read) 0B43:0C6C F8 CLC 0B43:0C6D 5A POP DX 0B43:0C6E C3 RET } write_to_port(al,dx) – 0c6f { ; al = data ; dx = port number 0B43:0C6F 51 PUSH CX ;set cx = 03e8 (loop ctr, dec 1000) 0B43:0C70 B9E803 MOV CX,03E8 ; ah = al 0B43:0C73 8AE0 MOV AH,AL ; waits until status bit is clear { ; get data from port dx 0B43:0C75 EC IN AL,DX ; if bit 7 of al is 0, jump to 0c7c 0B43:0C76 0AC0 OR AL,AL 0B43:0C78 7902 JNS 0C7C ; loop back 0B43:0C7A E2F9 LOOP 0C75 } ; set al = ah 0B43:0C7C 8AC4 MOV AL,AH ; write al to port dx 0B43:0C7E EE OUT DX,AL ; return 0B43:0C7F 59 POP CX 0B43:0C80 C3 RET } read_from_port() - 0c81 { ; byte value returned in al 0B43:0C81 52 PUSH DX ; set dx = 0x22e (for read status) 0B43:0C82 2E CS: 0B43:0C83 8B16EF00 MOV DX,[00EF] 0B43:0C87 80C20E ADD DL,0E ; clear al 0B43:0C8A 32C0 XOR AL,AL { ; read from 0x22e (int ack/read status) 0B43:0C8C EC IN AL,DX ; if bit 7 is clear, loop back 0B43:0C8D 0AC0 OR AL,AL 0B43:0C8F 79FB JNS 0C8C } ; read byte from 0x22a 0B43:0C91 80EA04 SUB DL,04 0B43:0C94 EC IN AL,DX 0B43:0C95 5A POP DX 0B43:0C96 C3 RET } reset_dsp() - 0c97 { ; set dx = port 0x226 0B43:0C97 2E CS: 0B43:0C98 8B16EF00 MOV DX,[00EF] 0B43:0C9C 80C206 ADD DL,06 ; write 01 to port 0x226 (dsp reset) 0B43:0C9F B001 MOV AL,01 0B43:0CA1 EE OUT DX,AL ; read from 0x226 8 times 0B43:0CA2 EC IN AL,DX 0B43:0CA3 EC IN AL,DX 0B43:0CA4 EC IN AL,DX 0B43:0CA5 EC IN AL,DX 0B43:0CA6 EC IN AL,DX 0B43:0CA7 EC IN AL,DX 0B43:0CA8 EC IN AL,DX 0B43:0CA9 EC IN AL,DX ; write 00 to port 0x226 (dsp reset) 0B43:0CAA 32C0 XOR AL,AL 0B43:0CAC EE OUT DX,AL ; set cl = 20 (loop ctr) 0B43:0CAD B120 MOV CL,20 { ; call read_from_port() 0B43:0CAF E8A0FF CALL 0C52 ; if return value = 0xAA (DSP_READY), jump to 0cbf 0B43:0CB2 3CAA CMP AL,AA 0B43:0CB4 7409 JZ 0CBF ; cl--, and loop back 0B43:0CB6 FEC9 DEC CL 0B43:0CB8 75F5 JNZ 0CAF } ; set return code = 0002 (failure) and return 0B43:0CBA B80200 MOV AX,0002 0B43:0CBD EB02 JMP 0CC1 ; set return code = 0000 (success) 0B43:0CBF 33C0 XOR AX,AX ; set flags and return 0B43:0CC1 0BC0 OR AX,AX 0B43:0CC3 C3 RET } 0cc4 { ;set bx = 02 (failure) 0B43:0CC4 BB0200 MOV BX,0002 ; set al = e0 (dsp identification) 0B43:0CC7 B0E0 MOV AL,E0 ; set dx = 0x22c (dsp write) 0B43:0CC9 2E CS: 0B43:0CCA 8B16EF00 MOV DX,[00EF] 0B43:0CCE 83C20C ADD DX,+0C ; get dsp identification (cmd e0) ; call write_to_port(e0, 0x22c) 0B43:0CD1 E86AFF CALL 0C3E ; if error, jump to 0ce8 0B43:0CD4 7212 JB 0CE8 ; cmd aa = ?? ; call write_to_port(aa, 0x22c) 0B43:0CD6 B0AA MOV AL,AA 0B43:0CD8 E863FF CALL 0C3E ; if error, jump to 0ce8 0B43:0CDB 720B JB 0CE8 ; call read_from_port() 0B43:0CDD E872FF CALL 0C52 ; if error, jump to 0ce8 0B43:0CE0 7206 JB 0CE8 ; if returned data != 0x55, return 0B43:0CE2 3C55 CMP AL,55 0B43:0CE4 7502 JNZ 0CE8 ; clear bx (success) 0B43:0CE6 33DB XOR BX,BX ; set ax = bx (return code) 0B43:0CE8 8BC3 MOV AX,BX ; set flags 0B43:0CEA 0BC0 OR AX,AX ; return 0B43:0CEC C3 RET } determine_sb_irq() - 0ced { ; set irq’s 2, 5, and 7 ; whichever irq actually responds ; when we talk to 0x220 is our sb irq ; call set_interrupt(02, 0a2d, 0d6f) 0B43:0CED B002 MOV AL,02 0B43:0CEF BA250B MOV DX,0D6F 0B43:0CF2 BBE307 MOV BX,0A2D 0B43:0CF5 E8FC00 CALL 0DF4 ; call set_interrupt(05, 0a31, 0d8d) 0B43:0CF8 B005 MOV AL,05 0B43:0CFA BA430B MOV DX,0D8D 0B43:0CFD BBE707 MOV BX,0A31 0B43:0D00 E8F100 CALL 0DF4 ; call set_interrupt(05, 0a35, 0dab) 0B43:0D03 B005 MOV AL,05 0B43:0D05 BA610B MOV DX,0DAB 0B43:0D08 BBEB07 MOV BX,0A35 0B43:0D0B E8E600 CALL 0DF4 ; call set_interrupt(07, 0a39, 0dc9) 0B43:0D0E B007 MOV AL,07 0B43:0D10 BA7F0B MOV DX,0DC9 0B43:0D13 BBEF07 MOV BX,0A39 0B43:0D16 E8DB00 CALL 0DF4 ; cs:0bed is the address of this method ; call compute_absolute_address(cs, 0bed) 0B43:0D19 8CCA MOV DX,CS 0B43:0D1B B8A309 MOV AX,0BED 0B43:0D1E E8BF00 CALL 0DE0 ; call program_dma(0000, 49, dl,ax) 0B43:0D21 33C9 XOR CX,CX 0B43:0D23 B649 MOV DH,49 0B43:0D25 E88F00 CALL 0DB7 ; set dx = 0x22c 0B43:0D28 2E CS: 0B43:0D29 8B16EF00 MOV DX,[00EF] 0B43:0D2D 83C20C ADD DX,+0C ; set time constant (cmd 40) to 0x64 (100) ; call write_to_port(40, 022c) 0B43:0D30 B040 MOV AL,40 0B43:0D32 E83AFF CALL 0C6F ; call write_to_port(64, 022c) 0B43:0D35 B064 MOV AL,64 0B43:0D37 E835FF CALL 0C6F ; dma mode output, 0 bytes length ; this is a dummy playback just to trigger the irq callback ; call write_to_port(14, 022c) 0B43:0D3A B014 MOV AL,14 0B43:0D3C E830FF CALL 0C6F ; call write_to_port(00, 022c) 0B43:0D3F 32C0 XOR AL,AL 0B43:0D41 E82BFF CALL 0C6F ; call write_to_port(00, 022c) 0B43:0D44 32C0 XOR AL,AL 0B43:0D46 E826FF CALL 0C6F ; clear ax,cx 0B43:0D49 33C0 XOR AX,AX 0B43:0D4B 31C9 XOR CX,CX ; loop 64k times or until we get the sb irq { ; halt (until we get an irq I guess?) 0B43:0D4D F4 HLT ; if irq 2/5/7 actually responded, jump to 0d5b 0B43:0D4E 2E CS: 0B43:0D4F 803EFF0700 CMP BYTE PTR [07FF],00 0B43:0D54 7505 JNZ 0D5B ; otherwise, loop back 0B43:0D56 E2F5 LOOP 0D4D } ; we get here if one of our dummy irq’s responded 0B43:0D58 B80300 MOV AX,0003 ; store ax 0B43:0D5B 50 PUSH AX ; call restore_interrupt(02, 0a2d) 0B43:0D5C B002 MOV AL,02 0B43:0D5E BBE307 MOV BX,0A2D 0B43:0D61 E8D700 CALL 0E3B ; call restore_interrupt(02, 0a31) 0B43:0D64 B005 MOV AL,05 0B43:0D66 BBE707 MOV BX,0A31 0B43:0D69 E8CF00 CALL 0E3B ; call restore_interrupt(02, 0a35) 0B43:0D6C B005 MOV AL,05 0B43:0D6E BBEB07 MOV BX,0A35 0B43:0D71 E8C700 CALL 0E3B ; call restore_interrupt(02, 0a39) 0B43:0D74 B007 MOV AL,07 0B43:0D76 BBEF07 MOV BX,0A39 0B43:0D79 E8BF00 CALL 0E3B ; restore ax 0B43:0D7C 58 POP AX ; set flags and return 0B43:0D7D 0BC0 OR AX,AX 0B43:0D7F C3 RET } get_dsp_version() - 0d80 { ; get dsp version (cmd e1) ; returns ax = 0 on success, 1 on failure ; call write_to_port(e1, 0x22c) 0B43:0D80 B0E1 MOV AL,E1 0B43:0D82 2E CS: 0B43:0D83 8B16EF00 MOV DX,[00EF] 0B43:0D87 80C20C ADD DL,0C 0B43:0D8A E8E2FE CALL 0C6F ; read major version ; call 0c81 0B43:0D8D E8F1FE CALL 0C81 ; read minor version ; call 0c81 0B43:0D90 8AE0 MOV AH,AL 0B43:0D92 E8ECFE CALL 0C81 ; set bx = 1 (failure) 0B43:0D95 BB0100 MOV BX,0001 ; if version < 1.1, jump to 0d9f 0B43:0D98 3D0101 CMP AX,0101 0B43:0D9B 7202 JB 0D9F ; clear bx (success) 0B43:0D9D 33DB XOR BX,BX ; set ax = bx (return code) 0B43:0D9F 8BC3 MOV AX,BX ; set flags 0B43:0DA1 0BC0 OR AX,AX 0B43:0DA3 C3 RET } pause_dma_output() - 0da4 { ; pause dma output (cmd d0) ; call write_to_port(d0, 0x022c) 0B43:0DA4 2E CS: 0B43:0DA5 8B16EF00 MOV DX,[00EF] 0B43:0DA9 80C20C ADD DL,0C 0B43:0DAC B0D0 MOV AL,D0 0B43:0DAE E8BEFE CALL 0C6F ; loop until write status is clear { 0B43:0DB1 EC IN AL,DX 0B43:0DB2 0AC0 OR AL,AL 0B43:0DB4 78FB JS 0DB1 } ; return 0B43:0DB6 C3 RET } program_dma(cx,dh,dl,ax) – 0db7 { ; cx = word count ; dh = ? ; dl,ax = absolute address 0B43:0DB7 53 PUSH BX ; set bx = ax 0B43:0DB8 8BD8 MOV BX,AX ; write 05 to port 0x0a (single mask register), ; disables dma channel 1 0B43:0DBA B005 MOV AL,05 0B43:0DBC E60A OUT 0A,AL ; write 00 to port 0x0c (clear byte flip-flop) 0B43:0DBE 32C0 XOR AL,AL 0B43:0DC0 E60C OUT 0C,AL ; write dh to port 0x0b (mode: playback on dma 1) 0B43:0DC2 8AC6 MOV AL,DH 0B43:0DC4 E60B OUT 0B,AL ; write bl,bh to port 0x02 (dma 1 starting address) 0B43:0DC6 8AC3 MOV AL,BL 0B43:0DC8 E602 OUT 02,AL 0B43:0DCA 8AC7 MOV AL,BH 0B43:0DCC E602 OUT 02,AL ; write cl,ch to port 0x03 (dma 1 word count) 0B43:0DCE 8AC1 MOV AL,CL 0B43:0DD0 E603 OUT 03,AL 0B43:0DD2 8AC5 MOV AL,CH 0B43:0DD4 E603 OUT 03,AL ; write dl to port 0x83 (high-word starting address ?) 0B43:0DD6 8AC2 MOV AL,DL 0B43:0DD8 E683 OUT 83,AL ; write 01 to port 0x0a (single mask register), ; enables dma channel 1 0B43:0DDA B001 MOV AL,01 0B43:0DDC E60A OUT 0A,AL 0B43:0DDE 5B POP BX 0B43:0DDF C3 RET } compute_absolute_address(dx,ax) - 0de0 { ; dx = segment ; ax = offset ; returns absolute address in dx,ax 0B43:0DE0 51 PUSH CX ; left-rotate segment by 4 bits 0B43:0DE1 B104 MOV CL,04 0B43:0DE3 D3C2 ROL DX,CL ; set cx = dx 0B43:0DE5 8BCA MOV CX,DX ; get first 4 bits (formerly last 4) 0B43:0DE7 83E20F AND DX,+0F ; remove those 4 bits from cx 0B43:0DEA 83E1F0 AND CX,-10 ; ax += cx 0B43:0DED 03C1 ADD AX,CX ; dx += carry 0B43:0DEF 83D200 ADC DX,+00 0B43:0DF2 59 POP CX 0B43:0DF3 C3 RET } set_interrupt(al,bx,dx) - 0df4 { ; al = irq number ; bx = address of backup for old interrupt ; dx = address of function to call 0B43:0DF4 53 PUSH BX 0B43:0DF5 51 PUSH CX 0B43:0DF6 52 PUSH DX 0B43:0DF7 9C PUSHF ; clear interrupt flag 0B43:0DF8 FA CLI ; set cl = al (interrupt) 0B43:0DF9 8AC8 MOV CL,AL ; al += 8 0B43:0DFB 0408 ADD AL,08 0B43:0DFD 98 CBW 0B43:0DFE D0E0 SHL AL,1 0B43:0E00 D0E0 SHL AL,1 ; set di = ax 0B43:0E02 8BF8 MOV DI,AX ; store es 0B43:0E04 06 PUSH ES ; set ax,es to 0 ; (es now points to the interrupt vector table) 0B43:0E05 33C0 XOR AX,AX 0B43:0E07 8EC0 MOV ES,AX ; save old interrupt vector to cs:bx ; set *cs:bx = *0000:di 0B43:0E09 26 ES: 0B43:0E0A 8B05 MOV AX,[DI] 0B43:0E0C 2E CS: 0B43:0E0D 8907 MOV [BX],AX ; set *0000:di = dx 0B43:0E0F 26 ES: 0B43:0E10 8915 MOV [DI],DX ; set *cs:bx+2 = *0000:di+2 0B43:0E12 26 ES: 0B43:0E13 8B4502 MOV AX,[DI+02] 0B43:0E16 2E CS: 0B43:0E17 894702 MOV [BX+02],AX ; set *0000:di+2 = cs 0B43:0E1A 26 ES: 0B43:0E1B 8C4D02 MOV [DI+02],CS ; restore es 0B43:0E1E 07 POP ES ; set ah = 01 0B43:0E1F B401 MOV AH,01 ; shift by interrupt vector 0B43:0E21 D2E4 SHL AH,CL ; invert to mask 0B43:0E23 F6D4 NOT AH ; read from 0x21 0B43:0E25 E421 IN AL,21 0B43:0E27 53 PUSH BX 0B43:0E28 8AD9 MOV BL,CL 0B43:0E2A 32FF XOR BH,BH 0B43:0E2C 2E CS: 0B43:0E2D 88870B08 MOV [BX+080B],AL 0B43:0E31 5B POP BX 0B43:0E32 22C4 AND AL,AH 0B43:0E34 E621 OUT 21,AL 0B43:0E36 9D POPF 0B43:0E37 5A POP DX 0B43:0E38 59 POP CX 0B43:0E39 5B POP BX 0B43:0E3A C3 RET } restore_interrupt() – 0e3b { 0B43:0E3B 9C PUSHF 0B43:0E3C FA CLI 0B43:0E3D 8AC8 MOV CL,AL 0B43:0E3F 0408 ADD AL,08 0B43:0E41 98 CBW 0B43:0E42 D0E0 SHL AL,1 0B43:0E44 D0E0 SHL AL,1 0B43:0E46 8BF8 MOV DI,AX 0B43:0E48 06 PUSH ES 0B43:0E49 33C0 XOR AX,AX 0B43:0E4B 8EC0 MOV ES,AX 0B43:0E4D 2E CS: 0B43:0E4E 8B07 MOV AX,[BX] 0B43:0E50 26 ES: 0B43:0E51 8905 MOV [DI],AX 0B43:0E53 2E CS: 0B43:0E54 8B4702 MOV AX,[BX+02] 0B43:0E57 26 ES: 0B43:0E58 894502 MOV [DI+02],AX 0B43:0E5B 07 POP ES 0B43:0E5C B401 MOV AH,01 0B43:0E5E D2E4 SHL AH,CL 0B43:0E60 53 PUSH BX 0B43:0E61 8AD9 MOV BL,CL 0B43:0E63 32FF XOR BH,BH 0B43:0E65 2E CS: 0B43:0E66 8A870B08 MOV AL,[BX+080B] 0B43:0E6A 5B POP BX 0B43:0E6B E621 OUT 21,AL 0B43:0E6D 9D POPF 0B43:0E6E C3 RET } dummy_irq_2() - 0e6f { 0B43:0E6F 52 PUSH DX 0B43:0E70 50 PUSH AX 0B43:0E71 52 PUSH DX ; set ds = cs 0B43:0E72 8CC8 MOV AX,CS 0B43:0E74 8ED8 MOV DS,AX ; set dx = *cs:00ef (sb port 0x220) 0B43:0E76 2E CS: 0B43:0E77 8B16EF00 MOV DX,[00EF] ; port offset 0x0e 0B43:0E7B 83C20E ADD DX,+0E ; read from 0x22e 0B43:0E7E EC IN AL,DX ; set *07ff = 02 0B43:0E7F 2E CS: 0B43:0E80 C606FF0702 MOV BYTE PTR [07FF],02 ; write 20 to port 20 ? 0B43:0E85 B020 MOV AL,20 0B43:0E87 E620 OUT 20,AL 0B43:0E89 5A POP DX 0B43:0E8A 58 POP AX 0B43:0E8B 5A POP DX 0B43:0E8C CF IRET } dummy_irq_5() - 0e8d { 0B43:0E8D 1E PUSH DS 0B43:0E8E 50 PUSH AX 0B43:0E8F 52 PUSH DX 0B43:0E90 8CC8 MOV AX,CS 0B43:0E92 8ED8 MOV DS,AX 0B43:0E94 2E CS: 0B43:0E95 8B16EF00 MOV DX,[00EF] 0B43:0E99 83C20E ADD DX,+0E 0B43:0E9C EC IN AL,DX 0B43:0E9D 2E CS: 0B43:0E9E C606FF0705 MOV BYTE PTR [07FF],05 0B43:0EA3 B020 MOV AL,20 0B43:0EA5 E620 OUT 20,AL 0B43:0EA7 5A POP DX 0B43:0EA8 58 POP AX 0B43:0EA9 5A POP DX 0B43:0EAA CF IRET } dummy_irq_5() – 0eab { 0B43:0EAB 1E PUSH DS 0B43:0EAC 50 PUSH AX 0B43:0EAD 52 PUSH DX 0B43:0EAE 8CC8 MOV AX,CS 0B43:0EB0 8ED8 MOV DS,AX 0B43:0EB2 2E CS: 0B43:0EB3 8B16EF00 MOV DX,[00EF] 0B43:0EB7 83C20E ADD DX,+0E 0B43:0EBA EC IN AL,DX 0B43:0EBB 2E CS: 0B43:0EBC C606FF0705 MOV BYTE PTR [07FF],05 0B43:0EC1 B020 MOV AL,20 0B43:0EC3 E620 OUT 20,AL 0B43:0EC5 5A POP DX 0B43:0EC6 58 POP AX 0B43:0EC7 5A POP DX 0B43:0EC8 CF IRET } dummy_irq_7() – 0ec9 { 0B43:0EC9 1E PUSH DS 0B43:0ECA 50 PUSH AX 0B43:0ECB 52 PUSH DX 0B43:0ECC 8CC8 MOV AX,CS 0B43:0ECE 8ED8 MOV DS,AX 0B43:0ED0 2E CS: 0B43:0ED1 8B16EF00 MOV DX,[00EF] 0B43:0ED5 83C20E ADD DX,+0E 0B43:0ED8 EC IN AL,DX 0B43:0ED9 2E CS: 0B43:0EDA C606FF0707 MOV BYTE PTR [07FF],07 0B43:0EDF B020 MOV AL,20 0B43:0EE1 E620 OUT 20,AL 0B43:0EE3 5A POP DX 0B43:0EE4 58 POP AX 0B43:0EE5 5A POP DX 0B43:0EE6 CF IRET } sb_irq_handler() – 0ee7 { 0B43:0EE7 1E PUSH DS 0B43:0EE8 06 PUSH ES 0B43:0EE9 50 PUSH AX 0B43:0EEA 53 PUSH BX 0B43:0EEB 51 PUSH CX 0B43:0EEC 52 PUSH DX 0B43:0EED 57 PUSH DI 0B43:0EEE 56 PUSH SI 0B43:0EEF 55 PUSH BP 0B43:0EF0 9C PUSHF ; clear interrupt & d flags 0B43:0EF1 FA CLI 0B43:0EF2 FC CLD ; set es = ds = cx 0B43:0EF3 8CC8 MOV AX,CS 0B43:0EF5 8ED8 MOV DS,AX 0B43:0EF7 8EC0 MOV ES,AX ; write 0x20 to port 0x20 0B43:0EF9 B020 MOV AL,20 0B43:0EFB E620 OUT 20,AL ; if *cs:07d0 != 02, return 0B43:0EFD 2E CS: 0B43:0EFE 803ED00702 CMP BYTE PTR [07D0],02 0B43:0F03 7519 JNZ 0F1E ; set ax = *cs:07f9 0B43:0F05 2E CS: 0B43:0F06 A1F907 MOV AX,[07F9] ; if ax != 0, jump to 0f12 0B43:0F09 0BC0 OR AX,AX 0B43:0F0B 7505 JNZ 0F12 ; call 0f9e 0B43:0F0D E88E00 CALL 0F9E ; jump to 0f15 0B43:0F10 EB03 JMP 0F15 ; call dma_output() 0B43:0F12 E81400 CALL 0F29 ; read (and return) byte from 0x22e (interrupt ack) 0B43:0F15 2E CS: 0B43:0F16 8B16EF00 MOV DX,[00EF] 0B43:0F1A 80C20E ADD DL,0E 0B43:0F1D EC IN AL,DX ; return 0B43:0F1E 9D POPF 0B43:0F1F 5D POP BP 0B43:0F20 5E POP SI 0B43:0F21 5F POP DI 0B43:0F22 5A POP DX 0B43:0F23 59 POP CX 0B43:0F24 5B POP BX 0B43:0F25 58 POP AX 0B43:0F26 07 POP ES 0B43:0F27 1F POP DS 0B43:0F28 CF IRET } dma_output() - 0f29 { ; set cx = ffff 0B43:0F29 B9FFFF MOV CX,FFFF ; if *07f8 != 0, jump to 0f3e 0B43:0F2C 2E CS: 0B43:0F2D 803EF80700 CMP BYTE PTR [07F8],00 0B43:0F32 750A JNZ 0F3E ; *07f8++ 0B43:0F34 2E CS: 0B43:0F35 FE06F807 INC BYTE PTR [07F8] 0B43:0F39 2E CS: 0B43:0F3A 8B0EFD07 MOV CX,[07FD] ; cx -= *07f4 0B43:0F3E 2E CS: 0B43:0F3F 2B0EF407 SUB CX,[07F4] ; set *07f6 = cx 0B43:0F43 2E CS: 0B43:0F44 890EF607 MOV [07F6],CX ; cx++ 0B43:0F48 41 INC CX 0B43:0F49 740D JZ 0F58 0B43:0F4B 2E CS: 0B43:0F4C 290EF907 SUB [07F9],CX 0B43:0F50 2E CS: 0B43:0F51 831EFB0700 SBB WORD PTR [07FB],+00 0B43:0F56 EB05 JMP 0F5D 0B43:0F58 2E CS: 0B43:0F59 FF0EFB07 DEC WORD PTR [07FB] 0B43:0F5D B649 MOV DH,49 0B43:0F5F 2E CS: 0B43:0F60 8A16F307 MOV DL,[07F3] 0B43:0F64 2E CS: 0B43:0F65 A1F407 MOV AX,[07F4] 0B43:0F68 2E CS: 0B43:0F69 8B0EF607 MOV CX,[07F6] ; call 0db7 0B43:0F6D E847FE CALL 0DB7 0B43:0F70 2E CS: 0B43:0F71 FE0EF807 DEC BYTE PTR [07F8] 0B43:0F75 2E CS: 0B43:0F76 FE06F307 INC BYTE PTR [07F3] 0B43:0F7A 2E CS: 0B43:0F7B C706F4070000 MOV WORD PTR [07F4],0000 ; set cx = cs:*07f6 (size of audio data) 0B43:0F81 2E CS: 0B43:0F82 8B0EF607 MOV CX,[07F6] ; set dx = 022c 0B43:0F86 2E CS: 0B43:0F87 8B16EF00 MOV DX,[00EF] 0B43:0F8B 80C20C ADD DL,0C ; dma output (cmd 14) ; call write_to_port(14, 022c) 0B43:0F8E B014 MOV AL,14 0B43:0F90 E8DCFC CALL 0C6F ; send length (lo-byte) ; call write to port(cl, 022c) 0B43:0F93 8AC1 MOV AL,CL 0B43:0F95 E8D7FC CALL 0C6F ; send length (hi-byte) ; call write_to_port(ch, 022c) 0B43:0F98 8AC5 MOV AL,CH 0B43:0F9A E8D2FC CALL 0C6F ; when do we send the actual data ??? ; return 0B43:0F9D C3 RET } 0f9e { ; if *07d2 != 0, jump to 1016 0B43:0F9E 2E CS: 0B43:0F9F 803ED20700 CMP BYTE PTR [07D2],00 0B43:0FA4 7402 JZ 0FA8 0B43:0FA6 EB6E JMP 1016 ; if *07d1 != 0, jump to 0feb 0B43:0FA8 2E CS: 0B43:0FA9 803ED10700 CMP BYTE PTR [07D1],00 0B43:0FAE 753B JNZ 0FEB ; if *07dd == 0, jump to 1016 0B43:0FB0 2E CS: 0B43:0FB1 833EDD0700 CMP WORD PTR [07DD],+00 0B43:0FB6 7502 JNZ 0FBA 0B43:0FB8 EB5C JMP 1016 ; set *07d2 = 01 0B43:0FBA 2E CS: 0B43:0FBB C606D20701 MOV BYTE PTR [07D2],01 0B43:0FC0 1E PUSH DS 0B43:0FC1 50 PUSH AX 0B43:0FC2 53 PUSH BX ; set *0809 = *07dd 0B43:0FC3 2E CS: 0B43:0FC4 A1DD07 MOV AX,[07DD] 0B43:0FC7 2E CS: 0B43:0FC8 A30908 MOV [0809],AX ; set bx = 07d9 0B43:0FCB 2E CS: 0B43:0FCC C51ED907 LDS BX,[07D9] ; set *0805,*0807 = ds,bx 0B43:0FD0 2E CS: 0B43:0FD1 8C1E0508 MOV [0805],DS 0B43:0FD5 2E CS: 0B43:0FD6 891E0708 MOV [0807],BX ; set *0800 = 0000 0B43:0FDA 2E CS: 0B43:0FDB C70600080000 MOV WORD PTR [0800],0000 ; set *07d0 = 01 0B43:0FE1 2E CS: 0B43:0FE2 C606D00701 MOV BYTE PTR [07D0],01 0B43:0FE7 5B POP BX 0B43:0FE8 58 POP AX 0B43:0FE9 1F POP DS 0B43:0FEA C3 RET 0B43:0FEB 1E PUSH DS 0B43:0FEC 50 PUSH AX 0B43:0FED 53 PUSH BX 0B43:0FEE 2E CS: 0B43:0FEF A1D707 MOV AX,[07D7] 0B43:0FF2 2E CS: 0B43:0FF3 A30908 MOV [0809],AX 0B43:0FF6 2E CS: 0B43:0FF7 C51ED307 LDS BX,[07D3] 0B43:0FFB 2E CS: 0B43:0FFC 8C1E0508 MOV [0805],DS 0B43:1000 2E CS: 0B43:1001 891E0708 MOV [0807],BX 0B43:1005 2E CS: 0B43:1006 C70600080000 MOV WORD PTR [0800],0000 0B43:100C 2E CS: 0B43:100D C606D00701 MOV BYTE PTR [07D0],01 0B43:1012 5B POP BX 0B43:1013 58 POP AX 0B43:1014 1F POP DS 0B43:1015 C3 RET 0B43:1016 B005 MOV AL,05 0B43:1018 E60A OUT 0A,AL ; call restore_interrupt(*07ff, 0a29) 0B43:101A 2E CS: 0B43:101B A0FF07 MOV AL,[07FF] 0B43:101E BBDF07 MOV BX,07DF 0B43:1021 E817FE CALL 0E3B 0B43:1024 2E CS: 0B43:1025 C70600080000 MOV WORD PTR [0800],0000 ; read byte from 0x022e (int ack & read status) 0B43:102B 2E CS: 0B43:102C 8B16EF00 MOV DX,[00EF] 0B43:1030 80C20E ADD DL,0E 0B43:1033 EC IN AL,DX 0B43:1034 C3 RET } init_sb() - 1035 { 0B43:1035 1E PUSH DS 0B43:1036 06 PUSH ES 0B43:1037 57 PUSH DI 0B43:1038 56 PUSH SI ; set es = ds = cs 0B43:1039 8CC8 MOV AX,CS 0B43:103B 8ED8 MOV DS,AX 0B43:103D 8EC0 MOV ES,AX ; call reset_dsp() 0B43:103F E855FC CALL 0C97 ; if failure, return 0B43:1042 7516 JNZ 105A ; call 0cc4 0B43:1044 E87DFC CALL 0CC4 ; if failure, return 0B43:1047 7511 JNZ 105A ; call get_dsp_version() 0B43:1049 E834FD CALL 0D80 ; if failure, return 0B43:104C 750C JNZ 105A ; call determine_sb_irq() 0B43:104E E89CFC CALL 0CED 0B43:1051 7507 JNZ 105A ; turn on speaker ; call toggle_speaker(01) 0B43:1053 B001 MOV AL,01 0B43:1055 E81B00 CALL 1073 ; clear ax (to indicate success) 0B43:1058 33C0 XOR AX,AX 0B43:105A 5E POP SI 0B43:105B 5F POP DI 0B43:105C 07 POP ES 0B43:105D 1F POP DS 0B43:105E C3 RET } toggle_speaker_wrapper(al) - 105f { ; al = zero to turn off speaker, ; non-zero to turn on speaker 0B43:105F 1E PUSH DS 0B43:1060 06 PUSH ES 0B43:1061 56 PUSH SI 0B43:1062 57 PUSH DI 0B43:1063 50 PUSH AX 0B43:1064 53 PUSH BX 0B43:1065 51 PUSH CX 0B43:1066 52 PUSH DX ; call toggle_speaker(al) 0B43:1067 E80900 CALL 1073 0B43:106A 5A POP DX 0B43:106B 59 POP CX 0B43:106C 5B POP BX 0B43:106D 58 POP AX 0B43:106E 5F POP DI 0B43:106F 5E POP SI 0B43:1070 07 POP ES 0B43:1071 1F POP DS 0B43:1072 C3 RET } toggle_speaker(al) - 1073 { ; al = zero to turn off speaker, ; non-zero to turn on speaker ; set dx = 0x022c 0B43:1073 2E CS: 0B43:1074 8B16EF00 MOV DX,[00EF] 0B43:1078 83C20C ADD DX,+0C ; set ah = d1 (turn on speaker cmd) 0B43:107B B4D1 MOV AH,D1 ; if al != 0, jump to 1083 0B43:107D 0AC0 OR AL,AL 0B43:107F 7502 JNZ 1083 ; set ah = d3 (turn off speaker cmd) 0B43:1081 B4D3 MOV AH,D3 ; set al = ah 0B43:1083 8AC4 MOV AL,AH ; call write_to_port(d3, 0x022c) 0B43:1085 E8E7FB CALL 0C6F ; clear ax 0B43:1088 33C0 XOR AX,AX 0B43:108A C3 RET } 108b { 0B43:108B 53 PUSH BX 0B43:108C 51 PUSH CX 0B43:108D 52 PUSH DX 0B43:108E 1E PUSH DS 0B43:108F 06 PUSH ES 0B43:1090 57 PUSH DI 0B43:1091 56 PUSH SI ; set es = ds = cs 0B43:1092 8CC8 MOV AX,CS 0B43:1094 8ED8 MOV DS,AX 0B43:1096 8EC0 MOV ES,AX ; if *0800 == 00, jump to 10a6 0B43:1098 2E CS: 0B43:1099 833E000800 CMP WORD PTR [0800],+00 0B43:109E 7406 JZ 10A6 ; set ax = 1 (failure) and return 0B43:10A0 B80100 MOV AX,0001 0B43:10A3 E98000 JMP 1126 ; set *0800 = 01 0B43:10A6 2E CS: 0B43:10A7 C70600080100 MOV WORD PTR [0800],0001 ; set dx = 022c 0B43:10AD 2E CS: 0B43:10AE 8B16EF00 MOV DX,[00EF] 0B43:10B2 80C20C ADD DL,0C ; set cl = *cs:0804 (timer constant) 0B43:10B5 2E CS: 0B43:10B6 8A0E0408 MOV CL,[0804] ; set dx = 022c 0B43:10BA 2E CS: 0B43:10BB 8B16EF00 MOV DX,[00EF] 0B43:10BF 80C20C ADD DL,0C ; set the timer constant ; call write_to_port(40, 0x022c) 0B43:10C2 B040 MOV AL,40 0B43:10C4 E8A8FB CALL 0C6F ; call write_to_port(cl, 0x022c) 0B43:10C7 8AC1 MOV AL,CL 0B43:10C9 E8A3FB CALL 0C6F ; 07ff is the sb irq ; call set_interrupt(*cs:07ff, 07df, 0b9d) 0B43:10CC 2E CS: 0B43:10CD A0FF07 MOV AL,[0A49] 0B43:10D0 BA9D0B MOV DX,0DE7 0B43:10D3 BBDF07 MOV BX,0A29 0B43:10D6 E81BFD CALL 0DF4 ; I think 0805,0807 is the address of the sample ; call compute_absolute_address(*0805, *0807,) 0B43:10D9 2E CS: 0B43:10DA 8B160508 MOV DX,[0805] 0B43:10DE 2E CS: 0B43:10DF A10708 MOV AX,[0807] 0B43:10E2 E8FBFC CALL 0DE0 0B43:10E5 2E CS: 0B43:10E6 8816F307 MOV [07F3],DL 0B43:10EA 2E CS: 0B43:10EB A3F407 MOV [07F4],AX 0B43:10EE 2E CS: 0B43:10EF 8B0E0908 MOV CX,[0809] 0B43:10F3 2E CS: 0B43:10F4 890EF907 MOV [07F9],CX 0B43:10F8 2E CS: 0B43:10F9 C706FB070000 MOV WORD PTR [07FB],0000 0B43:10FF 2E CS: 0B43:1100 03060908 ADD AX,[0809] 0B43:1104 80D200 ADC DL,00 0B43:1107 2D0100 SUB AX,0001 0B43:110A 80DA00 SBB DL,00 0B43:110D 2E CS: 0B43:110E A3FD07 MOV [07FD],AX 0B43:1111 2E CS: 0B43:1112 2A16F307 SUB DL,[07F3] 0B43:1116 2E CS: 0B43:1117 8816F807 MOV [07F8],DL ; call dma_output() 0B43:111B E80BFE CALL 0F29 ; set *cs:07d0 = 02 (sample played ???) 0B43:111E 2E CS: 0B43:111F C606D00702 MOV BYTE PTR [07D0],02 ; clear ax 0B43:1124 33C0 XOR AX,AX 0B43:1126 5E POP SI 0B43:1127 5F POP DI 0B43:1128 07 POP ES 0B43:1129 1F POP DS 0B43:112A 5A POP DX 0B43:112B 59 POP CX 0B43:112C 5B POP BX 0B43:112D C3 RET } 112e { 0B43:112E 50 PUSH AX 0B43:112F 53 PUSH BX 0B43:1130 51 PUSH CX 0B43:1131 52 PUSH DX 0B43:1132 1E PUSH DS 0B43:1133 06 PUSH ES 0B43:1134 57 PUSH DI 0B43:1135 56 PUSH SI 0B43:1136 8CC8 MOV AX,CS 0B43:1138 8ED8 MOV DS,AX 0B43:113A 8EC0 MOV ES,AX 0B43:113C B80100 MOV AX,0001 0B43:113F 2E CS: 0B43:1140 833E000800 CMP WORD PTR [0800],+00 0B43:1145 740E JZ 1155 ; call pause_dma_output() 0B43:1147 E85AFC CALL 0DA4 ; call 0f9e 0B43:114A E851FE CALL 0F9E 0B43:114D 2E CS: 0B43:114E C606D00700 MOV BYTE PTR [07D0],00 0B43:1153 33C0 XOR AX,AX 0B43:1155 5E POP SI 0B43:1156 5F POP DI 0B43:1157 07 POP ES 0B43:1158 1F POP DS 0B43:1159 5A POP DX 0B43:115A 59 POP CX 0B43:115B 5B POP BX 0B43:115C 58 POP AX 0B43:115D C3 RET } 0B43:115E 1E PUSH DS 0B43:115F 06 PUSH ES 0B43:1160 57 PUSH DI 0B43:1161 56 PUSH SI 0B43:1162 8CC8 MOV AX,CS 0B43:1164 8ED8 MOV DS,AX 0B43:1166 8EC0 MOV ES,AX 0B43:1168 B80100 MOV AX,0001 0B43:116B 2E CS: 0B43:116C 833E000801 CMP WORD PTR [0800],+01 0B43:1171 750B JNZ 117E 0B43:1173 E82EFC CALL 0DA4 0B43:1176 2E CS: 0B43:1177 C606D00704 MOV BYTE PTR [07D0],04 0B43:117C 33C0 XOR AX,AX 0B43:117E 5E POP SI 0B43:117F 5F POP DI 0B43:1180 07 POP ES 0B43:1181 1F POP DS 0B43:1182 C3 RET 0B43:1183 1E PUSH DS 0B43:1184 06 PUSH ES 0B43:1185 57 PUSH DI 0B43:1186 56 PUSH SI 0B43:1187 8CC8 MOV AX,CS 0B43:1189 8ED8 MOV DS,AX 0B43:118B 8EC0 MOV ES,AX 0B43:118D B80100 MOV AX,0001 0B43:1190 2E CS: 0B43:1191 833E000801 CMP WORD PTR [0800],+01 0B43:1196 7515 JNZ 11AD 0B43:1198 2E CS: 0B43:1199 8B16EF00 MOV DX,[00EF] 0B43:119D 80C20C ADD DL,0C 0B43:11A0 B0D4 MOV AL,D4 0B43:11A2 E8CAFA CALL 0C6F 0B43:11A5 2E CS: 0B43:11A6 C606D00702 MOV BYTE PTR [07D0],02 0B43:11AB 33C0 XOR AX,AX 0B43:11AD 5E POP SI 0B43:11AE 5F POP DI 0B43:11AF 07 POP ES 0B43:11B0 1F POP DS 0B43:11B1 C3 RET ; port cs:10b2 = 220 0B43:11B2 2002 AND [BP+SI],AL my_init_device() – 11b4 { ; call init_device() 11b4 call 0a84 ; call init_sb() 11b7 call 1035 ; if return value success, jump to 11c4 11ba cmp ax,0000 11bd jz 11c4 ; otherwise, set ax = ffff and jump to 11c7 11bf mov ax,ffff 11c2 jmp 11c7 ; set ax = address of this function 11c4 mov ax,10b4 ; set cx = 0801 11c7 mov cx,0801 ; return 11ca ret } /* Work Log */ 1 Renamed GENMIDI.DRV to GMBLAST.DRV 2 Created and ran mkgmblast.c which copies the DSP-handling code from MTBLAST.DRV and appends it to GMBLAST.DRV 3 Created this document with MS-DOS debug. Debug loads the program to offset 0x0100, so the code segment is 0x0100 greater than it should be. Need to keep this in mind when synching addresses accessed by absolute address (in brackets) and those by relative address (as in jmp and call). 4 Changed offset 0x00EF to 0x010B2. This is the location to store the SB I/O port base address. (0x0220) 5 Changed offsets 0x015E and 0x0160 to 0x04C2 and 0x04C3, respectively, based on how they were used in MTBLAST and GENMIDI. No idea what these do! In the SB code, they are only used in load_sample(). 6 Manually updated all memory offsets accessed by absolute address (in brackets). The offsets are 0x024A greater in GMBLAST.DRV than they were in MTBLAST.DRV. 7 Manually updated memory offsets accessed via indirect mode (e.g. stored in a register). These lines are highlighted in dark red. 8 (Undocumented) Created some wrappers around load/stop/play sample which write to a logfile, “LOG”. This will be truncated in the final version and is not documented in the code above. 9 Found the interrupt handler code and corrected their memory offsets so the correct values go into the interrupt vector table. These lines are highlighted in light red. 10 Created my_init_device() at 0x10c7 (0x11c7 in debug) which initializes the sb for output according to MTBLAST. 11 Found another missed memory offset in determine_sb_irq(), highlighted in green. 12 Worked properly after logging code was removed. Apparently, it adversely affected the timing of the sound output. Status – working & complete