Microsoft (R) Macro Assembler Version 6.1a 09/22/94 16:09:36 wave_a.asm Page 1 - 1 ;*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ* ; SAMP_A.ASM 386 ; (c) Adeline 1993 ;*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ* ;*---------------------------------------------- ----------------------------* include wave.inc C ;*---------------------------------------------- C ----------------------------* C C ;DEBUG equ 1 C = 1234 C VOICE_HANDLE equ 1234h C C IFDEF SB16 C = 0001 C SBLASTER equ 1 C ; it is also a SBLASTER ! C C ENDIF C C IFDEF SBPRO C C SBLASTER equ 1 C ; it is also a SBLASTER ! C STEREO equ 1 C C ENDIF C C IFDEF SBLASTER1 C C SBLASTER equ 1 C ; it is also a SBLASTER ! C SINGLE_DMA equ 1 C ; use DMA (no auto-reinit on the SB ver C 1.00-1.99) C C ELSEIFDEF SBLASTER C = 0001 C AUTO_DMA equ 1 C ; use auto_reinit DMA (faster and cleane C r) C C ENDIF C C IFDEF MWSS C C SAMPLE16BIT equ 1 C STEREO equ 1 C AUTO_DMA equ 1 C ; use auto_reinit DMA (faster and cleane C r) C C ENDIF C C IFDEF GOLD C C SAMPLE16BIT equ 1 C STEREO equ 1 C SINGLE_DMA equ 1 C ; use DMA (no counter on the card) C C ENDIF C C IFDEF GUS C C AUTO_DMA equ 1 C ; use auto_reinit DMA (faster and cleane C r) C SAMPLE16BIT equ 1 C STEREO equ 1 C NOIRQ equ 1 C C ENDIF C C ;*---------------------------------------------- C ----------------------------* C C IFDEF SAMPLE16BIT C IFDEF STEREO = 0001 C SLONG equ 1 = 0004 C SSIZE equ 4 C ELSE C SUWORD equ 1 C SSIZE equ 2 C ENDIF C ELSE C IFDEF STEREO C SUWORD equ 1 C SSIZE equ 2 C ELSE C SCHAR equ 1 C SSIZE equ 1 C ENDIF C ENDIF C C ;*---------------------------------------------- C ----------------------------* C = 0400 C BUFFER_SIZE equ 1024 C ; number of samples C C ; in half-buffer = 0032 C LIST_SIZE equ 50 = 002C C STRUCT_SIZE equ 44 = 0008 C SNAP_SIZE equ 8 C = 0003 C SHIFT_SAMPLE equ 3 C ; max number of C C ; samples mixed C C ;*---------------------------------------------- C ----------------------------* C ;*---------------------------------------------- ----------------------------* MIDPOINT MACRO IFDEF SAMPLE16BIT xor eax, eax ELSE mov eax, 80808080h ENDIF ENDM ;*---------------------------------------------- ----------------------------* .386 jumps .model FLAT, SYSCALL 0000 .CODE ;*---------------------------------------------- ----------------------------* PUBLIC driver_start 0000 000000A0 R driver_start dd OFFSET ListFuncs IFDEF SB16 0004 53 6F 75 6E 64 20 db 'Sound Blaster 16 (DSP 4 42 6C 61 73 74 .XX)' 65 72 20 31 36 20 28 44 53 50 20 34 2E 58 58 29 ELSEIFDEF SBPRO db 'Sound Blaster Pro (DSP 3.XX)' ELSEIFDEF SBLASTER1 db 'Sound Blaster 2 (DSP 2. 01+)' ELSEIFDEF SBLASTER db 'Sound Blaster (DSP 1.00 -2.00)' ELSEIFDEF MWSS db 'Microsoft Windows Sound System (AD1848 SoundPort)' ELSEIFDEF GOLD db 'Adlib Gold (Yamaha GOLD )' ELSEIFDEF GUS db 'Advanced Gravis UltraSo und' ENDIF 001F 20 57 61 76 65 20 db ' Wave Driver,', 13, 10 44 72 69 76 65 72 2C 0D 0A IFDEF SAMPLE16BIT 002E 31 36 20 62 69 74 db '16 bit' ELSE db '8 bit' ENDIF IFDEF STEREO 0034 20 53 74 65 72 65 db ' Stereo' 6F ELSE db ' Mono' ENDIF IFDEF SURROUND db ' Surround' ENDIF 003B 20 70 6C 61 79 62 db ' playback, Version 1.00 61 63 6B 2C 20 .', 13, 10 56 65 72 73 69 6F 6E 20 31 2E 30 30 2E 0D 0A IFDEF GUS db 'Copyright (C) 1991,1992 Miles Design, Inc.', 0Dh, 0Ah db 'Copyright (C) 1993,1994 Advanced Gravis Computer ' db 'Technology Ltd. All rig hts reserved.', 0Dh, 0Ah db 'Copyright (C) 1992,1993 ,1994 Forte Technologies.', 0Dh, 0Ah db 'Copyright (C) 1994 Adel ine Software International.', 0Dh, 0Ah db 'All rights reserved.', 0Dh, 0Ah db 'UltraSound conversion b y Jayeson Lee-Steere.', 0Dh, 0Ah db 'Adeline Software conver sion by Serge Plagnol.', 0Dh, 0Ah db 'MIDI and Digital sound library by Forte.', 0Dh, 0Ah, 0Ah, 0 ELSE 0055 43 6F 70 79 72 69 db 'Copyright (c) Adeline S 67 68 74 20 28 oftware International 1994, All Rights Reserved. 63 29 20 41 64 ', 13, 10, 10, 0 65 6C 69 6E 65 20 53 6F 66 74 77 61 72 65 20 49 6E 74 65 72 6E 61 74 69 6F 6E 61 6C 20 31 39 39 34 2C 20 41 6C 6C 20 52 69 67 68 74 73 20 52 65 73 65 72 76 65 64 2E 0D 0A 0A 00 ENDIF 00A0 00002FED R ListFuncs dd offset InitCard 00A4 00003177 R dd offset ClearCard 00A8 000031F4 R dd offset AskVars 00AC 00002D21 R dd offset MixSample 00B0 00003213 R dd offset GiveSampleInfo0 00B4 00002A31 R dd offset StopSample 00B8 00002A91 R dd offset StopOneSample 00BC 00002C27 R dd offset SampleInList 00C0 00003268 R dd offset GetSnapSample 00C4 00002F07 R dd offset PauseSample 00C8 00002F5C R dd offset ContinueSample 00CC 00003307 R dd offset SaveStateSample 00D0 000033A1 R dd offset RestoreStateSamp le 00D4 000025F3 R dd offset GetDMAAddr 00D8 0000320D R dd offset GetBufferSize 00DC 00002CBE R dd offset ChangeVolume 00E0 00002B2D R dd offset ShiftSamples 00E4 00002BB9 R dd offset StopOneSampleLon g ;*---------------------------------------------- ----------------------------* = 0000 ADDRESS equ 0 = 0004 FRACT equ 4 = 0008 LEFT equ 8 = 000C C_REPEAT equ 12 = 000E INCR equ 14 = 0010 SON equ 16 = 0014 HANDLE equ 20 = 0018 START equ 24 = 001C DLENGTH equ 28 = 0020 VOL_LEFT equ 32 = 0022 VOL_RIGHT equ 34 = 0024 INFO0 equ 36 = 0028 INTERPOL equ 40 = 0029 LAST_SAMPLE equ 41 ;*---------------------------------------------- ----------------------------* = 0014 DSP_VO8S_CMD equ 14h = 001C DSP_VO8_CMD equ 1Ch = 0040 DSP_TIME_CMD equ 40h = 0041 DSP_RATE_CMD equ 41h = 0048 DSP_BSIZE_CMD equ 48h = 0090 DSP_VO8H_CMD equ 90h = 00B0 DSP_VO16S_CMD equ 0B0h = 00B6 DSP_VO16_CMD equ 0B6h = 00C0 DSP_VO8S_4_CMD equ 0C0h = 00C6 DSP_VO8_4_CMD equ 0C6h = 00D1 DSP_ONSPK_CMD equ 0D1h = 00D3 DSP_OFFSPK_CMD equ 0D3h = 0010 DSP_16MONO_MODE equ 10h = 0030 DSP_16STEREO_MODE equ 30h = 0000 DSP_8MONO_MODE equ 00h = 0020 DSP_8STEREO_MODE equ 20h = 00AA RESET_TEST_CODE equ 0AAh ;*---------------------------------------------- ----------------------------* ifndef NOIRQ = 0000 VOICE_OUT equ 0 ; equ to access the 2 arrays below = 0001 AUTO_OUT equ 1 = 0002 MASK1 equ 2 = 0003 MASK2 equ 3 = 0004 ADDX_REG equ 4 = 0006 COUNT_REG equ 6 = 0008 MASK_REG equ 8 = 000A MODE_REG equ 10 = 000C FF_REG equ 12 = 000E PAGE_REG equ 14 00E8 = 00E8 DMA0 equ $ ; Ports for DMA0 00E8 48 DMA0_VOICE_OUT db 48H 00E9 58 DMA0_AUTO_OUT db 58H 00EA 00 DMA0_MASK1 db 00H 00EB 04 DMA0_MASK2 db 04H 00EC 0000 DMA0_ADDX_REG dw 00H 00EE 0001 DMA0_COUNT_REG dw 01H 00F0 000A DMA0_MASK_REG dw 0AH 00F2 000B DMA0_MODE_REG dw 0BH 00F4 000C DMA0_FF_REG dw 0CH 00F6 0087 DMA0_PAGE_REG dw 87H 00F8 = 00F8 DMA1 equ $ ; Ports for DMA1 00F8 49 DMA1_VOICE_OUT db 49H 00F9 59 DMA1_AUTO_OUT db 59H 00FA 01 DMA1_MASK1 db 01H 00FB 05 DMA1_MASK2 db 05H 00FC 0002 DMA1_ADDX_REG dw 02H 00FE 0003 DMA1_COUNT_REG dw 03H 0100 000A DMA1_MASK_REG dw 0AH 0102 000B DMA1_MODE_REG dw 0BH 0104 000C DMA1_FF_REG dw 0CH 0106 0083 DMA1_PAGE_REG dw 83H 0108 = 0108 DMA3 equ $ ; Ports for DMA3 0108 4B DMA3_VOICE_OUT db 4BH 0109 5B DMA3_AUTO_OUT db 5BH 010A 03 DMA3_MASK1 db 03H 010B 07 DMA3_MASK2 db 07H 010C 0006 DMA3_ADDX_REG dw 06H 010E 0007 DMA3_COUNT_REG dw 07H 0110 000A DMA3_MASK_REG dw 0AH 0112 000B DMA3_MODE_REG dw 0BH 0114 000C DMA3_FF_REG dw 0CH 0116 0082 DMA3_PAGE_REG dw 82H 0118 = 0118 DMA5 equ $ ; Ports for DMA5 0118 49 DMA5_VOICE_OUT db 49H 0119 59 DMA5_AUTO_OUT db 59H 011A 01 DMA5_MASK1 db 01H 011B 05 DMA5_MASK2 db 05H 011C 00C4 DMA5_ADDX_REG dw 0C4H 011E 00C6 DMA5_COUNT_REG dw 0C6H 0120 00D4 DMA5_MASK_REG dw 0D4H 0122 00D6 DMA5_MODE_REG dw 0D6H 0124 00D8 DMA5_FF_REG dw 0D8H 0126 008B DMA5_PAGE_REG dw 08BH 0128 = 0128 DMA6 equ $ ; Ports for DMA6 0128 4A DMA6_VOICE_OUT db 4AH 0129 5A DMA6_AUTO_OUT db 5AH 012A 02 DMA6_MASK1 db 02H 012B 06 DMA6_MASK2 db 06H 012C 00C8 DMA6_ADDX_REG dw 0C8H 012E 00CA DMA6_COUNT_REG dw 0CAH 0130 00D4 DMA6_MASK_REG dw 0D4H 0132 00D6 DMA6_MODE_REG dw 0D6H 0134 00D8 DMA6_FF_REG dw 0D8H 0136 0089 DMA6_PAGE_REG dw 089H 0138 = 0138 DMA7 equ $ ; Ports for DMA7 0138 4B DMA7_VOICE_OUT db 4BH 0139 5B DMA7_AUTO_OUT db 5BH 013A 03 DMA7_MASK1 db 03H 013B 07 DMA7_MASK2 db 07H 013C 00CC DMA7_ADDX_REG dw 0CCH 013E 00CE DMA7_COUNT_REG dw 0CEH 0140 00D4 DMA7_MASK_REG dw 0D4H 0142 00D6 DMA7_MODE_REG dw 0D6H 0144 00D8 DMA7_FF_REG dw 0D8H 0146 008A DMA7_PAGE_REG dw 08AH ALIGN 4 0148 000000E8 R TAB_DMA dd offset DMA0 014C 000000F8 R dd offset DMA1 0150 00000000 dd 0 0154 00000108 R dd offset DMA3 0158 00000000 dd 0 015C 00000118 R dd offset DMA5 0160 00000128 R dd offset DMA6 0164 00000138 R dd offset DMA7 endif ;*---------------------------------------------- ----------------------------* 0168 0898 [ CurrentList db STRUCT_SIZE*LIST 00 _SIZE dup (?) ] 0A00 0898 [ SonList db STRUCT_SIZE*LIST 00 _SIZE dup (?) ] 1298 0898 [ BackCurrentList db STRUCT_SIZE*LIST 00 _SIZE dup (?) ] 1B30 0898 [ BackSonList db STRUCT_SIZE*LIST 00 _SIZE dup (?) ] 23C8 0190 [ SnapList db SNAP_SIZE*LIST_S 00 IZE dup (?) ] 2558 00 IRQ_mask db ? 2559 00 FlagPause db 0 255A 57 61 76 65 42 61 WaveBase db 'WaveBase',0 73 65 00 2563 57 61 76 65 49 52 WaveIRQ db 'WaveIRQ',0 51 00 256B 57 61 76 65 44 4D WaveDMA db 'WaveDMA',0 41 00 2573 57 61 76 65 52 61 WaveRate db 'WaveRate' 74 65 257B 00 Empty db 0 ifdef SBPRO OkIRQ db 0 Filter db ? endif ifdef GOLD Mixer_13 db ? Mixer_14 db ? Gold_IRQ db 3, 4, 5, 7, 10, 11, 12, 15 endif ifdef SB16 257C 02 05 07 0A SB16_IRQ db 2, 5, 7, 10 endif EVEN ifdef MWSS MWSSFreq dw 11025, 3, 16000, 2, 18900, 5, 22050, 7 dw 27429, 4, 32000, 6, 33075, 0dh, 37800, 9 dw 44100, 0Bh MWSSIrq db 0, 0, 010000b, 0 , 0, 0, 0, 001000b, 0, 010000b db 011000b, 100000b , 0, 0, 0, 0 MWSSDma db 01b, 10b, 0, 11b , 0, 0, 0, 0 endif 2580 0000 Critical dw ? 2582 0000 DoUpdate dw ? 2584 0000 Old_RIRQ_Seg dw ? 2586 0000 Old_PIRQ_Sel dw ? 2588 0000 Old_18_Sel dw ? 258A 0000 Old_RIRQ_Off dw ? ALIGN 4 258C 00000000 Old_PIRQ_Off dd ? 2590 00000000 Old_18_Off dd ? ifdef GOLD ListNames dd offset WaveBase dd offset Empty elseifdef SB16 2594 0000255A R ListNames dd offset WaveBase 2598 00002573 R dd offset WaveRate 259C 0000257B R dd offset Empty elseifdef GUS ListNames dd offset WaveRate dd offset Empty else ListNames dd offset WaveBase dd offset WaveRate dd offset WaveIRQ dd offset WaveDMA dd offset Empty endif public Nolanguage PlayRate 25A0 = 25A0 ListVars equ $ ifdef GOLD BASE_ADDR dd 388h ; By default 388h PlayRate dd 22000 ; By default 22 Khz IRQ_number dd ? ; no default (read card) DMA_number dd ? ; no default (read card) elseifdef SBLASTER 25A0 00000220 BASE_ADDR dd 220h ; By default 220h 25A4 000055F0 PlayRate dd 22000 ; By default 22 Khz 25A8 00000005 IRQ_number dd 5 ; By default 5 25AC 00000001 DMA_number dd 1 ; By default 1 elseifdef MWSS BASE_ADDR dd 540h ; By default 540h PlayRate dd 22000 ; By default 22 Khz IRQ_number dd 9 ; By default 9 DMA_number dd 1 ; By default 1 elseifdef GUS PlayRate dd 22000 ; By default 22 Khz else BASE_ADDR dd 0 ; no default PlayRate dd 22000 ; By default 22 Khz IRQ_number dd 0 ; no default DMA_number dd 0 ; no default endif 25B0 0000000D INT_number dd 0Dh ; By default 0Dh public Nolanguage BufferHalf 25B4 00000000 BufferHalf dd ? 25B8 FFFFFFFF follow dd -1 25BC FFFFFFFF backfollow dd -1 ifndef NOIRQ 25C0 000000F8 R DMA dd offset DMA1 ; By default DMA1 endif 25C4 00000000 weirdcount dd ? 25C8 00000000 backweirdcount dd ? 25CC 00000000 TheVolumeR dd ? 25D0 00000000 TheVolumeL dd ? 25D4 00000000 save_1 dd ? 25D8 00000000 save_2 dd ? 25DC 00000000 save_3 dd ? 25E0 00000000 save_4 dd ? public Nolanguage BUFFER_DMA public Nolanguage CURRENT_BUFFER ifdef RAM_CARD BUFFER_DMA dd ? ; adress of the buffer R_BUFFER_CARD dd ? ; adress of the buffer on the card for Right cha nnel MID_R_BUFFER_CARD dd ? ; adress of the mid buffer for Right channel CURRENT_R_BUFFER_CARD dd ? ; current half for Right channel L_BUFFER_CARD dd ? ; adress of the buffer on the card for Left chan nel MID_L_BUFFER_CARD dd ? ; adress of the mid buffer for Left channel CURRENT_L_BUFFER_CARD dd ? ; current half for Left channel else 25E4 00000000 BUFFER_DMA dd ? ; adress of the buffer 25E8 00000000 MID_BUFFER_DMA dd ? ; adress of the mid buffer 25EC 00000000 CURRENT_BUFFER dd ? ; current half endif ifdef INTERRRUPT DMA_COUNT dd ? DMA_PTR dd ? endif ;*---------------------------------------------- ----------------------------* 25F0 Redirector PROC 25F0 CD 18 int 18h 25F2 CF iretd 25F3 Redirector ENDP ;*---------------------------------------------- ----------------------------* setalc MACRO db 0D6h ENDM lve MACRO Reg, Exp lea Reg, [Exp] ENDM ;*---------------------------------------------- ----------------------------* GET_REAL_VECT MACRO mov ax, 0200h int 31h ENDM SET_REAL_VECT MACRO mov ax, 0201h int 31h ENDM GET_PROT_VECT MACRO mov ax, 0204h int 31h ENDM SET_PROT_VECT MACRO mov ax, 0205h int 31h ENDM CRIT_SECT MACRO ; Enter Critical Section ;-) mov word ptr[Critical], 1 ; tell the IRQ not to update the buffer ; we'll take care of it if nescessary O:-) ENDM END_CRIT_SECT MACRO ; Exit Critical Section O:-) local NoUpdate ; Update buffer if necessary ; Dealing with the critical sect ion flags................ ; DO NOT TOUCH !!!! mov word ptr[Critical], 0 ; exit crit. sect. ; this way DoUpdate can't change to 1 anymore cmp word ptr[DoUpdate], 0 ; IRQ happened ? je NoUpdate ; if DopUpdate change to 0 now, we are in deep ; shit anyway because we missed one round! ; The program won't crash but we'll ear the old ; content of half a buffer and also miss half a buffer ; of new data... :-( mov word ptr[Critical], 1 ; yes, crit. again, so we don't update twice ; because UpdateBuffer is not reentrant ; and we don't want to take a chance on crashing ! pushad ; if DoUpdate change to 1 HERE ; it means again that we missed one round! ; So we play the buffer we are updating! (funny noise :-( ) ; and then will ear half buffer of old data! call UpdateBuffer ; do the update popad mov word ptr[Critical], 0 ; exit crit. sect ; this way DoUpdate can't change to 1 anymore mov word ptr[DoUpdate], 0 ; Update done, so DoUpdate = 0 NoUpDate: ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! !! ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B UFFER ; TAKES MORE THAN 46000 microsec! ; (at 33 Mhz one cycle = .03 microsec so 4600 mi crosec = 1.5 million cycle) ENDM ;*---------------------------------------------- ----------------------------* 25F3 GetDMAAddr PROC USES EBX 25F3 53 * push ebx 25F4 33 C0 xor eax, eax ifndef NOIRQ 25F6 8B 1D 000025C0 R mov ebx, dword ptr[DMA] 25FC FA cli 25FD 66| 8B 53 0E mov dx, word ptr[ebx + PAGE_ REG] 2601 EC in al, dx 2602 C1 E0 10 shl eax, 16 2605 66| 8B 53 0C mov dx, word ptr[ebx + FF_RE G] 2609 EE out dx, al ; Flip-Flop 260A 66| 8B 53 04 mov dx, word ptr[ebx + ADDX_ REG] ; to get offset 260E EC in al, dx 260F 8A E0 mov ah, al 2611 EC in al, dx 2612 FB sti 2613 86 C4 xchg al, ah 2615 66| 83 3D 000025AC R cmp word ptr[DMA_number], 3 03 261D 76 07 jbe noadjust lve eax, eax*2 1 261F 8D 04 45 00000000 1 lea eax, [eax*2] 1 2626 noadjust: endif ret 2626 5B * pop ebx 2627 C3 * ret 00000h 2628 GetDMAAddr ENDP ;*---------------------------------------------- ----------------------------* ifndef NOIRQ 2628 NewIRQ PROC 2628 60 pushad 2629 1E push ds 262A 06 push es 262B FC cld ; DAMN IT !! :-o 262C = 262E local_DS equ $+2 262C 66| B8 1234 mov ax, 1234h 2630 66| 8E D8 mov ds, ax ; restore DS 2633 66| 8E C0 mov es, ax ; and ES !!! 2636 B0 20 mov al, 20h ; allows for new int 2638 80 3D 000025A8 R cmp byte ptr[IRQ_number], 7 07 263F 76 02 jbe short NoSecondCtrl 2641 E6 A0 out 0A0h, al 2643 E6 20 NoSecondCtrl: out 20h, al ifndef DEBUG 2645 E8 00000EBF call AckIrq 264A 72 4A jc short FinIRQ ; not a DMA IRQ ifdef SINGLE_DMA call BlockTransfert ; Normal ACK location endif endif 264C A1 000025B4 R mov eax, dword ptr[BufferHal f] 2651 34 04 xor al, 4 ; switch half 2653 A2 000025B4 R mov byte ptr[BufferHalf], al ifdef RAM_CARD mov eax, dword ptr[R_BUFFER_ CARD+eax]; get current card buffer address mov dword ptr[CURRENT_R_BUFF ER_CARD], eax; update CURRENT_BUFFER_CARD else 2658 8B 80 000025E4 R mov eax, dword ptr[BUFFER_DM A+eax] ; get current buffer address 265E A3 000025EC R mov dword ptr[CURRENT_BUFFER ], eax ; update CURRENT_BUFFER endif 2663 66| C7 05 00002582 R mov word ptr[DoUpdate], 1 0001 ; Time to do the update 266C 66| 83 3D 00002580 R cmp word ptr[Critical], 0 00 ; crit. sect ? 2674 75 20 jne FinIRQ ; yes, don't update yet! 2676 66| C7 05 00002580 R mov word ptr[Critical], 1 0001 ; just to make jure it case the interrup t 267F E8 00000016 call UpdateBuffer ; happen again before its finished 2684 66| C7 05 00002580 R mov word ptr[Critical], 0 0000 268D 66| C7 05 00002582 R mov word ptr[DoUpdate], 0 0000 ; Update done ifdef DEBUG call AckIrq jc short FinIRQ ; not a DMA IRQ ifdef SINGLE_DMA call BlockTransfert ; Normal ACK location endif endif 2696 FinIRQ: 2696 07 pop es 2697 1F pop ds 2698 61 popad 2699 CF iretd 269A NewIRQ ENDP endif ;*---------------------------------------------- ----------------------------* ifdef GUS PUBLIC Nolanguage UpdateBu ffer PUBLIC Nolanguage DoUpdate PUBLIC Nolanguage Critical endif ;*---------------------------------------------- ----------------------------* 269A UpdateBuffer PROC 269A B8 00000400 mov eax, BUFFER_SIZE ifdef RAM_CARD mov edi, dword ptr[BUFFER_DM A] ; Buffer else 269F 8B 3D 000025EC R mov edi, dword ptr[CURRENT_B UFFER] ; Buffer endif 26A5 80 3D 00002559 R cmp byte ptr[FlagPause], 1 01 26AC 74 10 je short dopause 26AE 8D 1D 00000168 R lea ebx, CurrentList ; Point to List of samples 26B4 8B 33 mov esi, dword ptr[ebx] ; Current Source 26B6 0B F6 or esi, esi ; if 0 then empty list 26B8 0F 85 0000008D jnz process_1st 26BE dopause: 26BE B9 00000400 mov ecx, (BUFFER_SIZE * SSIZ E) / 4 MIDPOINT 1 1 IFDEF SAMPLE16BIT 26C3 33 C0 1 xor eax, eax 1 ELSE 1 mov eax, 80808080h 1 ENDIF 1 26C5 F3/ AB rep stosd 26C7 EB 6C jmp endfade 26C9 exit: 26C9 A0 00002559 R mov al, byte ptr[FlagPause] 26CE FE C8 dec al 26D0 78 6F js reallyexit ifdef RAM_CARD mov edi, dword ptr[BUFFER_DM A] ; Buffer else 26D2 8B 3D 000025EC R mov edi, dword ptr[CURRENT_B UFFER] ; Buffer endif 26D8 BE 00000400 mov esi, ( BUFFER_SIZE * SSI ZE ) / 4 26DD 66| 0F BD CE bsr cx, si 26E1 66| 4E dec si ; no need to fade first/last sample ; since it will be multiplied by 1 26E3 FE C8 dec al 26E5 75 2A jnz short fadeout 26E7 BB 00000001 mov ebx, 1 ; skip 0 ifdef SAMPLE16BIT 26EC 8B 17 loopfadein: mov edx, dword ptr[edi] 26EE 0F BF C2 movsx eax, dx 26F1 0F AF C3 imul eax, ebx 26F4 D3 F8 sar eax, cl 26F6 C1 FA 10 sar edx, 16 26F9 0F AF D3 imul edx, ebx 26FC D3 FA sar edx, cl 26FE C1 E2 10 shl edx, 16 2701 66| 8B D0 mov dx, ax 2704 89 17 mov dword ptr[edi], edx 2706 83 C7 04 add edi, 4 2709 66| 43 inc bx 270B 66| 4E dec si 270D 75 DD jnz short loopfadein else loopfadein: mov edx, dword ptr[edi] xor edx, 80808080h ; convert to signed REPT 2 movsx eax, dl imul eax, ebx sar eax, cl mov dl, al movsx eax, dh imul eax, ebx sar eax, cl mov dh, al rol edx, 16 ENDM xor edx, 80808080h ; back to unsigned mov dword ptr[edi], edx add edi, 4 inc bx dec si jnz short loopfadein endif 270F EB 24 jmp short endfade 2711 fadeout: 2711 83 C7 04 add edi, 4 ; skip first ifdef SAMPLE16BIT 2714 8B 17 loopfadeout: mov edx, dword ptr[edi] 2716 0F BF C2 movsx eax, dx 2719 0F AF C6 imul eax, esi 271C D3 F8 sar eax, cl 271E C1 FA 10 sar edx, 16 2721 0F AF D6 imul edx, esi 2724 D3 FA sar edx, cl 2726 C1 E2 10 shl edx, 16 2729 66| 8B D0 mov dx, ax 272C 89 17 mov dword ptr[edi], edx 272E 83 C7 04 add edi, 4 2731 66| 4E dec si 2733 75 DF jnz short loopfadeout else loopfadeout: mov edx, dword ptr[edi] xor edx, 80808080h ; convert to signed REPT 2 movsx eax, dl imul eax, esi sar eax, cl mov dl, al movsx eax, dh imul eax, esi sar eax, cl mov dh, al rol edx, 16 ENDM xor edx, 80808080h ; back to unsigned mov dword ptr[edi], edx add edi, 4 dec si jnz short loopfadeout endif 2735 endfade: 2735 A0 00002559 R mov al, byte ptr[FlagPause] 273A 24 01 and al, 1 273C A2 00002559 R mov byte ptr[FlagPause], al 2741 reallyexit: 2741 C3 ret 2742 FinishFill0: 2742 66| 0B C0 or ax, ax ; still some room in the buffer? 2745 0F 84 000002CA jz Finish2 274B process_1st: 274B 66| 8B C8 mov cx, ax 274E C1 E0 10 shl eax, 16 2751 66| 8B C1 mov ax, cx ; eax = BUFFER_SIZE:BUFFER_SIZE 2754 66| 8B 53 04 mov dx, word ptr[ebx+FRACT] ; fractionnal Source 2758 66| 8B 6B 0E mov bp, word ptr[ebx+INCR] ; fractionnal inc 275C 8B 4B 08 mov ecx, dword ptr[ebx+LEFT] ; length left 275F 81 F9 0000FFFF cmp ecx, 0FFFFh ; length left to fill after sample 2765 77 05 ja Longer0 ; 64K or +, then more than the buffer 2767 66| 2B C1 sub ax, cx 276A 73 13 jae short NotLonger0 ; some left? 276C Longer0: 276C C1 E8 10 shr eax, 16 276F 8B C8 mov ecx, eax ; length = buffer_size 2771 29 4B 08 sub dword ptr[ebx+LEFT], ecx ; reduce length left 2774 66| C7 05 000025E0 R mov word ptr[save_4], 0 0000 ; no room left 277D EB 08 jmp short StartMix0 277F NotLonger0: 277F 66| 40 inc ax ; length + 1 (in case left = 0) 2781 66| A3 000025E0 R mov word ptr[save_4], ax 2787 StartMix0: 2787 C1 E2 10 shl edx, 16 278A 0B CA or ecx, edx ; hecx = FRACT 278C C1 E5 10 shl ebp, 16 ; hebp = INCR ifdef SAMPLE16BIT 278F 8B 53 20 mov edx, dword ptr[ebx+VOL_L EFT] ; read left & right volume ifdef STEREO 2792 80 7B 28 00 cmp byte ptr[ebx+INTERPOL], 0 2796 0F 84 00000090 je nofilter 279C 89 1D 000025DC R mov dword ptr[save_3], ebx 27A2 0F BF C2 movsx eax, dx 27A5 A3 000025D0 R mov [TheVolumeL], eax 27AA C1 FA 10 sar edx, 16 27AD 89 15 000025CC R mov [TheVolumeR], edx 27B3 C1 ED 10 shr ebp, 16 ; BP = fract inc 27B6 8B D1 mov edx, ecx 27B8 C1 EA 10 shr edx, 16 ; DX = fract 27BB C1 C1 08 rol ecx, 8 27BE 8A 4B 29 mov cl, [ebx+LAST_SAMPLE] 27C1 C1 C9 08 ror ecx, 8 27C4 EB 09 jmp short next0 27C6 C1 C1 08 start0: rol ecx, 8 27C9 8A 0E mov cl, [esi] 27CB 46 inc esi 27CC C1 C9 08 ror ecx, 8 27CF 8B C1 next0: mov eax, ecx 27D1 8A 06 mov al, [esi] ; read data 27D3 C1 C0 08 rol eax, 8 27D6 66| 35 8080 xor ax, 8080h ; 8 bit signed 27DA 0F BE D8 movsx ebx, al 27DD 0F BE C4 movsx eax, ah ; sign extension to 32 bit 27E0 66| F7 D2 not dx 27E3 42 inc edx 27E4 0F AF DA imul ebx, edx 27E7 4A dec edx 27E8 66| F7 D2 not dx 27EB 0F AF C2 imul eax, edx 27EE 03 D8 add ebx, eax 27F0 8B C3 mov eax, ebx 27F2 0F AF 1D 000025CC R imul ebx, [TheVolumeR] ; Right 27F9 0F AF 05 000025D0 R imul eax, [TheVolumeL] ; Left 2800 C1 F8 10 sar eax, 16 2803 66| 8B D8 mov bx, ax 2806 89 1F mov [edi], ebx ; store buffer content 2808 83 C7 04 add edi, 4 ; next location 280B 66| 03 D5 add dx, bp ; update fractional part of address 280E 66| 49 dec cx ; length-1, doesn't touch C but set Z ;- ) 2810 77 BD ja short next0 ; if (not C) and (not Z) next 2812 75 B2 jnz short start0 ; if some left, read a new one 2814 8B 1D 000025DC R mov ebx, dword ptr[save_3] 281A 66| 9C pushf 281C C1 C1 08 rol ecx, 8 281F 88 4B 29 mov [ebx+LAST_SAMPLE], cl 2822 C1 E2 10 shl edx, 16 2825 8B CA mov ecx, edx 2827 46 inc esi 2828 66| 9D popf 282A EB 2B jmp short end16 282C nofilter: 282C 89 1D 000025DC R mov dword ptr[save_3], ebx 2832 AC start01: lodsb ; read new data 2833 34 80 xor al, 80h ; 8 bit signed 2835 0F BE C0 movsx eax, al ; sign extension to 32 bit 2838 8B D8 mov ebx, eax ; copy into ebx 283A 66| 0F AF C2 imul ax, dx ; ax = left 283E 0F AF DA imul ebx, edx 2841 66| 8B D8 mov bx, ax 2844 89 1F next01: mov dword ptr[edi], ebx ; write data 2846 83 C7 04 add edi, 4 ; next location 2849 03 CD add ecx, ebp ; update fractional part of address 284B 66| 49 dec cx ; length-1, doesn't touch C but set Z ;- ) 284D 77 F5 ja short next01 ; if (not C) and (not Z) next 284F 75 E1 jnz short start01 ; if some left, read a new one 2851 8B 1D 000025DC R mov ebx, dword ptr[save_3] 2857 end16: else start0: lodsb ; read new data xor al, 80h ; 8 bit signed movsx ax, al ; sign extension to 16 bit imul ax, dx ; ax = "volumed" sample next0: mov word ptr[edi], ax ; write data add edi, 2 ; next location add ecx, ebp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short next0 ; if (not C) and (not Z) next jnz short start0 ; if some left, read a new one endif else ifdef STEREO mov dl, byte ptr[ebx+VOL_LEF T] or dl, dl jz short middle0 dec dl jz short left0 mov al, 80h ; "0" -> left r_start0: mov ah, byte ptr[esi] ; read new data -> right inc esi r_next0: mov word ptr[edi], ax ; write data add edi, 2 ; next location add ecx, ebp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short r_next0 ; if (not C) and (not Z) next jnz short r_start0 ; if some left, read a new one jmp short end0 left0: mov ah, 80h ; "0" -> right l_start0: lodsb ; read new data -> left l_next0: mov word ptr[edi], ax ; write data add edi, 2 ; next location add ecx, ebp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short l_next0 ; if (not C) and (not Z) next jnz short l_start0 ; if some left, read a new one jmp short end0 middle0: m_start0: lodsb ; read new data -> left mov ah, al ; data -> right m_next0: mov word ptr[edi], ax ; write data add edi, 2 ; next location add ecx, ebp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short m_next0 ; if (not C) and (not Z) next jnz short m_start0 ; if some left, read a new one end0: else start0: lodsb ; read new data next0: mov byte ptr[edi], al ; write data inc edi ; next location add ecx, ebp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short next0 ; if (not C) and (not Z) next jnz short start0 ; if some left, read a new one endif endif 2857 72 01 jc noadjust0 ; was a new data going to be read? 2859 4E dec esi ; no, last data will be read again 285A noadjust0: 285A 66| A1 000025E0 R mov ax, word ptr[save_4] ; left to copy 2860 66| 0B C0 or ax, ax 2863 0F 84 000001A3 jz Finish ; 0 normal end 2869 66| 48 dec ax ; readjust size 286B 66| FF 4B 0C dec word ptr[ebx+C_REPEAT] ; repeat again? 286F 75 74 jnz Reset0 ; yes, then reset 2871 8B 53 10 mov edx, dword ptr[ebx+SON] ; no, got a son? 2874 0B D2 or edx, edx 2876 78 15 js short NoSon0 ; no, remove the sample 2878 8D 35 00000A00 R lea esi, SonList ; yes, then find it 287E KeepLooking0: 287E 83 3E 00 cmp dword ptr[esi], 0 ; the end ? 2881 74 0A je short NoSon0 ; yes, then no son 2883 3B 56 14 cmp edx, dword ptr[esi+HANDL E] ; this one? 2886 74 2B je short FoundSon0 ; yes, found! 2888 83 C6 2C add esi, STRUCT_SIZE ; no, keep looking 288B EB F1 jmp short KeepLooking0 288D NoSon0: 288D 33 C9 xor ecx, ecx 288F 66| 8B C8 mov cx, ax ; clear rest of the buffer MIDPOINT 1 1 IFDEF SAMPLE16BIT 2892 33 C0 1 xor eax, eax 1 ELSE 1 mov eax, 80808080h 1 ENDIF 1 IFDEF SCHAR mov edx, ecx and ecx, 3 ; up to 3 by byte rep stosb mov ecx, edx shr ecx, 2 ; the rest by dword ELSEIFDEF SUWORD shr ecx, 1 jnc short NoAdjustByOne stosw NoAdjustByOne: ENDIF 2894 F3/ AB rep stosd 2896 8B F3 mov esi, ebx ; point where it is 2898 8B FB mov edi, ebx ; idem 289A 83 C6 2C add esi, STRUCT_SIZE ; source one further 289D 83 3E 00 LoopRemove0: cmp dword ptr[esi], 0 ; end ? 28A0 74 09 je short EndRemove0 ; yes, exit 28A2 B9 0000000B mov ecx, STRUCT_SIZE / 4 ; trasnfert one struct 28A7 F3/ A5 rep movsd ; transfer 28A9 EB F2 jmp short LoopRemove0 28AB EndRemove0: 28AB C7 07 00000000 mov dword ptr[edi], 0 ; write 0 to mark the end 28B1 EB 46 jmp NextSample 28B3 FoundSon0: 28B3 8B EE mov ebp, esi ; save esi 28B5 8B D7 mov edx, edi ; save edi 28B7 8B FB mov edi, ebx ; transfert at the location of the fathe r 28B9 B9 0000000B mov ecx, STRUCT_SIZE / 4 ; count in dword 28BE F3/ A5 rep movsd ; transfert 28C0 8B F5 mov esi, ebp ; remove son from SonList 28C2 8B FD mov edi, ebp ; so, point to it 28C4 83 C6 2C add esi, STRUCT_SIZE ; source one further 28C7 83 3E 00 LoopSon0: cmp dword ptr[esi], 0 28CA 74 09 je short EndSon0 28CC B9 0000000B mov ecx, STRUCT_SIZE / 4 28D1 F3/ A5 rep movsd ; transfer while not 0 28D3 EB F2 jmp short LoopSon0 28D5 EndSon0: 28D5 C7 07 00000000 mov dword ptr[edi], 0 ; write 0 to mark the end 28DB 8B FA mov edi, edx ; restore edi in the buffer 28DD 8B 73 18 mov esi, dword ptr[ebx+START ] ; restore source, no need to write it 28E0 E9 FFFFFE5D jmp FinishFill0 28E5 Reset0: 28E5 8B 73 18 mov esi, dword ptr[ebx+START ] ; restore source, no need to write it 28E8 8B 6B 1C mov ebp, dword ptr[ebx+DLENG TH] ; restore length 28EB 89 6B 08 mov dword ptr[ebx+LEFT], ebp 28EE 66| C7 43 04 0000 mov word ptr[ebx+FRACT], 0 28F4 E9 FFFFFE49 jmp FinishFill0 28F9 NextSample: 28F9 8B 33 mov esi, dword ptr[ebx] ; Current Source 28FB 0B F6 or esi, esi ; if 0 then end of the list 28FD 0F 84 FFFFFDC6 jz exit ifdef RAM_CARD mov edi, dword ptr[BUFFER_DM A] ; Buffer else 2903 8B 3D 000025EC R mov edi, dword ptr[CURRENT_B UFFER] ; Buffer endif 2909 66| B8 0400 mov ax, BUFFER_SIZE 290D FinishFill: 290D 66| 0B C0 or ax, ax ; still some room in the buffer? 2910 0F 84 000000FF jz Finish2 2916 66| 8B C8 mov cx, ax 2919 C1 E0 10 shl eax, 16 291C 66| 8B C1 mov ax, cx ; eax = BUFFER_SIZE:BUFFER_SIZE 291F 66| 8B 53 04 mov dx, word ptr[ebx+FRACT] ; fractionnal Source 2923 66| 8B 6B 0E mov bp, word ptr[ebx+INCR] ; fractionnal inc 2927 8B 4B 08 mov ecx, dword ptr[ebx+LEFT] ; length left 292A 81 F9 0000FFFF cmp ecx, 0FFFFh ; length left to fill after sample 2930 77 05 ja Longer ; 64K or +, then more than the buffer 2932 66| 2B C1 sub ax, cx 2935 73 13 jae short NotLonger ; some left? 2937 Longer: 2937 C1 E8 10 shr eax, 16 ; no, restore buffer_size in ax 293A 8B C8 mov ecx, eax ; length = buffer_size 293C 29 4B 08 sub dword ptr[ebx+LEFT], ecx ; reduce length left 293F 66| C7 05 000025E0 R mov word ptr[save_4], 0 0000 ; no room left 2948 EB 08 jmp short startMix00 294A NotLonger: 294A 66| 40 inc ax ; length + 1 (in case left = 0) 294C 66| A3 000025E0 R mov word ptr[save_4], ax 2952 StartMix00: 2952 C1 E2 10 shl edx, 16 2955 0B CA or ecx, edx ; hecx = FRACT 2957 C1 E5 10 shl ebp, 16 ; hebp = INCR ifdef SAMPLE16BIT 295A 8B 53 20 mov edx, dword ptr[ebx+VOL_L EFT] ifdef STEREO comment @ mov dword ptr[save_3], ebx movsx eax, dx mov [TheVolumeL], eax sar edx, 16 mov [TheVolumeR], edx shr ebp, 16 ; BP = fract inc mov edx, ecx shr edx, 16 ; DX = fract dec esi start00: inc esi next00: mov ax, [esi] ; read data xor ax, 8080h ; 8 bit signed movsx ebx, al movsx eax, ah ; sign extension to 32 bit not dx inc edx imul ebx, edx dec edx not dx imul eax, edx add ebx, eax mov eax, ebx imul ebx, [TheVolumeR] ; Right imul eax, [TheVolumeL] ; Left sar eax, 16 mov bx, ax add [edi], ebx ; add with buffer content (one bit might jump from right to left, but oh well...) add edi, 4 ; next location add dx, bp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short next00 ; if (not C) and (not Z) next jnz short start00 ; if some left, read a new one pushf shl edx, 16 mov ecx, edx inc esi popf mov ebx, dword ptr[save_3] @ 295D 89 1D 000025DC R mov dword ptr[save_3], ebx 2963 AC start00: lodsb ; read new data 2964 34 80 xor al, 80h ; 8 bit signed 2966 0F BE C0 movsx eax, al ; sign extension to 32 bit 2969 8B D8 mov ebx, eax ; copy into ebx 296B 66| 0F AF C2 imul ax, dx ; ax = left 296F 0F AF DA imul ebx, edx 2972 66| 8B D8 mov bx, ax 2975 01 1F next00: add dword ptr[edi], ebx ; add with buffer content (one bit might jump from right to left, but oh well...) 2977 83 C7 04 add edi, 4 ; next location 297A 03 CD add ecx, ebp ; update fractional part of address 297C 66| 49 dec cx ; length-1, doesn't touch C but set Z ;- ) 297E 77 F5 ja short next00 ; if (not C) and (not Z) next 2980 75 E1 jnz short start00 ; if some left, read a new one 2982 8B 1D 000025DC R mov ebx, dword ptr[save_3] else start00: lodsb ; read new data xor al, 80h ; 8 bit signed movsx ax, al ; sign extension to 16 bit imul ax, dx ; ax = "volumed" sample next00: add word ptr[edi], ax ; add with buffer content add edi, 2 ; next location add ecx, ebp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short next00 ; if (not C) and (not Z) next jnz short start00 ; if some left, read a new one endif else ifdef STEREO mov dl, byte ptr[ebx+VOL_LEF T] or dl, dl jz short middle00 dec dl jz short left00 inc edi ; go right r_start00: lodsb ; read new data mov ah, al ; save it in ah r_next00: add al, byte ptr[edi] ; add with buffer content rcr al, 1 ; average adc al, 0 mov byte ptr[edi], al ; write result back add edi, 2 ; next location mov al, ah ; restore data add ecx, ebp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short r_next00 ; if (not C) and (not Z) next jnz short r_start00 ; if some left, read a new one dec edi ; go back left jmp short end00 left00: l_start00: lodsb ; read new data mov ah, al ; save it in ah l_next00: add al, byte ptr[edi] ; add with buffer content rcr al, 1 ; average adc al, 0 mov byte ptr[edi], al ; write result back add edi, 2 ; next location mov al, ah ; restore data add ecx, ebp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short l_next00 ; if (not C) and (not Z) next jnz short l_start00 ; if some left, read a new one jmp short end00 middle00: m_start00: lodsb ; read new data m_next00: mov dx, word ptr[edi] ; read buffer, left & right add dl, al ; average with left rcr dl, 1 adc dl, 0 add dh, al ; average with right rcr dh, 1 adc dl, 0 mov word ptr[edi], dx ; write result back add edi, 2 ; next location add ecx, ebp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short m_next00 ; if (not C) and (not Z) next jnz short m_start00 ; if some left, read a new one end00: else start00: lodsb ; read new data mov ah, al ; save it in ah next00: add al, byte ptr[edi] ; add with buffer content rcr al, 1 ; average adc al, 0 mov byte ptr[edi], al ; write result back inc edi ; next location mov al, ah ; restore data add ecx, ebp ; update fractional part of address dec cx ; length-1, doesn't touch C but set Z ;- ) ja short next00 ; if (not C) and (not Z) next jnz short start00 ; if some left, read a new one endif endif 2988 72 01 jc noadjust ; was a new data going to be read? 298A 4E dec esi ; no, last data will be read again 298B noadjust: 298B 66| A1 000025E0 R mov ax, word ptr[save_4] ; left to copy 2991 66| 0B C0 or ax, ax 2994 74 76 jz short Finish ; 0 normal end 2996 66| 48 dec ax ; readjust size 2998 66| FF 4B 0C dec word ptr[ebx+C_REPEAT] ; repeat again? 299C 75 7F jnz short Reset ; yes, then reset 299E 8B 53 10 mov edx, dword ptr[ebx+SON] ; no, got a son? 29A1 0B D2 or edx, edx 29A3 78 15 js short NoSon ; no, remove the sample 29A5 8D 35 00000A00 R lea esi, SonList ; yes, then find it 29AB KeepLooking: 29AB 83 3E 00 cmp dword ptr[esi], 0 ; the end ? 29AE 74 0A je short NoSon ; yes, then no son 29B0 3B 56 14 cmp edx, dword ptr[esi+HANDL E] ; this one? 29B3 74 25 je short FoundSon ; yes, found! 29B5 83 C6 2C add esi, STRUCT_SIZE ; no, keep looking 29B8 EB F1 jmp short KeepLooking 29BA NoSon: ; remove it 29BA 8B F3 mov esi, ebx ; point where it is 29BC 8B FB mov edi, ebx ; idem 29BE 83 C6 2C add esi, STRUCT_SIZE ; source one further 29C1 83 3E 00 LoopRemove: cmp dword ptr[esi], 0 ; end ? 29C4 74 09 je short EndRemove ; yes, exit 29C6 B9 0000000B mov ecx, STRUCT_SIZE / 4 ; trasnfert one struct 29CB F3/ A5 rep movsd ; transfer 29CD EB F2 jmp short LoopRemove 29CF EndRemove: 29CF C7 07 00000000 mov dword ptr[edi], 0 ; write 0 to mark the end 29D5 E9 FFFFFF1F jmp NextSample 29DA FoundSon: 29DA 8B EE mov ebp, esi ; save esi 29DC 8B D7 mov edx, edi ; save edi 29DE 8B FB mov edi, ebx ; transfert at the location of the fathe r 29E0 B9 0000000B mov ecx, STRUCT_SIZE / 4 ; count in dword 29E5 F3/ A5 rep movsd ; transfert 29E7 8B F5 mov esi, ebp ; remove son from SonList 29E9 8B FD mov edi, ebp ; so, point to it 29EB 83 C6 2C add esi, STRUCT_SIZE ; source one further 29EE 83 3E 00 LoopSon: cmp dword ptr[esi], 0 29F1 74 09 je short EndSon 29F3 B9 0000000B mov ecx, STRUCT_SIZE / 4 29F8 F3/ A5 rep movsd ; transfer while not 0 29FA EB F2 jmp short LoopSon 29FC EndSon: 29FC C7 07 00000000 mov dword ptr[edi], 0 ; write 0 to mark the end 2A02 8B FA mov edi, edx ; restore edi in the buffer 2A04 8B 73 18 mov esi, dword ptr[ebx+START ] ; restore source, no need to write it 2A07 E9 FFFFFF01 jmp FinishFill 2A0C Finish: 2A0C 89 33 mov dword ptr[ebx], esi ; save current address 2A0E C1 E9 10 shr ecx, 16 2A11 66| 89 4B 04 mov word ptr[ebx+FRACT], cx ; save fractional part 2A15 83 C3 2C Finish2: add ebx, STRUCT_SIZE ; point to next sample 2A18 E9 FFFFFEDC jmp NextSample 2A1D Reset: 2A1D 8B 73 18 mov esi, dword ptr[ebx+START ] ; restore source, no need to write it 2A20 8B 6B 1C mov ebp, dword ptr[ebx+DLENG TH] ; restore length 2A23 89 6B 08 mov dword ptr[ebx+LEFT], ebp 2A26 66| C7 43 04 0000 mov word ptr[ebx+FRACT], 0 2A2C E9 FFFFFEDC jmp FinishFill 2A31 UpdateBuffer ENDP ;*---------------------------------------------- ----------------------------* 2A31 StopSample PROC CRIT_SECT 1 2A31 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 2A3A 33 C0 xor eax, eax 2A3C A3 00000168 R mov dword ptr[CurrentList], eax 2A41 A3 00000A00 R mov dword ptr[SonList], eax 2A46 A2 00002559 R mov byte ptr[FlagPause], al 2A4B 48 dec eax 2A4C A3 000025B8 R mov dword ptr[follow], eax ; -1 2A51 C7 05 000025C4 R mov dword ptr[weirdcount], 1 00010000 0000h END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 2A5B 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 2A64 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 2A6C 74 22 1 je ??0000 ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 2A6E 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 2A77 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 2A78 E8 FFFFFC1D 1 call UpdateBuffer 1 ; do the update 2A7D 61 1 popad 2A7E 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 2A87 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 2A90 1 ??0000: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) 2A90 C3 ret 2A91 StopSample ENDP ;*---------------------------------------------- ----------------------------* 2A91 StopOneSample PROC USES EBX ESI EDI,\ thehandle:DWORD 2A91 55 * push ebp 2A92 8B EC * mov ebp, esp 2A94 53 * push ebx 2A95 56 * push esi 2A96 57 * push edi 2A97 6A FF push -1 ; end of recursion 2A99 8B 45 08 mov eax, thehandle 2A9C 8D 15 00000168 R lea edx, CurrentList 2AA2 8B DA mov ebx, edx CRIT_SECT 1 2AA4 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 2AAD 83 3B 00 keeplooking: cmp dword ptr[ebx], 0 2AB0 74 0B je short exit 2AB2 66| 3B 43 14 cmp ax, word ptr[ebx+HANDLE] 2AB6 74 50 je short found 2AB8 83 C3 2C add ebx, STRUCT_SIZE 2ABB EB F0 jmp short keeplooking 2ABD exit: 2ABD 8D 1D 00000A00 R lea ebx, SonList 2AC3 3B D3 cmp edx, ebx 2AC5 8B D3 mov edx, ebx 2AC7 75 E4 jne short keeplooking 2AC9 58 pop eax ; get "son" 2ACA 0B C0 or eax, eax 2ACC 79 DF jns short keeplooking ; less than #2 billions samples ! END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 2ACE 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 2AD7 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 2ADF 74 22 1 je ??0001 ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 2AE1 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 2AEA 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 2AEB E8 FFFFFBAA 1 call UpdateBuffer 1 ; do the update 2AF0 61 1 popad 2AF1 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 2AFA 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 2B03 1 ??0001: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) ret 2B03 5F * pop edi 2B04 5E * pop esi 2B05 5B * pop ebx 2B06 C9 * leave 2B07 C3 * ret 00000h 2B08 found: 2B08 8B 4B 10 mov ecx, dword ptr[ebx+SON] 2B0B 0B C9 or ecx, ecx 2B0D 78 01 js short noson 2B0F 51 push ecx ; "son" to be removed 2B10 noson: 2B10 8B F3 mov esi, ebx 2B12 8B FB mov edi, ebx 2B14 83 C6 2C add esi, STRUCT_SIZE 2B17 83 3E 00 LoopRemove: cmp dword ptr[esi], 0 2B1A 74 09 je short EndRemove 2B1C B9 0000000B mov ecx, STRUCT_SIZE / 4 2B21 F3/ A5 rep movsd 2B23 EB F2 jmp short LoopRemove 2B25 EndRemove: 2B25 C7 07 00000000 mov dword ptr[edi], 0 2B2B EB 80 jmp short keeplooking 2B2D StopOneSample ENDP ;----------------------------------------------- ----------------------------- 2B2D ShiftSamples PROC USES ESI EDI EBX,\ DestAddr:DWORD, SrcAddr:DWORD, S izeByte:DWORD 2B2D 55 * push ebp 2B2E 8B EC * mov ebp, esp 2B30 56 * push esi 2B31 57 * push edi 2B32 53 * push ebx 2B33 8D 15 00000168 R lea edx, CurrentList 2B39 8B 75 0C mov esi, SrcAddr ; Source 2B3C 8B C6 mov eax, esi ; save Source for comparison 2B3E 8B 7D 08 mov edi, DestAddr ; Destination 2B41 8B 4D 10 mov ecx, SizeByte ; number of bytes to move 2B44 8A D9 mov bl, cl ; compute counters 2B46 C1 E9 02 shr ecx, 2 2B49 80 E3 03 and bl, 3 CRIT_SECT 1 2B4C 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 2B55 F3/ A5 rep movsd ; move the data 2B57 8A CB mov cl, bl 2B59 F3/ A4 rep movsb 2B5B 2B FE sub edi, esi ; shift (delta addr) 2B5D 8B DA mov ebx, edx 2B5F 83 3B 00 keeplooking: cmp dword ptr[ebx], 0 2B62 74 0F je short exit 2B64 3B 43 18 cmp eax, [ebx+START] 2B67 77 05 ja short notfound 2B69 01 7B 18 add [ebx+START], edi 2B6C 01 3B add [ebx], edi 2B6E notfound: 2B6E 83 C3 2C add ebx, STRUCT_SIZE 2B71 EB EC jmp short keeplooking 2B73 exit: 2B73 8D 1D 00000A00 R lea ebx, SonList 2B79 3B D3 cmp edx, ebx 2B7B 8B D3 mov edx, ebx 2B7D 75 E0 jne short keeplooking END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 2B7F 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 2B88 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 2B90 74 22 1 je ??0002 ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 2B92 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 2B9B 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 2B9C E8 FFFFFAF9 1 call UpdateBuffer 1 ; do the update 2BA1 61 1 popad 2BA2 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 2BAB 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 2BB4 1 ??0002: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) ret 2BB4 5B * pop ebx 2BB5 5F * pop edi 2BB6 5E * pop esi 2BB7 C9 * leave 2BB8 C3 * ret 00000h 2BB9 ShiftSamples ENDP ;----------------------------------------------- ----------------------------- 2BB9 StopOneSampleLong PROC USES ESI EDI,\ LongHandle:DWORD 2BB9 55 * push ebp 2BBA 8B EC * mov ebp, esp 2BBC 56 * push esi 2BBD 57 * push edi 2BBE 8B 45 08 mov eax, LongHandle CRIT_SECT 1 2BC1 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 2BCA E8 000000CB call SearchLongHandle 2BCF 0B D2 or edx, edx 2BD1 74 1B jz short notfound 2BD3 8B F2 mov esi, edx 2BD5 8B FA mov edi, edx 2BD7 83 C6 2C add esi, STRUCT_SIZE 2BDA 83 3E 00 LoopRemove: cmp dword ptr[esi], 0 2BDD 74 09 je short EndRemove 2BDF B9 0000000B mov ecx, STRUCT_SIZE / 4 2BE4 F3/ A5 rep movsd 2BE6 EB F2 jmp short LoopRemove 2BE8 EndRemove: 2BE8 C7 07 00000000 mov dword ptr[edi], 0 2BEE notfound: END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 2BEE 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 2BF7 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 2BFF 74 22 1 je ??0003 ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 2C01 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 2C0A 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 2C0B E8 FFFFFA8A 1 call UpdateBuffer 1 ; do the update 2C10 61 1 popad 2C11 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 2C1A 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 2C23 1 ??0003: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) ret 2C23 5F * pop edi 2C24 5E * pop esi 2C25 C9 * leave 2C26 C3 * ret 00000h 2C27 StopOneSampleLong ENDP ;*---------------------------------------------- ----------------------------* 2C27 SampleInList PROC USES EBX,\ thehandle:DWORD CRIT_SECT 1 2C27 55 * push ebp 2C28 8B EC * mov ebp, esp 2C2A 53 * push ebx 2C2B 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 2C34 8B 55 08 mov edx, thehandle 2C37 B8 00000001 mov eax, 1 ; True 2C3C 8D 0D 00000168 R lea ecx, CurrentList 2C42 8B D9 mov ebx, ecx 2C44 83 3B 00 keeplooking: cmp dword ptr[ebx], 0 2C47 74 0B je short exit 2C49 66| 3B 53 14 cmp dx, word ptr[ebx+HANDLE] 2C4D 74 13 je short found 2C4F 83 C3 2C add ebx, STRUCT_SIZE 2C52 EB F0 jmp short keeplooking 2C54 exit: 2C54 8D 1D 00000A00 R lea ebx, SonList 2C5A 3B CB cmp ecx, ebx 2C5C 8B CB mov ecx, ebx 2C5E 75 E4 jne keeplooking 2C60 33 C0 xor eax, eax ; False 2C62 found: END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 2C62 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 2C6B 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 2C73 74 22 1 je ??0004 ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 2C75 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 2C7E 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 2C7F E8 FFFFFA16 1 call UpdateBuffer 1 ; do the update 2C84 61 1 popad 2C85 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 2C8E 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 2C97 1 ??0004: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) ret 2C97 5B * pop ebx 2C98 C9 * leave 2C99 C3 * ret 00000h 2C9A SampleInList ENDP ;*---------------------------------------------- ----------------------------* 2C9A SearchLongHandle PROC 2C9A 8D 15 00000168 R lea edx, CurrentList 2CA0 8D 0D 00000A00 R lea ecx, SonList 2CA6 83 3A 00 keeplooking: cmp dword ptr[edx], 0 2CA9 74 0A je short exit 2CAB 3B 42 14 cmp eax, dword ptr[edx+HANDL E] 2CAE 74 0D je short found 2CB0 83 C2 2C add edx, STRUCT_SIZE 2CB3 EB F1 jmp short keeplooking 2CB5 exit: 2CB5 3B D1 cmp edx, ecx 2CB7 8B D1 mov edx, ecx 2CB9 75 EB jne keeplooking 2CBB 33 D2 xor edx, edx 2CBD found: 2CBD C3 ret 2CBE SearchLongHandle ENDP ;*---------------------------------------------- ----------------------------* 2CBE ChangeVolume PROC \ LongHandle:DWORD, volleft:DWORD, volright:DWORD ifdef STEREO ifdef SAMPLE16BIT 2CBE 55 * push ebp 2CBF 8B EC * mov ebp, esp 2CC1 8B 45 08 mov eax, LongHandle CRIT_SECT 1 2CC4 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 2CCD E8 FFFFFFC8 call SearchLongHandle 2CD2 0B D2 or edx, edx 2CD4 74 14 jz short notfound 2CD6 8B 45 0C mov eax, volleft 2CD9 C1 E8 02 shr eax, SHIFT_SAMPLE - 1 ; Preshift according to number of channe ls 2CDC 66| 89 42 20 mov word ptr[edx+VOL_LEFT], ax 2CE0 8B 45 10 mov eax, volright 2CE3 C1 E8 02 shr eax, SHIFT_SAMPLE - 1 ; Preshift according to number of channe ls ifdef SURROUND neg eax endif 2CE6 66| 89 42 22 mov word ptr[edx+VOL_RIGHT], ax 2CEA notfound: END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 2CEA 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 2CF3 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 2CFB 74 22 1 je ??0005 ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 2CFD 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 2D06 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 2D07 E8 FFFFF98E 1 call UpdateBuffer 1 ; do the update 2D0C 61 1 popad 2D0D 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 2D16 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 2D1F 1 ??0005: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) else mov eax, LongHandle CRIT_SECT call SearchLongHandle or edx, edx jz short notfound push edi mov edi, edx mov cx, word ptr[volleft] or cx, cx jnz short okleft mov cx, 2 ; if volleft = 0 then right jmp short storepos okleft: mov ax, word ptr[volright] shl ax, 7 ; * 128 xor dx, dx div cx mov cx, 2 ; right cmp ax, 222 ; 1.732 (= tan 60) * 128 jae short storepos dec cx ; left cmp ax, 74 ; .577 (= tan 30) * 128 jb short storepos dec cx ; middle storepos: mov word ptr[edi+VOL_LEFT], cx ; Store position (0:middle, 1:left, 2:ri ght) pop edi notfound: END_CRIT_SECT endif else ifdef SAMPLE16BIT mov eax, LongHandle CRIT_SECT call SearchLongHandle or edx, edx jz short notfound push edi push ebx mov edi, edx mov eax, volleft imul eax, eax mov ecx, volright imul ecx, ecx add eax, ecx call sqr2 shr eax, SHIFT_SAMPLE - 1 ; Preshift according to number of channe ls mov word ptr[edi+VOL_LEFT], ax ; VOL_LEFT = sqr(volleft^2 + volright^2) pop ebx pop esi notfound: END_CRIT_SECT endif endif ret 2D1F C9 * leave 2D20 C3 * ret 00000h 2D21 ChangeVolume ENDP ifdef SAMPLE16BIT ifndef STEREO ;*---------------------------------------------- ----------------------------* ; EAX = Sqr(EAX) Sqr2 PROC cmp eax, 3 ; if eax <= 3 then jbe short asqr_0_1 ; square root is 0 or 1 xor edx, edx ; clear edx mov ebx, eax ; copy eax into ebx so that ; edx:ebx are used "like" a 64 bit ; register bsr eax, ebx ; position of last 1 of ebx in eax mov cl, 33 ; compute how many left shift sub cl, al ; are needed in order to have the and cl, 11111110b ; most significant 2 bit pair at the ; leftmost position of edx shld edx, ebx, cl ; shift edx:ebx by the number shl ebx, cl ; computed above mov ecx, eax ; compute in ecx how many pairs of shr ecx, 1 ; 2 bit are left to be processed mov eax, 1 ; eax = 1 dec edx ; edx = edx - 1 asqr_loop: shld edx, ebx, 2 ; edx:ebx << 2 shl ebx, 2 ; lve eax, eax*2 ; eax * 2 cmp edx, eax ; compare edx and eax jb short asqr_neg ; if edx> 1 dec ecx ; one less pair to process jnz short asqr_loop ; if there is some left then go asqr_loop ret ; return to caller asqr_0_1: or eax, eax ; if eax = 0 jz short asqr_00 ; then return to caller mov eax, 1 ; else eax = 1 asqr_00: ret ; return to caller Sqr2 ENDP endif endif ;*---------------------------------------------- ----------------------------* 2D21 MixSample PROC USES ESI EDI EBX,\ thehandle:DWORD, pitchbend:DWORD , therepeat:DWORD,\ plug:DWORD, volleft:DWORD, volri ght:DWORD,\ buffer:DWORD; buffer with .VOC 2D21 55 * push ebp 2D22 8B EC * mov ebp, esp 2D24 56 * push esi 2D25 57 * push edi 2D26 53 * push ebx 2D27 8B 75 20 mov esi, buffer 2D2A 33 C0 xor eax, eax 2D2C 8A 06 mov al, [esi] 2D2E FE C0 inc al 2D30 3C 0A cmp al, 10 2D32 72 02 jb okfilter 2D34 33 C0 xor eax, eax 2D36 50 okfilter: push eax 2D37 0F B7 46 14 movzx eax, word ptr[esi+14h] 2D3B 03 F0 add esi, eax ; skip header 2D3D 80 3E 01 cmp byte ptr[esi], 1 ; only 1 bloc type allowed 2D40 0F 85 000001B9 jne typeunknown 2D46 80 7E 05 00 cmp byte ptr[esi + 5], 0 ; pack method 2D4A 0F 85 000001AF jne typeunknown ; This crap should be removed by using a file format containing the ; real sampling frequency instead of tha t stupid sr number in .VOC ! ; :-( 2D50 66| BA 000F mov dx, 0Fh 2D54 66| B8 4240 mov ax, 4240h ; dx:ax = 1000000 2D58 33 DB xor ebx, ebx 2D5A 8A 5E 04 mov bl, byte ptr[esi + 4] ; bl = sr 2D5D F6 DB neg bl ; bl = 256 - sr 2D5F 66| F7 F3 div bx 2D62 66| D1 E2 shl dx, 1 2D65 66| 83 D0 00 adc ax, 0 ; round to nearest 2D69 66| 8B D8 mov bx, ax ; ebx = real sampling rate ; up to here ! and then avoid this ^ div ! 2D6C 8B 46 01 mov eax, dword ptr[esi + 1] ; size sample 2D6F 25 00FFFFFF and eax, 0FFFFFFh ; 24 significant bits 2D74 83 E8 02 sub eax, 2 ; -2 header 2D77 83 C6 06 add esi, 6 ; esi->data 2D7A 89 35 000025D4 R mov dword ptr[save_1], esi ; save it 2D80 8B 55 0C mov edx, pitchbend 2D83 C1 E2 04 shl edx, 4 2D86 0F AF DA imul ebx, edx 2D89 C1 EB 10 shr ebx, 16 2D8C 66| 83 D3 00 adc bx, 0 ; ebx = scaled sampling rate 2D90 33 D2 xor edx, edx 2D92 93 xchg eax, ebx ; edx = 0, eax = sr, ebx = size 2D93 92 xchg edx, eax ; edx = sr, eax = 0, ebx = size 2D94 66| F7 35 000025A4 R div word ptr[PlayRate] ; dx:ax / PlayRate; ax = INCR 2D9B 3D 0000FFFF cmp eax, 0FFFFh 2DA0 76 05 jbe okincr 2DA2 B8 0000FFFF mov eax, 0FFFFh 2DA7 A3 000025D8 R okincr: mov dword ptr[save_2], eax ; save_2 = INCR 2DAC 8B CB mov ecx, ebx ; ecx = size 2DAE 8B F3 mov esi, ebx 2DB0 C1 EE 10 shr esi, 16 ; esi = hi(size) 2DB3 8B D6 mov edx, esi 2DB5 93 xchg eax, ebx ; eax = size, ebx = INCR 2DB6 48 dec eax ; A TRY !!!! (will make loop around next longer...) 2DB7 C1 E0 10 shl eax, 16 2DBA F7 F3 div ebx ; div 64 bits !!! 2DBC 2B C6 sub eax, esi ; sub max roundoff error 2DBE 8B F0 mov esi, eax ; esi = eax = new size 2DC0 F7 E3 mul ebx ; remultiply 2DC2 66| 8B D8 mov bx, ax ; FRACT in bx 2DC5 0F AC D0 10 shrd eax, edx, 16 ; size in eax 2DC9 66| 8B 15 000025D8 R mov dx, word ptr[save_2] ; INCR in dx 2DD0 2B C8 sub ecx, eax ; how much am I off? 2DD2 0F 86 00000127 jbe typeunknown ; security, should not happen! 2DD8 46 next: inc esi ; length + 1 2DD9 66| 03 DA add bx, dx ; update fractional part of address 2DDC 73 FA jnc short next ; if (not C) next 2DDE 66| 49 dec cx 2DE0 75 F6 jnz short next ; not right yet, loop 2DE2 A1 000025B8 R mov eax, dword ptr[follow] 2DE7 8D 1D 00000168 R lea ebx, CurrentList 2DED 8B FB mov edi, ebx 2DEF 66| 8B 4D 08 mov cx, word ptr[thehandle] IFNDEF SAMPLE_16BIT 2DF3 66| 81 F9 1234 cmp cx, VOICE_HANDLE 2DF8 75 0B jne ok_handle 2DFA 50 push eax 2DFB 51 push ecx 2DFC 52 push edx 2DFD E8 FFFFFC2F call StopSample 2E02 5A pop edx 2E03 59 pop ecx 2E04 58 pop eax 2E05 ok_handle: ENDIF 2E05 0B 0D 000025C4 R or ecx, dword ptr[weirdcoun t] ; why not ? 2E0B 66| FF 05 000025C6 R inc word ptr[weirdcount+2] CRIT_SECT 1 2E12 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 2E1B 83 7D 14 00 cmp plug, 0 2E1F 74 31 je NoPlug 2E21 8D 3D 00000A00 R lea edi, SonList 2E27 83 3B 00 keeplooking0: cmp dword ptr[ebx], 0 2E2A 74 0A je short SearchSonList 2E2C 3B 43 14 cmp eax, dword ptr[ebx+HANDL E] ; look for the "father" sample 2E2F 74 1E je short found 2E31 83 C3 2C add ebx, STRUCT_SIZE 2E34 EB F1 jmp short keeplooking0 2E36 SearchSonList: 2E36 8D 1D 00000A00 R lea ebx, SonList 2E3C 83 3B 00 keeplooking1: cmp dword ptr[ebx], 0 2E3F 74 0A je short Exit 2E41 3B 43 14 cmp eax, dword ptr[ebx+HANDL E] ; look for the "father" sample 2E44 74 09 je short found 2E46 83 C3 2C add ebx, STRUCT_SIZE 2E49 EB F1 jmp short keeplooking1 2E4B exit: 2E4B 33 C0 xor eax, eax 2E4D EB 76 jmp endcritical 2E4F found: 2E4F 89 4B 10 mov dword ptr[ebx+SON], ecx ; connect it to ist "son" 2E52 NoPlug: 2E52 33 C0 xor eax, eax 2E54 83 EF 2C sub edi, STRUCT_SIZE 2E57 83 C7 2C SearchEnd: add edi, STRUCT_SIZE 2E5A 3B 07 cmp eax, dword ptr[edi] 2E5C 75 F9 jne short SearchEnd 2E5E 89 0D 000025B8 R mov dword ptr[follow], ecx ; update follow 2E64 89 4F 14 mov dword ptr[edi+HANDLE], e cx ; sample handle 2E67 66| 8B 4D 10 mov cx, word ptr[therepeat] 2E6B 66| 89 4F 0C mov word ptr[edi+C_REPEAT], cx ; Repeat 2E6F 89 77 08 mov dword ptr[edi+LEFT], esi ; length 2E72 89 77 1C mov dword ptr[edi+DLENGTH], esi ; length 2E75 A1 000025D4 R mov eax, dword ptr[save_1] 2E7A 89 07 mov dword ptr[edi], eax ; Start 2E7C 89 47 18 mov dword ptr[edi+START], ea x ; Start 2E7F A1 000025D8 R mov eax, dword ptr[save_2] 2E84 66| 89 47 0E mov word ptr[edi+INCR], ax ; increment 2E88 C7 47 04 00010000 mov dword ptr[edi+FRACT], 10 000h ; fractional (with 1 above so != 0) 2E8F C7 47 10 FFFFFFFF mov dword ptr[edi+SON], -1 ; son 2E96 C7 47 24 FFFFFFFF mov dword ptr[edi+INFO0], -1 ; info0 2E9D 58 pop eax 2E9E 88 47 28 mov [edi+INTERPOL], al ; filter on/off 2EA1 C6 47 29 80 mov byte ptr[edi+LAST_SAMPLE ], 80h ; 80h ( 0 ) ifdef STEREO ifdef SAMPLE16BIT 2EA5 8B 45 18 mov eax, volleft 2EA8 C1 E8 02 shr eax, SHIFT_SAMPLE - 1 ; Preshift according to number of channe ls 2EAB 66| 89 47 20 mov word ptr[edi+VOL_LEFT], ax 2EAF 8B 45 1C mov eax, volright 2EB2 C1 E8 02 shr eax, SHIFT_SAMPLE - 1 ; Preshift according to number of channe ls ifdef SURROUND neg eax endif 2EB5 66| 89 47 22 mov word ptr[edi+VOL_RIGHT], ax else mov si, 2 ; right mov ecx, volleft or ecx, ecx jz short storepos okleft: mov eax, volright shl eax, 7 ; * 128 xor edx, edx div ecx cmp eax, 74 ; 1.732 (= tan 60) * 128 jb short storepos dec si ; left cmp eax, 222 ; .577 (= tan 30) * 128 jae short storepos dec si ; middle storepos: mov word ptr[edi+VOL_LEFT], si ; Store position (0:middle, 1:left, 2:ri ght) mov word ptr[edi+VOL_RIGHT], 1 ; to fill with non 0 endif else ifdef SAMPLE16BIT mov eax, volleft imul eax, eax mov ecx, volright imul ecx, ecx add eax, ecx call sqr2 shr eax, SHIFT_SAMPLE - 1 ; Preshift according to number of channe ls mov word ptr[edi+VOL_LEFT], ax ; VOL_LEFT = sqr(volleft^2 + volright^2) mov word ptr[edi+VOL_RIGHT], 1 ; to fill with non 0 else mov dword ptr[edi+VOL_LEFT], 1 ; to fill with non 0 endif endif 2EB9 C7 47 2C 00000000 mov dword ptr[edi+STRUCT_SIZ E], 0 ; mark end of List 2EC0 A1 000025B8 R mov eax, dword ptr[follow] 2EC5 endcritical: END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 2EC5 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 2ECE 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 2ED6 74 22 1 je ??0006 ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 2ED8 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 2EE1 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 2EE2 E8 FFFFF7B3 1 call UpdateBuffer 1 ; do the update 2EE7 61 1 popad 2EE8 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 2EF1 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 2EFA 1 ??0006: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) ret 2EFA 5B * pop ebx 2EFB 5F * pop edi 2EFC 5E * pop esi 2EFD C9 * leave 2EFE C3 * ret 00000h 2EFF typeunknown: 2EFF 58 pop eax 2F00 33 C0 xor eax, eax ret 2F02 5B * pop ebx 2F03 5F * pop edi 2F04 5E * pop esi 2F05 C9 * leave 2F06 C3 * ret 00000h 2F07 MixSample ENDP ;*---------------------------------------------- ----------------------------* ifdef SINGLE_DMA BlockTransfert PROC push ebx mov ecx, BUFFER_SIZE * SSIZE cmp word ptr[DMA_number], 3 jbe noLengthAdj shr ecx, 1 NoLengthAdj: dec ecx ; buffer size - 1 mov ebx, dword ptr[DMA] ; Point to DMAx mov dx, word ptr[ebx + MASK_ REG] mov al, byte ptr[ebx + MASK2 ] ; mask channel out dx, al mov dx, word ptr[ebx + FF_RE G] out dx, al ; flip-flop mov dx, word ptr[ebx + COUNT _REG] mov al, cl ; buffer size - 1 out dx, al mov al, ch out dx, al mov dx, word ptr[ebx + ADDX_ REG] mov eax, dword ptr[BufferHal f] mov eax, dword ptr[BUFFER_DM A+eax] ; start offset cmp word ptr[DMA_number], 3 jbe noAddrAdj shr eax, 1 NoAddrAdj: out dx, al shr eax, 8 out dx, al mov dx, word ptr[ebx + PAGE_ REG] shr eax, 8 ; page of DMA transfert out dx, al mov dx, word ptr[ebx + MODE_ REG] mov al, byte ptr[ebx + VOICE _OUT] ; output sample out dx, al mov dx, word ptr[ebx + MASK_ REG] mov al, byte ptr[ebx + MASK1 ] ; channel OK out dx, al pop ebx jmp StartDMACard BlockTransfert ENDP endif ;*---------------------------------------------- ----------------------------* 2F07 PauseSample PROC 2F07 33 C0 xor eax, eax CRIT_SECT 1 2F09 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 2F12 A0 00002559 R mov al, byte ptr[FlagPause] 2F17 FE C8 dec al 2F19 24 02 and al, 10b 2F1B 0C 01 or al, 01b ; 0->3, 1->1, 2->1, 3->3 2F1D A2 00002559 R mov byte ptr[FlagPause], al 2F22 D1 E8 shr eax, 1 2F24 34 01 xor al, 1 END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 2F26 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 2F2F 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 2F37 74 22 1 je ??0007 ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 2F39 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 2F42 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 2F43 E8 FFFFF752 1 call UpdateBuffer 1 ; do the update 2F48 61 1 popad 2F49 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 2F52 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 2F5B 1 ??0007: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) 2F5B C3 ret 2F5C PauseSample ENDP ;*---------------------------------------------- ----------------------------* 2F5C ContinueSample PROC 2F5C 33 C0 xor eax, eax CRIT_SECT 1 2F5E 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 2F67 A0 00002559 R mov al, byte ptr[FlagPause] 2F6C FE C0 inc al 2F6E 24 02 and al, 10b ; 0->0, 1->2, 2->2, 3->0 2F70 A2 00002559 R mov byte ptr[FlagPause], al 2F75 D1 E8 shr eax, 1 END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 2F77 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 2F80 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 2F88 74 22 1 je ??0008 ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 2F8A 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 2F93 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 2F94 E8 FFFFF701 1 call UpdateBuffer 1 ; do the update 2F99 61 1 popad 2F9A 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 2FA3 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 2FAC 1 ??0008: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) 2FAC C3 ret 2FAD ContinueSample ENDP ;----------------------------------------------- ----------------------------- ifndef NOIRQ 2FAD InstallISR PROC 2FAD 52 push edx 2FAE 8A 1D 000025B0 R mov bl, byte ptr[INT_number] ; plug ISR on user INT 2FB4 66| 8C C9 mov cx, cs SET_PROT_VECT 1 2FB7 66| B8 0205 1 mov ax, 0205h 2FBB CD 31 1 int 31h 1 2FBD 5A pop edx 2FBE 83 3D 000025A8 R cmp dword ptr[IRQ_number], 7 07 ; if IRQ > 7 2FC5 76 25 jbe nobi 2FC7 B3 18 mov bl, 18h ; plug as well on int 18h 2FC9 66| 8C C9 mov cx, cs SET_PROT_VECT 1 2FCC 66| B8 0205 1 mov ax, 0205h 2FD0 CD 31 1 int 31h 1 2FD2 8A 1D 000025B0 R mov bl, byte ptr[INT_number] ; plug into real usr INT 2FD8 B9 000025F0 R mov ecx, offset Redirector 2FDD 66| 8B D1 mov dx, cx ; compute real-mode 2FE0 66| 33 C9 xor cx, cx ; seg:ofs 2FE3 C1 E9 04 shr ecx, 4 SET_REAL_VECT 1 2FE6 66| B8 0201 1 mov ax, 0201h 2FEA CD 31 1 int 31h 1 2FEC nobi: 2FEC C3 ret 2FED InstallISR ENDP endif ;----------------------------------------------- ----------------------------- 2FED InitCard PROC USES EBX EDI ESI EBP,\ Buffer:DWORD ifndef NOIRQ 2FED 55 * push ebp 2FEE 8B EC * mov ebp, esp 2FF0 53 * push ebx 2FF1 57 * push edi 2FF2 56 * push esi 2FF3 55 * push ebp 2FF4 66| 8C 1D 0000262E R mov word ptr[local_DS], ds endif 2FFB 8B 45 08 mov eax, Buffer 2FFE A3 000025E4 R mov dword ptr[BUFFER_DMA], e ax ifndef SBPRO 3003 E8 0000042E call ResetCard endif ifndef NOIRQ 3008 33 C0 xor eax, eax 300A 66| A1 000025AC R mov ax, word ptr[DMA_number] 3010 66| 83 F8 07 cmp ax, 7 3014 77 0B ja short ErrorDMA 3016 8B 04 85 00000148 R mov eax, dword ptr[TAB_DMA+e ax*4] 301D 0B C0 or eax, eax 301F 75 08 jnz short DMAFound 3021 ErrorDMA: 3021 33 C0 xor eax, eax ret 3023 5D * pop ebp 3024 5E * pop esi 3025 5F * pop edi 3026 5B * pop ebx 3027 C9 * leave 3028 C3 * ret 00000h 3029 DMAFound: 3029 A3 000025C0 R mov dword ptr[DMA], eax 302E A1 000025A8 R mov eax, dword ptr[IRQ_numbe r] 3033 3C 07 cmp al, 7 3035 77 04 ja short Second 3037 04 08 add al, 8 3039 EB 02 jmp short gotvect 303B Second: 303B 04 68 add al, 70h - 8 303D gotvect: 303D A3 000025B0 R mov dword ptr[INT_number], e ax ; save user int 3042 8A D8 mov bl, al GET_PROT_VECT 1 3044 66| B8 0204 1 mov ax, 0204h 3048 CD 31 1 int 31h 1 304A 66| 89 0D 00002586 R mov word ptr[Old_PIRQ_Sel], cx 3051 89 15 0000258C R mov dword ptr[Old_PIRQ_Off], edx 3057 83 3D 000025A8 R cmp dword ptr[IRQ_number], 7 07 305E 76 2F jbe nobi 3060 8A 1D 000025B0 R mov bl, byte ptr[INT_number] ; if IRQ>7 save real vect GET_REAL_VECT 1 3066 66| B8 0200 1 mov ax, 0200h 306A CD 31 1 int 31h 1 306C 66| 89 0D 00002584 R mov word ptr[Old_RIRQ_Seg], cx 3073 66| 89 15 0000258A R mov word ptr[Old_RIRQ_Off], dx 307A B3 18 mov bl, 18h ; if IRQ>7 save int 18h GET_PROT_VECT 1 307C 66| B8 0204 1 mov ax, 0204h 3080 CD 31 1 int 31h 1 3082 66| 89 0D 00002588 R mov word ptr[Old_18_Sel], cx 3089 89 15 00002590 R mov dword ptr[Old_18_Off], e dx 308F nobi: 308F 66| BA 0021 mov dx, 21h ; IRQ mask reg 3093 66| 8B 0D 000025A8 R mov cx, word ptr[IRQ_number] 309A 66| 83 F9 07 cmp cx, 7 309E 76 04 jbe short Ok21 30A0 66| BA 00A1 mov dx, 0A1h ; reg A1h, 2nd ctrl 30A4 EC Ok21: in al, dx 30A5 A2 00002558 R mov byte ptr[IRQ_mask], al ; save mask 30AA 80 E1 07 and cl, 7 30AD B3 01 mov bl, 1 30AF D2 E3 shl bl, cl 30B1 F6 D3 not bl 30B3 22 C3 and al, bl ; unmask IRQ 30B5 EE out dx, al ; write new mask ifdef SBPRO call ResetCard endif 30B6 BA 00002628 R mov edx, offset NewIRQ 30BB E8 FFFFFEED call InstallISR endif 30C0 E8 FFFFF96C call StopSample ; to reset everything 30C5 33 C0 xor eax, eax 30C7 A3 00001298 R mov dword ptr[BackCurrentLis t], eax 30CC A3 00001B30 R mov dword ptr[BackSonList], eax 30D1 8B 3D 000025E4 R mov edi, dword ptr[BUFFER_DM A] 30D7 8B C7 mov eax, edi 30D9 05 00001000 add eax, BUFFER_SIZE * SSIZE 30DE A3 000025E8 R mov dword ptr[MID_BUFFER_DMA ], eax ; init pointer 30E3 A3 000025EC R mov dword ptr[CURRENT_BUFFER ], eax ; init pointer 30E8 C7 05 000025B4 R mov dword ptr[BufferHalf], 4 00000004 ; point on second half 30F2 B9 00000800 mov ecx, (BUFFER_SIZE * 2 * SSIZE) / 4; clear all buffer MIDPOINT 1 1 IFDEF SAMPLE16BIT 30F7 33 C0 1 xor eax, eax 1 ELSE 1 mov eax, 80808080h 1 ENDIF 1 30F9 F3/ AB rep stosd ifndef NOIRQ ifdef AUTO_DMA 30FB B9 00002000 mov ecx, BUFFER_SIZE * 2 * S SIZE 3100 66| 83 3D 000025AC R cmp word ptr[DMA_number], 3 03 3108 76 02 jbe noLengthAdj 310A D1 E9 shr ecx, 1 310C NoLengthAdj: 310C 49 dec ecx 310D 8B 1D 000025C0 R mov ebx, dword ptr[DMA] ; Point to DMAx 3113 66| 8B 53 08 mov dx, word ptr[ebx + MASK_ REG] 3117 8A 43 03 mov al, byte ptr[ebx + MASK2 ] ; mask channel 311A EE out dx, al 311B 66| 8B 53 0C mov dx, word ptr[ebx + FF_RE G] 311F EE out dx, al ; flip-flop 3120 66| 8B 53 06 mov dx, word ptr[ebx + COUNT _REG] 3124 8A C1 mov al, cl ; buffer size - 1 3126 EE out dx, al 3127 8A C5 mov al, ch 3129 EE out dx, al 312A 66| 8B 53 04 mov dx, word ptr[ebx + ADDX_ REG] 312E A1 000025E4 R mov eax, dword ptr[BUFFER_DM A] ; start offset 3133 66| 83 3D 000025AC R cmp word ptr[DMA_number], 3 03 313B 76 0D jbe noAddrAdj ; shr eax, 1 313D D1 E8 shr eax, 1 313F 66| 8B F8 mov di, ax 3142 66| 33 C0 xor ax, ax 3145 D1 E0 shl eax, 1 3147 66| 8B C7 mov ax, di 314A NoAddrAdj: 314A EE out dx, al 314B C1 E8 08 shr eax, 8 314E EE out dx, al 314F 66| 8B 53 0E mov dx, word ptr[ebx + PAGE_ REG] 3153 C1 E8 08 shr eax, 8 ; page of DMA transfert 3156 EE out dx, al 3157 66| 8B 53 0A mov dx, word ptr[ebx + MODE_ REG] 315B 8A 43 01 mov al, byte ptr[ebx + AUTO_ OUT] ; output sample 315E EE out dx, al 315F 66| 8B 53 08 mov dx, word ptr[ebx + MASK_ REG] 3163 8A 43 02 mov al, byte ptr[ebx + MASK1 ] ; channel OK 3166 EE out dx, al endif endif ifdef AUTO_DMA 3167 E8 000003B8 call StartDMACard elseifdef SINGLE_DMA call BlockTransfert ; Start DMA transfert endif 316C B8 00000001 mov eax, 1 ret 3171 5D * pop ebp 3172 5E * pop esi 3173 5F * pop edi 3174 5B * pop ebx 3175 C9 * leave 3176 C3 * ret 00000h 3177 InitCard ENDP ;----------------------------------------------- ----------------------------- 3177 ClearCard PROC USES EBX ESI EDI EBP 3177 53 * push ebx 3178 56 * push esi 3179 57 * push edi 317A 55 * push ebp 317B E8 FFFFF8B1 call StopSample ; just in case something was playing... 3180 E8 00000359 call CloseCard ifndef NOIRQ 3185 66| BA 0021 mov dx, 21h ; read IRQ mask 3189 66| 83 3D 000025A8 R cmp word ptr[IRQ_number], 7 07 3191 76 05 jbe short Ok21 3193 66| 81 C2 0080 add dx, 80h ; reg 0A1h 3198 A0 00002558 R Ok21: mov al, byte ptr[IRQ_mask] ; get old mask 319D EE out dx, al ; write old IRQ mask 319E 8A 1D 000025B0 R mov bl, byte ptr[INT_number] 31A4 66| 8B 0D 00002586 R mov cx, word ptr[Old_PIRQ_se l] 31AB 8B 15 0000258C R mov edx, dword ptr[Old_PIRQ_ off] SET_PROT_VECT 1 31B1 66| B8 0205 1 mov ax, 0205h 31B5 CD 31 1 int 31h 1 31B7 83 3D 000025A8 R cmp dword ptr[IRQ_number], 7 07 31BE 76 2F jbe nobi 31C0 8A 1D 000025B0 R mov bl, byte ptr[INT_number] 31C6 66| 8B 0D 00002584 R mov cx, word ptr[Old_RIRQ_se g] 31CD 66| 8B 15 0000258A R mov dx, word ptr[Old_RIRQ_of f] SET_REAL_VECT 1 31D4 66| B8 0201 1 mov ax, 0201h 31D8 CD 31 1 int 31h 1 31DA B3 18 mov bl, 18h 31DC 66| 8B 0D 00002588 R mov cx, word ptr[Old_18_sel] 31E3 8B 15 00002590 R mov edx, dword ptr[Old_18_of f] SET_PROT_VECT 1 31E9 66| B8 0205 1 mov ax, 0205h 31ED CD 31 1 int 31h 1 31EF nobi: endif ret 31EF 5D * pop ebp 31F0 5F * pop edi 31F1 5E * pop esi 31F2 5B * pop ebx 31F3 C3 * ret 00000h 31F4 ClearCard ENDP ;----------------------------------------------- ----------------------------- 31F4 AskVars PROC ,\ pListNames:DWORD, pListVars:DWOR D 31F4 55 * push ebp 31F5 8B EC * mov ebp, esp 31F7 B8 00002594 R mov eax, offset ListNames 31FC 8B 4D 08 mov ecx, pListNames 31FF 89 01 mov dword ptr[ecx], eax 3201 B8 000025A0 R mov eax, offset ListVars 3206 8B 4D 0C mov ecx, pListVars 3209 89 01 mov dword ptr[ecx], eax ret 320B C9 * leave 320C C3 * ret 00000h 320D AskVars ENDP ;----------------------------------------------- ----------------------------- 320D GetBufferSize PROC 320D B8 00002000 mov eax, BUFFER_SIZE * 2 * S SIZE 3212 C3 ret 3213 GetBufferSize ENDP ;----------------------------------------------- ----------------------------- 3213 GiveSampleInfo0 PROC \ LongHandle:DWORD, Info:DWORD 3213 55 * push ebp 3214 8B EC * mov ebp, esp 3216 8B 45 08 mov eax, LongHandle CRIT_SECT 1 3219 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 3222 E8 FFFFFA73 call SearchLongHandle 3227 0B D2 or edx, edx 3229 74 06 jz short notfound 322B 8B 45 0C mov eax, Info 322E 89 42 24 mov dword ptr[edx+INFO0], ea x 3231 notfound: END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 3231 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 323A 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 3242 74 22 1 je ??0009 ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 3244 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 324D 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 324E E8 FFFFF447 1 call UpdateBuffer 1 ; do the update 3253 61 1 popad 3254 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 325D 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 3266 1 ??0009: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) ret 3266 C9 * leave 3267 C3 * ret 00000h 3268 GiveSampleInfo0 ENDP ;----------------------------------------------- ----------------------------- 3268 GetSnapSample PROC USES EBX,\ pList:DWORD 3268 55 * push ebp 3269 8B EC * mov ebp, esp 326B 53 * push ebx 326C 8D 05 000023C8 R lea eax, SnapList 3272 8B 55 08 mov edx, pList 3275 89 02 mov dword ptr[edx], eax 3277 8D 15 00000168 R lea edx, CurrentList 327D 8D 0D 00000A00 R lea ecx, SonList CRIT_SECT 1 3283 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 328C 83 3A 00 keeplooking: cmp dword ptr[edx], 0 328F 74 1B je short exit 3291 8B 5A 14 mov ebx, dword ptr[edx+HANDL E] 3294 89 18 mov dword ptr[eax], ebx 3296 8B 5A 24 mov ebx, dword ptr[edx+INFO0 ] 3299 89 58 04 mov dword ptr[eax+4], ebx 329C 8B 1A mov ebx, dword ptr[edx] 329E 2B 5A 18 sub ebx, dword ptr[edx+START ] 32A1 89 58 08 mov dword ptr[eax+8], ebx 32A4 83 C0 0C add eax, 12 32A7 83 C2 2C add edx, STRUCT_SIZE 32AA EB E0 jmp short keeplooking 32AC exit: 32AC 3B CA cmp ecx, edx 32AE 8B D1 mov edx, ecx 32B0 75 DA jne keeplooking END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 32B2 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 32BB 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 32C3 74 22 1 je ??000A ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 32C5 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 32CE 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 32CF E8 FFFFF3C6 1 call UpdateBuffer 1 ; do the update 32D4 61 1 popad 32D5 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 32DE 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 32E7 1 ??000A: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) 32E7 2D 000023C8 R sub eax, offset SnapList 32EC C1 E8 03 shr eax, 3 ret 32EF 5B * pop ebx 32F0 C9 * leave 32F1 C3 * ret 00000h 32F2 GetSnapSample ENDP ;----------------------------------------------- ----------------------------- 32F2 CopyList PROC 32F2 83 3E 00 keepcopying: cmp dword ptr[esi], 0 32F5 74 09 je short endcopy 32F7 B9 0000000B mov ecx, STRUCT_SIZE / 4 32FC F3/ A5 rep movsd 32FE EB F2 jmp short keepcopying 3300 C7 07 00000000 endcopy: mov dword ptr[edi], 0 3306 C3 ret 3307 CopyList ENDP ;----------------------------------------------- ----------------------------- 3307 SAveStateSample PROC USES ESI EDI 3307 56 * push esi 3308 57 * push edi 3309 E8 FFFFFBF9 call PauseSample 330E 80 3D 00002559 R waitpause: cmp byte ptr[FlagPause], 1 01 3315 75 F7 jne short waitpause CRIT_SECT 1 3317 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 3320 8D 35 00000168 R lea esi, CurrentList ; backup CurrentList 3326 8D 3D 00001298 R lea edi, BackCurrentList 332C E8 FFFFFFC1 call CopyList 3331 8D 35 00000A00 R lea esi, SonList ; backup SonList 3337 8D 3D 00001B30 R lea edi, BackSonList 333D E8 FFFFFFB0 call CopyList 3342 A1 000025B8 R mov eax, dword ptr[follow] ; Backup follow 3347 A3 000025BC R mov dword ptr[backfollow], e ax 334C A1 000025C4 R mov eax, dword ptr[weirdcoun t] ; Backup weirdcount 3351 A3 000025C8 R mov dword ptr[backweirdcount ], eax 3356 33 C0 xor eax, eax ; empty both lists 3358 A3 00000168 R mov dword ptr[CurrentList], eax 335D A3 00000A00 R mov dword ptr[SonList], eax 3362 C6 05 00002559 R mov byte ptr[FlagPause], 0 00 END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 3369 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 3372 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 337A 74 22 1 je ??000B ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 337C 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 3385 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 3386 E8 FFFFF30F 1 call UpdateBuffer 1 ; do the update 338B 61 1 popad 338C 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 3395 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 339E 1 ??000B: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) ret 339E 5F * pop edi 339F 5E * pop esi 33A0 C3 * ret 00000h 33A1 SAveStateSample ENDP ;----------------------------------------------- ----------------------------- 33A1 RestoreStateSample PROC USES ESI EDI 33A1 56 * push esi 33A2 57 * push edi 33A3 E8 FFFFFB5F call PauseSample 33A8 80 3D 00002559 R waitpause: cmp byte ptr[FlagPause], 1 01 33AF 75 F7 jne short waitpause CRIT_SECT 1 33B1 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; tell the IRQ not to update the buffer 1 1 ; we'll take care of it if nescessary O:-) 33BA 8D 35 00001298 R lea esi, BackCurrentList ; restore CurrentList 33C0 8D 3D 00000168 R lea edi, CurrentList 33C6 E8 FFFFFF27 call CopyList 33CB 8D 3D 00001B30 R lea edi, BackSonList ; restore SonList 33D1 8D 3D 00000A00 R lea edi, SonList 33D7 E8 FFFFFF16 call CopyList 33DC A1 000025BC R mov eax, dword ptr[backfollo w] ; restore follow 33E1 A3 000025B8 R mov dword ptr[follow], eax 33E6 A1 000025C8 R mov eax, dword ptr[backweird count] ; restore weirdcount 33EB A1 000025C4 R mov eax, dword ptr[weirdcoun t] END_CRIT_SECT 1 local NoUpdate 1 ; Update buffer if necessary 1 1 ; Dealing with the critical sect 1 ion flags................ 1 ; 1 DO NOT TOUCH !!!! 1 33F0 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect. 1 1 ; this way DoUpdate can't change to 1 anymore 33F9 66| 83 3D 00002582 R 1 cmp word ptr[DoUpdate], 0 00 1 ; IRQ happened ? 3401 74 22 1 je ??000C ; 1 if DopUpdate change to 0 now, we are in deep 1 1 ; shit anyway because we missed one round! 1 1 ; The program won't crash but we'll ear the old 1 1 ; content of half a buffer and also miss half a 1 buffer 1 1 ; of new data... :-( 3403 66| C7 05 00002580 R 1 mov word ptr[Critical], 1 0001 1 ; yes, crit. again, so we don't update twice 1 1 ; because UpdateBuffer is not reentrant 1 1 ; and we don't want to take a chance on crashing 1 ! 340C 60 1 pushad 1 ; if DoUpdate change to 1 HERE 1 1 ; it means again that we missed one round! 1 1 ; So we play the buffer we are updating! (funny 1 noise :-( ) 1 1 ; and then will ear half buffer of old data! 340D E8 FFFFF288 1 call UpdateBuffer 1 ; do the update 3412 61 1 popad 3413 66| C7 05 00002580 R 1 mov word ptr[Critical], 0 0000 1 ; exit crit. sect 1 1 ; this way DoUpdate can't change to 1 anymore 341C 66| C7 05 00002582 R 1 mov word ptr[DoUpdate], 0 0000 1 ; Update done, so DoUpdate = 0 3425 1 ??000C: 1 1 1 ; ALL THOSE NASTY THING SHOULD NOT HAPPEN :-) !! 1 !! 1 1 ; BECAUSE IT WOULD MEAN THAT THE UPDATE OF THE B 1 UFFER 1 1 ; TAKES MORE THAN 46000 microsec! 1 1 ; (at 33 Mhz one cycle = .03 microsec so 4600 mi 1 crosec = 1.5 million cycle) 3425 E8 FFFFFB32 call ContinueSample 342A 80 3D 00002559 R waitcontinue: cmp byte ptr[FlagPause], 0 00 3431 75 F7 jne short waitcontinue ret 3433 5F * pop edi 3434 5E * pop esi 3435 C3 * ret 00000h 3436 RestoreStateSample ENDP ;----------------------------------------------- ----------------------------- ;----------------------------------------------- ----------------------------- ifdef MWSS ResetCard PROC USES EBX mov ax, word ptr[PlayRate] cmp ax, 44100 jae short Freq44 lea edx, MWSSFreq SearchFreq: cmp ax, word ptr[edx] jb short FoundFreq add edx, 4 jmp short SearchFreq Freq44: mov ax, 44100 mov cl, 0Bh jmp short WBack FoundFreq: mov ax, word ptr[edx] ; closest faster speed mov cl, byte ptr[edx+2] ; clock select WBack: mov word ptr[PlayRate], ax or cl, 01010000b ; 16 bit linear, Stereo mov edx, [IRQ_number] ; IRQ mov al, [MWSSIrq+edx] mov edx, [DMA_number] ; DMA or al, [MWSSDma+edx] mov dx, word ptr[BASE_ADDR] add dl, 3 ; offset 3 out dx, al ; program IRQ & DMA inc dl ; offset 4 mov al, 6 ; left vol out dx, al inc dl ; offset 5 mov al, 80h ; mute out dx, al dec dl ; offset 4 mov al, 7 ; right vol out dx, al inc dl ; offset 5 mov al, 80h ; mute out dx, al dec dl ; offset 4 mov al, 13 ; digital mix out dx, al inc dl ; offset 5 xor al, al ; mute out dx, al dec dl ; offset 4 mov al, 2 ; left aux1 out dx, al inc dl ; offset 5 mov al, 80h ; mute out dx, al dec dl ; offset 4 mov al, 3 ; right aux1 out dx, al inc dl ; offset 5 mov al, 80h ; mute out dx, al dec dl ; offset 4 mov al, 4 ; left aux2 out dx, al inc dl ; offset 5 mov al, 80h ; mute out dx, al dec dl ; offset 4 mov al, 5 ; right aux2 out dx, al inc dl ; offset 5 mov al, 80h ; mute out dx, al dec dl ; offset 4 mov al, 49h ; enter MCE, Interface Ctrl out dx, al inc dl ; offset 5 mov al, 08h ; auto-calibrate out dx, al dec dl ; offset 4 mov al, 48h ; MCE, Interface Ctrl out dx, al inc dl ; offset 5 mov al, cl ; 16 bit linear, stereo, speed out dx, al dec dl ; offset 4 wait_init: in al, dx and al, 80h jnz wait_init xor al, al out dx, al ; clear MCE xor bx, bx ; at least 6 millisec. wait0: in al, dx dec bx jnz short wait0 wait_cal: mov al, 0Bh ; Test & Init Reg out dx, al inc dl ; offset 5 in al, dx dec dl ; offset 4 and al, 20h jnz wait_cal mov al, 6 ; left vol out dx, al inc dl ; offset 5 xor al, al ; max vol out dx, al dec dl ; offset 4 mov al, 7 ; right vol out dx, al inc dl ; offset 5 xor al, al ; max vol out dx, al ret ResetCard ENDP ;*---------------------------------------------- ----------------------------* CloseCard PROC mov dx, word ptr[BASE_ADDR] ; DSP add dl, 4 ; offset 4 mov al, 0Ah ; Pin Ctrl reg out dx, al inc dx ; offset 5 xor al, al ; turn off interrupts out dx, al inc dx ; offset 6 out dx, al ; Ack outstanding interrupts sub dl, 2 ; offset 4 mov al, 9 ; Interface Config reg out dx, al inc dx ; offset 5 xor al, al ; turn off codec DMA out dx, al sub dl, 2 out dx, al ; deselect IRQ and DMA ret CloseCard ENDP ;----------------------------------------------- ----------------------------- AckIrq PROC mov dx, word ptr[BASE_ADDR] ; DSP add dl, 6 in al, dx shr al, 1 ; get int flag in C cmc ; complement C in order to return error if 0 out dx, al ; Ack anyway ret AckIrq ENDP ;----------------------------------------------- ----------------------------- StartDMACard PROC mov cx, BUFFER_SIZE - 1 mov dx, word ptr[BASE_ADDR] ; DSP add dl, 6 out dx, al ; clear any pending IRQ sub dl, 2 ; offset 4 mov al, 15 ; DMA Count Lower out dx, al inc dl ; offset 5 mov al, cl out dx, al dec dl ; offset 4 mov al, 14 ; DMA Count Upper out dx, al inc dl ; offset 5 mov al, ch out dx, al dec dl ; offset 4 mov al, 9 ; Interface config out dx, al inc dl ; offset 5 mov al, 00000101b ; DMA Playback out dx, al dec dl ; offset 4 mov al, 0Ah ; Pin Ctrl Reg out dx, al inc dx ; offset 5 mov al, 00000010b ; Turn on Interrupts out dx, al ret StartDMACard ENDP endif ;----------------------------------------------- ----------------------------- ;----------------------------------------------- ----------------------------- ifdef SBLASTER WRITE_DSP MACRO VAL ; write to DSP whithout timeout local wait_dsp wait_dsp: in al, dx or al, al js wait_dsp mov al, VAL out dx, al ENDM WRITE_MIXER MACRO REG, VAL ; write to MIXER chip mov al, REG out dx, al inc dx mov al, VAL out dx, al dec dx ENDM READ_MIXER MACRO REG ; read from MIXER chip mov al, REG out dx, al inc dx in al, dx dec dx ENDM ifdef SBPRO InitIRQ PROC pushad push ds mov ax, cs:word ptr[local_DS ] ; restore DS mov ds, ax mov al, 20h ; allows for new int cmp byte ptr[IRQ_number], 7 jbe short NoSecondCtrl out 0A0h, al NoSecondCtrl: out 20h, al call AckIrq jc short FinIRQ ; not a DMA IRQ mov byte ptr[OkIRQ], 1 FinIRQ: pop ds popad iretd InitIRQ ENDP endif 3436 ResetCard PROC 3436 81 3D 000025A4 R cmp dword ptr[PlayRate], 120 00002EE0 00 3440 73 0A jae OkRateLow 3442 C7 05 000025A4 R mov dword ptr[PlayRate], 120 00002EE0 00 344C OkRateLow: 344C 81 3D 000025A4 R cmp dword ptr[PlayRate], 220 000055F0 00 3456 76 0A jbe OkRateHigh 3458 C7 05 000025A4 R mov dword ptr[PlayRate], 220 000055F0 00 3462 OkRateHigh: ifndef SB16 ifdef SBPRO mov dx, 07A1h mov ax, 2000h ; dx:ax = 128000000 else mov dx, 0F42h mov ax, 4000h ; dx:ax = 256000000 endif div word ptr[PlayRate] ; divide by PlayRate neg ax shr ax, 8 mov cx, ax ; cl = "Magic" push ecx ifdef SBPRO mov dx, 07h mov ax, 0A120h ; dx:ax = 500000 else mov dx, 0Fh mov ax, 4240h ; dx:ax = 1000000 endif neg cl div cx ; divide by "-Magic" mov word ptr[PlayRate], ax ; write back PlayRate endif 3462 66| 8B 15 000025A0 R mov dx, word ptr[BASE_ADDR] 3469 80 C2 06 add dl, 6 ; reset port (offset 6) 346C B0 01 mov al, 1 ; write 1 346E EE out dx, al 346F B4 18 mov ah, 8 * 3 ; 4 * "in al, dx" = 1 microsec on std IS A bus (8 Mhz) 3471 EC wait_io: in al, dx ; so 8 to be sure if 16 MHz ! 3472 FE CC dec ah ; kill the cat ! 3474 75 FB jnz short wait_io 3476 32 C0 xor al, al 3478 EE out dx, al ; write 0 ; now reset should be done.. 3479 80 C2 04 add dl, 4 ; offset 0Ah 347C 80 C2 04 Next: add dl, 4 ; offset 0Eh 347F EC Wait_s: in al, dx 3480 0A C0 or al, al 3482 79 FB jns Wait_s 3484 80 EA 04 sub dl, 4 ; offset 0Ah 3487 EC in al, dx ; read if reset terminated 3488 3C AA cmp al, RESET_TEST_CODE ; should be... 348A 75 F0 jne Next ifdef SB16 348C 80 EA 06 sub dl, 6 ; offset 04h 348F B0 80 mov al, 80h 3491 EE out dx, al 3492 66| 42 inc dx ; offset 05h 3494 33 C0 xor eax, eax 3496 EC in al, dx 3497 24 0F and al, 0Fh ; mask reserved bit 3499 66| 0F BC C0 bsf ax, ax 349D 8A 80 0000257C R mov al, byte ptr[SB16_IRQ+ea x] 34A3 A3 000025A8 R mov dword ptr[IRQ_number], e ax 34A8 66| 4A dec dx ; offset 04h 34AA B0 81 mov al, 81h 34AC EE out dx, al 34AD 66| 42 inc dx ; offset 05h 34AF EC in al, dx 34B0 24 EB and al, 11101011b ; mask reserved bit ifdef SAMPLE16BIT 34B2 66| 0F BD C0 bsr ax, ax else bsf ax, ax endif 34B6 A3 000025AC R mov dword ptr[DMA_number], e ax 34BB 80 C2 07 add dl, 7 ; offset 0Ch WRITE_DSP DSP_RATE_CMD ; rate 1 local wait_dsp 1 34BE EC 1 ??000D: in al, dx 34BF 0A C0 1 or al, al 34C1 78 FB 1 js ??000D 1 34C3 B0 41 1 mov al, DSP_RATE_CMD 34C5 EE 1 out dx, al 1 34C6 66| 8B 0D 000025A4 R mov cx, word ptr[PlayRate] WRITE_DSP ch ; 1 local wait_dsp 1 34CD EC 1 ??000E: in al, dx 34CE 0A C0 1 or al, al 34D0 78 FB 1 js ??000E 1 34D2 8A C5 1 mov al, ch 34D4 EE 1 out dx, al 1 WRITE_DSP cl ; 1 local wait_dsp 1 34D5 EC 1 ??000F: in al, dx 34D6 0A C0 1 or al, al 34D8 78 FB 1 js ??000F 1 34DA 8A C1 1 mov al, cl 34DC EE 1 out dx, al 1 else add dl, 02h ; offset 0Ch WRITE_DSP DSP_ONSPK_CMD ; Turn speaker on ifdef SBPRO mov edx, offset InitIRQ ; Temporary IRQ handler call InstallISR mov dx, word ptr[BASE_ADDR] add dl, 4 ; offset 4 mov al, 0Eh ; stereo switch & filter out dx, al inc dx ; offset 5 in al, dx or al, 2 ; enable stereo out dx, al mov ecx, dword ptr[DMA] ; Point to DMAx mov dx, word ptr[ecx + MASK_ REG] mov al, byte ptr[ecx + MASK2 ] ; mask channel out dx, al mov dx, word ptr[ecx + FF_RE G] out dx, al ; flip-flop mov dx, word ptr[ecx + COUNT _REG] xor al, al out dx, al out dx, al mov eax, dword ptr[BUFFER_DM A] ; start offset mov byte ptr[eax], 80h ; write a "0" into the buffer mov dx, word ptr[ecx + ADDX_ REG] out dx, al shr eax, 8 out dx, al mov dx, word ptr[ecx + PAGE_ REG] shr eax, 8 ; page of DMA transfert out dx, al mov dx, word ptr[ecx + MODE_ REG] mov al, byte ptr[ecx + VOICE _OUT] ; output sample out dx, al mov dx, word ptr[ecx + MASK_ REG] mov al, byte ptr[ecx + MASK1 ] ; channel OK out dx, al mov dx, word ptr[BASE_ADDR] add dl, 0Ch ; offset 0Ch mov byte ptr[OkIRQ], 0 WRITE_DSP DSP_VO8S_CMD WRITE_DSP 0 WRITE_DSP 0 WaitIRQ: cmp byte ptr[OkIRQ], 1 jne short WaitIRQ sub dl, 8 ; offset 4 mov al, 0Eh ; stereo switch & filter out dx, al inc dx ; offset 5 in al, dx mov byte ptr[Filter], al or al, 20h ; disable filter out dx, al add dl, 7 ; offset 0Ch endif pop ecx WRITE_DSP DSP_TIME_CMD ; "rate" WRITE_DSP cl ; magic number ! endif 34DD C3 ret 34DE ResetCard ENDP ;*---------------------------------------------- ----------------------------* 34DE CloseCard PROC 34DE 66| 8B 15 000025A0 R mov dx, word ptr[BASE_ADDR] ; point to DSP ifdef SB16 34E5 80 C2 0C add dl, 0CH ifdef SAMPLE16BIT WRITE_DSP DSP_VO16S_CMD ; single-cycle 16 bit DMA 1 local wait_dsp 1 34E8 EC 1 ??0010: in al, dx 34E9 0A C0 1 or al, al 34EB 78 FB 1 js ??0010 1 34ED B0 B0 1 mov al, DSP_VO16S_CMD 34EF EE 1 out dx, al 1 ifdef STEREO WRITE_DSP DSP_16STEREO_MODE ; 16 bit stereo 1 local wait_dsp 1 34F0 EC 1 ??0011: in al, dx 34F1 0A C0 1 or al, al 34F3 78 FB 1 js ??0011 1 34F5 B0 30 1 mov al, DSP_16STEREO_MODE 34F7 EE 1 out dx, al 1 else WRITE_DSP DSP_16MONO_MODE ; 16 bit mono endif else WRITE_DSP DSP_VO8S_4_CMD ; single-cycle 8 bit DMA ifdef STEREO WRITE_DSP DSP_8STEREO_MODE ; 8 bit stereo else WRITE_DSP DSP_8MONO_MODE ; 8 bit mono endif endif WRITE_DSP 0 ; length of 1 to finish 1 local wait_dsp 1 34F8 EC 1 ??0012: in al, dx 34F9 0A C0 1 or al, al 34FB 78 FB 1 js ??0012 1 34FD B0 00 1 mov al, 0 34FF EE 1 out dx, al 1 WRITE_DSP 0 1 local wait_dsp 1 3500 EC 1 ??0013: in al, dx 3501 0A C0 1 or al, al 3503 78 FB 1 js ??0013 1 3505 B0 00 1 mov al, 0 3507 EE 1 out dx, al 1 else ifdef SBPRO add dl, 6 ; reset port (offset 6) mov al, 1 ; write 1 out dx, al mov ah, 8 * 3 ; 4 * "in al, dx" = 1 microsec on std IS A bus (8 Mhz) wait_io: in al, dx ; so 8 to be sure if 16 MHz ! dec ah ; kill the cat ! jnz wait_io xor al, al out dx, al ; write 0 ; now reset should be done.. add dl, 4 ; offset 0Ah Next: add dl, 4 ; offset 0Eh Wait_s: in al, dx or al, al jns Wait_s sub dl, 4 ; offset 0Ah in al, dx ; read if reset terminated cmp al, RESET_TEST_CODE ; should be... jne Next sub dl, 6 ; offset 4 mov al, 0Eh out dx, al inc dx ; offset 5 mov al, byte ptr[Filter] ; restore filter out dx, al dec dx mov al, 0Eh out dx, al inc dx ; offset 5 in al, dx and al, 11111101b ; turn off stereo out dx, al add dl, 7 ; offset 0Ch WRITE_DSP DSP_OFFSPK_CMD ; Turn speaker off else add dl, 0CH WRITE_DSP DSP_OFFSPK_CMD ; Turn speaker off WRITE_DSP DSP_VO8S_CMD ; single-cycle 8 bit DMA WRITE_DSP 0 ; length of 1 to finish WRITE_DSP 0 endif endif 3508 C3 ret 3509 CloseCard ENDP ;----------------------------------------------- ----------------------------- 3509 AckIrq PROC 3509 66| 8B 15 000025A0 R mov dx, word ptr[BASE_ADDR] ; DSP IRQ ACK ifdef SB16 3510 80 C2 04 add dl, 4 ; offset 4 3513 B0 82 mov al, 82h 3515 EE out dx, al 3516 66| 42 inc dx ; offset 5 3518 EC in al, dx ifdef SAMPLE16BIT 3519 24 02 and al, 2 351B 74 05 jz NoDMAIRQ 351D 80 C2 0A add dl, 10 ; offset Fh else and al, 1 jz NoDMAIRQ add dl, 9 ; offset Eh endif 3520 EC in al, dx 3521 C3 ret 3522 NoDMAIRQ: 3522 F9 stc 3523 C3 ret else add dl, 0Eh ; 8 bit Samples ACK in al, dx ret endif 3524 AckIrq ENDP ;----------------------------------------------- ----------------------------- 3524 StartDMACard PROC 3524 66| 8B 15 000025A0 R mov dx, word ptr[BASE_ADDR] ; DSP 352B 80 C2 0C add dl, 0Ch ifdef STEREO 352E 66| B9 07FF mov cx, BUFFER_SIZE * 2 - 1 ; half-buffer size - 1 for DMA else mov cx, BUFFER_SIZE - 1 ; half-buffer size - 1 for DMA endif ifdef SB16 ifdef SAMPLE16BIT WRITE_DSP DSP_VO16_CMD ; auto-init 16 bit DMA 1 local wait_dsp 1 3532 EC 1 ??0014: in al, dx 3533 0A C0 1 or al, al 3535 78 FB 1 js ??0014 1 3537 B0 B6 1 mov al, DSP_VO16_CMD 3539 EE 1 out dx, al 1 ifdef STEREO WRITE_DSP DSP_16STEREO_MODE ; 16 bit stereo 1 local wait_dsp 1 353A EC 1 ??0015: in al, dx 353B 0A C0 1 or al, al 353D 78 FB 1 js ??0015 1 353F B0 30 1 mov al, DSP_16STEREO_MODE 3541 EE 1 out dx, al 1 else WRITE_DSP DSP_16MONO_MODE ; 16 bit mono endif else WRITE_DSP DSP_VO8_4_CMD ; auto-init 8 bit DMA ifdef STEREO WRITE_DSP DSP_8STEREO_MODE ; 8 bit stereo else WRITE_DSP DSP_8MONO_MODE ; 8 bit mono endif endif WRITE_DSP cl 1 local wait_dsp 1 3542 EC 1 ??0016: in al, dx 3543 0A C0 1 or al, al 3545 78 FB 1 js ??0016 1 3547 8A C1 1 mov al, cl 3549 EE 1 out dx, al 1 WRITE_DSP ch 1 local wait_dsp 1 354A EC 1 ??0017: in al, dx 354B 0A C0 1 or al, al 354D 78 FB 1 js ??0017 1 354F 8A C5 1 mov al, ch 3551 EE 1 out dx, al 1 elseifdef SBLASTER1 WRITE_DSP DSP_VO8S_CMD ; single-cycle 8 bit DMA WRITE_DSP cl WRITE_DSP ch else WRITE_DSP DSP_BSIZE_CMD ; Set block size WRITE_DSP cl WRITE_DSP ch ifdef SBPRO WRITE_DSP DSP_VO8H_CMD ; auto-init 8 bit high-speed DMA else WRITE_DSP DSP_VO8_CMD ; auto-init 8 bit DMA endif endif 3552 C3 ret 3553 StartDMACard ENDP endif ;----------------------------------------------- ----------------------------- ;----------------------------------------------- ----------------------------- ifdef GOLD SELECT_MIXER MACRO local wait mov al, 0FFh out dx, al out dx, al wait: in al, dx and al, 11000000b jnz wait ENDM LEAVE_MIXER MACRO local wait wait: in al, dx and al, 11000000b jnz wait mov al, 0FEh out dx, al out dx, al ENDM WRITE_MIXER MACRO PORT, VAL local wait1, wait2 mov al, PORT out dx, al wait1: in al, dx and al, 11000000b jnz wait1 inc dx mov al, VAL out dx, al dec dx wait2: in al, dx and al, 11000000b jnz wait2 ENDM READ_MIXER MACRO PORT local wait1, wait2 mov al, PORT out dx, al wait1: in al, dx and al, 11000000b jnz wait1 inc dx in al, dx dec dx mov ah, al wait2: in al, dx and al, 11000000b jnz wait2 mov al, ah ENDM WRITE_MMA0 MACRO PORT, VAL mov al, PORT out dx, al inc dx mov al, VAL out dx, al dec dx in al, dx in al, dx ENDM READ_MMA0 MACRO PORT mov al, PORT out dx, al inc dx in al, dx dec dx mov ah, al in al, dx in al, dx mov al, ah ENDM WRITE_MMA1 MACRO PORT, VAL mov al, PORT out dx, al add dx, 3 mov al, VAL out dx, al sub dx, 3 in al, dx in al, dx ENDM READ_MMA1 MACRO PORT mov al, PORT out dx, al add dx, 3 in al, dx sub dx, 3 mov ah, al in al, dx in al, dx mov al, ah ENDM ;*---------------------------------------------- ----------------------------* ResetCard PROC mov dx, word ptr[BASE_ADDR] add dx, 2 ; MIXER SELECT_MIXER WRITE_MIXER 8h, 11001110b ; STEREO mode WRITE_MIXER 11h, 00001000b ; filter on output, no mic input, no PC- speaker input READ_MIXER 13h mov byte ptr[Mixer_13], al mov cl, al and eax, 3 lea ebx, Gold_IRQ mov al, byte ptr[ebx+eax] mov dword ptr[IRQ_number], e ax mov al, cl shr al, 4 and al, 3 mov dword ptr[DMA_number], e ax or cl, 10001000b ; enable DMA0, enable IRQ WRITE_MIXER 13h, cl READ_MIXER 14h mov byte ptr[Mixer_14], al mov cl, al and cl, 01111111b WRITE_MIXER 14h, cl LEAVE_MIXER add dx, 2 ; MMA WRITE_MMA0 9, 80h ; reset channel 0 WRITE_MMA1 9, 80h ; reset channel 1 mov cx, 4 fillFIFO0: WRITE_MMA0 0Bh, 0 dec cx jnz FillFIFO0 mov cx, 4 fillFIFO1: WRITE_MMA1 0Bh, 0 dec cx jnz FillFIFO1 WRITE_MMA0 9, 00101110b ; 22.05 Khz, PCM, L, Play WRITE_MMA1 9, 01001110b ; 22.05 Khz, PCM, R, Play mov word ptr[PlayRate], 2205 0 ; 22.05 Khz WRITE_MMA0 0Ch, 11000101b ; Interleave, 16 bit, 96 byte FIFO, DMA WRITE_MMA1 0Ch, 01000011b ; 16 bit, no FIFO (use other channel), D MA WRITE_MMA0 0Ah, 0FFh ; Maximum volume (volume will be control led by mixer) WRITE_MMA1 0Ah, 0FFh mov cx, 100 fillFIFO: WRITE_MMA0 0Bh, 0 dec cx jnz FillFIFO ret ResetCard ENDP ;*---------------------------------------------- ----------------------------* CloseCard PROC mov dx, word ptr[BASE_ADDR] add dx, 4 ; MMA WRITE_MMA1 0Ch, 01000010b ; 16 bit, no FIFO, no DMA WRITE_MMA0 0Ch, 01000010b ; 16 bit, no FIFO, no DMA WRITE_MMA0 9, 80h ; reset channel 0 WRITE_MMA1 9, 80h ; reset channel 1 sub dx, 2 ; MIXER SELECT_MIXER WRITE_MIXER 13h, Mixer_13 WRITE_MIXER 14h, Mixer_14 LEAVE_MIXER ret CloseCard ENDP ;----------------------------------------------- ----------------------------- AckIrq PROC mov dx, word ptr[BASE_ADDR] add dx, 4 ; MMA in al, dx and al, 1 jz short noDMA mov ebx, dword ptr[DMA] ; Point to DMAx mov dx, word ptr[ebx + FF_RE G] out dx, al ; flip-flop mov dx, word ptr[ebx + COUNT _REG] in al, dx mov ah, al in al, dx xchg al, ah or ax, ax jz short OkDMA inc ax jnz short noDMA OkDMA: clc ret NoDMA: stc ret AckIrq ENDP ;----------------------------------------------- ----------------------------- StartDMACard PROC mov dx, word ptr[BASE_ADDR] add dx, 4 ; MMA WRITE_MMA0 9, 00101111b ; 22.05 Khz, PCM, L, Play, GO ret StartDMACard ENDP endif ;----------------------------------------------- ----------------------------- ;----------------------------------------------- ----------------------------- ifdef GUS extrn Nolanguage resetcard:PROC ;*---------------------------------------------- ----------------------------* extrn Nolanguage CloseCard:PROC ;*---------------------------------------------- ----------------------------* extrn Nolanguage StartDMACard:PROC endif ;----------------------------------------------- ----------------------------- ;----------------------------------------------- ----------------------------- END Microsoft (R) Macro Assembler Version 6.1a 09/22/94 16:09:36 wave_a.asm Symbols 2 - 1 Macros: N a m e Type CRIT_SECT . . . . . . . . . . . Proc END_CRIT_SECT . . . . . . . . . Proc GET_PROT_VECT . . . . . . . . . Proc GET_REAL_VECT . . . . . . . . . Proc MIDPOINT . . . . . . . . . . . . Proc READ_MIXER . . . . . . . . . . . Proc SET_PROT_VECT . . . . . . . . . Proc SET_REAL_VECT . . . . . . . . . Proc WRITE_DSP . . . . . . . . . . . Proc WRITE_MIXER . . . . . . . . . . Proc lve . . . . . . . . . . . . . . Proc setalc . . . . . . . . . . . . . Proc Segments and Groups: N a m e Size Length Align Combine Class FLAT . . . . . . . . . . . . . . GROUP _DATA . . . . . . . . . . . . . 32 Bit 0000 DWord Public 'DATA' _TEXT . . . . . . . . . . . . . 32 Bit 3553 DWord Public 'CODE' Procedures, parameters and locals: N a m e Type Value Attr AckIrq . . . . . . . . . . . . . P Near 3509 _TEXT Length= 001B Pub lic SYSCALL NoDMAIRQ . . . . . . . . . . . L Near 3522 _TEXT AskVars . . . . . . . . . . . . P Near 31F4 _TEXT Length= 0019 Pub lic SYSCALL pListNames . . . . . . . . . . DWord bp + 0008 pListVars . . . . . . . . . . DWord bp + 000C ChangeVolume . . . . . . . . . . P Near 2CBE _TEXT Length= 0063 Pub lic SYSCALL LongHandle . . . . . . . . . . DWord bp + 0008 volleft . . . . . . . . . . . DWord bp + 000C volright . . . . . . . . . . . DWord bp + 0010 notfound . . . . . . . . . . . L Near 2CEA _TEXT ??0005 . . . . . . . . . . . . L Near 2D1F _TEXT ClearCard . . . . . . . . . . . P Near 3177 _TEXT Length= 007D Pub lic SYSCALL Ok21 . . . . . . . . . . . . . L Near 3198 _TEXT nobi . . . . . . . . . . . . . L Near 31EF _TEXT CloseCard . . . . . . . . . . . P Near 34DE _TEXT Length= 002B Pub lic SYSCALL ??0010 . . . . . . . . . . . . L Near 34E8 _TEXT ??0011 . . . . . . . . . . . . L Near 34F0 _TEXT ??0012 . . . . . . . . . . . . L Near 34F8 _TEXT ??0013 . . . . . . . . . . . . L Near 3500 _TEXT ContinueSample . . . . . . . . . P Near 2F5C _TEXT Length= 0051 Pub lic SYSCALL ??0008 . . . . . . . . . . . . L Near 2FAC _TEXT CopyList . . . . . . . . . . . . P Near 32F2 _TEXT Length= 0015 Pub lic SYSCALL keepcopying . . . . . . . . . L Near 32F2 _TEXT endcopy . . . . . . . . . . . L Near 3300 _TEXT GetBufferSize . . . . . . . . . P Near 320D _TEXT Length= 0006 Pub lic SYSCALL GetDMAAddr . . . . . . . . . . . P Near 25F3 _TEXT Length= 0035 Pub lic SYSCALL noadjust . . . . . . . . . . . L Near 2626 _TEXT GetSnapSample . . . . . . . . . P Near 3268 _TEXT Length= 008A Pub lic SYSCALL pList . . . . . . . . . . . . DWord bp + 0008 keeplooking . . . . . . . . . L Near 328C _TEXT exit . . . . . . . . . . . . . L Near 32AC _TEXT ??000A . . . . . . . . . . . . L Near 32E7 _TEXT GiveSampleInfo0 . . . . . . . . P Near 3213 _TEXT Length= 0055 Pub lic SYSCALL LongHandle . . . . . . . . . . DWord bp + 0008 Info . . . . . . . . . . . . . DWord bp + 000C notfound . . . . . . . . . . . L Near 3231 _TEXT ??0009 . . . . . . . . . . . . L Near 3266 _TEXT InitCard . . . . . . . . . . . . P Near 2FED _TEXT Length= 018A Pub lic SYSCALL Buffer . . . . . . . . . . . . DWord bp + 0008 ErrorDMA . . . . . . . . . . . L Near 3021 _TEXT DMAFound . . . . . . . . . . . L Near 3029 _TEXT Second . . . . . . . . . . . . L Near 303B _TEXT gotvect . . . . . . . . . . . L Near 303D _TEXT nobi . . . . . . . . . . . . . L Near 308F _TEXT Ok21 . . . . . . . . . . . . . L Near 30A4 _TEXT NoLengthAdj . . . . . . . . . L Near 310C _TEXT NoAddrAdj . . . . . . . . . . L Near 314A _TEXT InstallISR . . . . . . . . . . . P Near 2FAD _TEXT Length= 0040 Pub lic SYSCALL nobi . . . . . . . . . . . . . L Near 2FEC _TEXT MixSample . . . . . . . . . . . P Near 2D21 _TEXT Length= 01E6 Pub lic SYSCALL thehandle . . . . . . . . . . DWord bp + 0008 pitchbend . . . . . . . . . . DWord bp + 000C therepeat . . . . . . . . . . DWord bp + 0010 plug . . . . . . . . . . . . . DWord bp + 0014 volleft . . . . . . . . . . . DWord bp + 0018 volright . . . . . . . . . . . DWord bp + 001C buffer . . . . . . . . . . . . DWord bp + 0020 okfilter . . . . . . . . . . . L Near 2D36 _TEXT okincr . . . . . . . . . . . . L Near 2DA7 _TEXT next . . . . . . . . . . . . . L Near 2DD8 _TEXT ok_handle . . . . . . . . . . L Near 2E05 _TEXT keeplooking0 . . . . . . . . . L Near 2E27 _TEXT SearchSonList . . . . . . . . L Near 2E36 _TEXT keeplooking1 . . . . . . . . . L Near 2E3C _TEXT exit . . . . . . . . . . . . . L Near 2E4B _TEXT found . . . . . . . . . . . . L Near 2E4F _TEXT NoPlug . . . . . . . . . . . . L Near 2E52 _TEXT SearchEnd . . . . . . . . . . L Near 2E57 _TEXT endcritical . . . . . . . . . L Near 2EC5 _TEXT ??0006 . . . . . . . . . . . . L Near 2EFA _TEXT typeunknown . . . . . . . . . L Near 2EFF _TEXT NewIRQ . . . . . . . . . . . . . P Near 2628 _TEXT Length= 0072 Pub lic SYSCALL NoSecondCtrl . . . . . . . . . L Near 2643 _TEXT FinIRQ . . . . . . . . . . . . L Near 2696 _TEXT PauseSample . . . . . . . . . . P Near 2F07 _TEXT Length= 0055 Pub lic SYSCALL ??0007 . . . . . . . . . . . . L Near 2F5B _TEXT Redirector . . . . . . . . . . . P Near 25F0 _TEXT Length= 0003 Pub lic SYSCALL ResetCard . . . . . . . . . . . P Near 3436 _TEXT Length= 00A8 Pub lic SYSCALL OkRateLow . . . . . . . . . . L Near 344C _TEXT OkRateHigh . . . . . . . . . . L Near 3462 _TEXT wait_io . . . . . . . . . . . L Near 3471 _TEXT Next . . . . . . . . . . . . . L Near 347C _TEXT Wait_s . . . . . . . . . . . . L Near 347F _TEXT ??000D . . . . . . . . . . . . L Near 34BE _TEXT ??000E . . . . . . . . . . . . L Near 34CD _TEXT ??000F . . . . . . . . . . . . L Near 34D5 _TEXT RestoreStateSample . . . . . . . P Near 33A1 _TEXT Length= 0095 Pub lic SYSCALL waitpause . . . . . . . . . . L Near 33A8 _TEXT ??000C . . . . . . . . . . . . L Near 3425 _TEXT waitcontinue . . . . . . . . . L Near 342A _TEXT SAveStateSample . . . . . . . . P Near 3307 _TEXT Length= 009A Pub lic SYSCALL waitpause . . . . . . . . . . L Near 330E _TEXT ??000B . . . . . . . . . . . . L Near 339E _TEXT SampleInList . . . . . . . . . . P Near 2C27 _TEXT Length= 0073 Pub lic SYSCALL thehandle . . . . . . . . . . DWord bp + 0008 keeplooking . . . . . . . . . L Near 2C44 _TEXT exit . . . . . . . . . . . . . L Near 2C54 _TEXT found . . . . . . . . . . . . L Near 2C62 _TEXT ??0004 . . . . . . . . . . . . L Near 2C97 _TEXT SearchLongHandle . . . . . . . . P Near 2C9A _TEXT Length= 0024 Pub lic SYSCALL keeplooking . . . . . . . . . L Near 2CA6 _TEXT exit . . . . . . . . . . . . . L Near 2CB5 _TEXT found . . . . . . . . . . . . L Near 2CBD _TEXT ShiftSamples . . . . . . . . . . P Near 2B2D _TEXT Length= 008C Pub lic SYSCALL DestAddr . . . . . . . . . . . DWord bp + 0008 SrcAddr . . . . . . . . . . . DWord bp + 000C SizeByte . . . . . . . . . . . DWord bp + 0010 keeplooking . . . . . . . . . L Near 2B5F _TEXT notfound . . . . . . . . . . . L Near 2B6E _TEXT exit . . . . . . . . . . . . . L Near 2B73 _TEXT ??0002 . . . . . . . . . . . . L Near 2BB4 _TEXT StartDMACard . . . . . . . . . . P Near 3524 _TEXT Length= 002F Pub lic SYSCALL ??0014 . . . . . . . . . . . . L Near 3532 _TEXT ??0015 . . . . . . . . . . . . L Near 353A _TEXT ??0016 . . . . . . . . . . . . L Near 3542 _TEXT ??0017 . . . . . . . . . . . . L Near 354A _TEXT StopOneSampleLong . . . . . . . P Near 2BB9 _TEXT Length= 006E Pub lic SYSCALL LongHandle . . . . . . . . . . DWord bp + 0008 LoopRemove . . . . . . . . . . L Near 2BDA _TEXT EndRemove . . . . . . . . . . L Near 2BE8 _TEXT notfound . . . . . . . . . . . L Near 2BEE _TEXT ??0003 . . . . . . . . . . . . L Near 2C23 _TEXT StopOneSample . . . . . . . . . P Near 2A91 _TEXT Length= 009C Pub lic SYSCALL thehandle . . . . . . . . . . DWord bp + 0008 keeplooking . . . . . . . . . L Near 2AAD _TEXT exit . . . . . . . . . . . . . L Near 2ABD _TEXT ??0001 . . . . . . . . . . . . L Near 2B03 _TEXT found . . . . . . . . . . . . L Near 2B08 _TEXT noson . . . . . . . . . . . . L Near 2B10 _TEXT LoopRemove . . . . . . . . . . L Near 2B17 _TEXT EndRemove . . . . . . . . . . L Near 2B25 _TEXT StopSample . . . . . . . . . . . P Near 2A31 _TEXT Length= 0060 Pub lic SYSCALL ??0000 . . . . . . . . . . . . L Near 2A90 _TEXT UpdateBuffer . . . . . . . . . . P Near 269A _TEXT Length= 0397 Pub lic SYSCALL dopause . . . . . . . . . . . L Near 26BE _TEXT exit . . . . . . . . . . . . . L Near 26C9 _TEXT loopfadein . . . . . . . . . . L Near 26EC _TEXT fadeout . . . . . . . . . . . L Near 2711 _TEXT loopfadeout . . . . . . . . . L Near 2714 _TEXT endfade . . . . . . . . . . . L Near 2735 _TEXT reallyexit . . . . . . . . . . L Near 2741 _TEXT FinishFill0 . . . . . . . . . L Near 2742 _TEXT process_1st . . . . . . . . . L Near 274B _TEXT Longer0 . . . . . . . . . . . L Near 276C _TEXT NotLonger0 . . . . . . . . . . L Near 277F _TEXT StartMix0 . . . . . . . . . . L Near 2787 _TEXT start0 . . . . . . . . . . . . L Near 27C6 _TEXT next0 . . . . . . . . . . . . L Near 27CF _TEXT nofilter . . . . . . . . . . . L Near 282C _TEXT start01 . . . . . . . . . . . L Near 2832 _TEXT next01 . . . . . . . . . . . . L Near 2844 _TEXT end16 . . . . . . . . . . . . L Near 2857 _TEXT noadjust0 . . . . . . . . . . L Near 285A _TEXT KeepLooking0 . . . . . . . . . L Near 287E _TEXT NoSon0 . . . . . . . . . . . . L Near 288D _TEXT LoopRemove0 . . . . . . . . . L Near 289D _TEXT EndRemove0 . . . . . . . . . . L Near 28AB _TEXT FoundSon0 . . . . . . . . . . L Near 28B3 _TEXT LoopSon0 . . . . . . . . . . . L Near 28C7 _TEXT EndSon0 . . . . . . . . . . . L Near 28D5 _TEXT Reset0 . . . . . . . . . . . . L Near 28E5 _TEXT NextSample . . . . . . . . . . L Near 28F9 _TEXT FinishFill . . . . . . . . . . L Near 290D _TEXT Longer . . . . . . . . . . . . L Near 2937 _TEXT NotLonger . . . . . . . . . . L Near 294A _TEXT StartMix00 . . . . . . . . . . L Near 2952 _TEXT start00 . . . . . . . . . . . L Near 2963 _TEXT next00 . . . . . . . . . . . . L Near 2975 _TEXT noadjust . . . . . . . . . . . L Near 298B _TEXT KeepLooking . . . . . . . . . L Near 29AB _TEXT NoSon . . . . . . . . . . . . L Near 29BA _TEXT LoopRemove . . . . . . . . . . L Near 29C1 _TEXT EndRemove . . . . . . . . . . L Near 29CF _TEXT FoundSon . . . . . . . . . . . L Near 29DA _TEXT LoopSon . . . . . . . . . . . L Near 29EE _TEXT EndSon . . . . . . . . . . . . L Near 29FC _TEXT Finish . . . . . . . . . . . . L Near 2A0C _TEXT Finish2 . . . . . . . . . . . L Near 2A15 _TEXT Reset . . . . . . . . . . . . L Near 2A1D _TEXT Symbols: N a m e Type Value Attr @CodeSize . . . . . . . . . . . Number 0000h @DataSize . . . . . . . . . . . Number 0000h @Interface . . . . . . . . . . . Number 0002h @Model . . . . . . . . . . . . . Number 0007h @code . . . . . . . . . . . . . Text _TEXT @data . . . . . . . . . . . . . Text FLAT @fardata? . . . . . . . . . . . Text FLAT @fardata . . . . . . . . . . . . Text FLAT @stack . . . . . . . . . . . . . Text FLAT ADDRESS . . . . . . . . . . . . Number 0000h ADDX_REG . . . . . . . . . . . . Number 0004h AUTO_DMA . . . . . . . . . . . . Number 0001h AUTO_OUT . . . . . . . . . . . . Number 0001h BASE_ADDR . . . . . . . . . . . DWord 25A0 _TEXT BUFFER_DMA . . . . . . . . . . . DWord 25E4 _TEXT Public SYSCALL BUFFER_SIZE . . . . . . . . . . Number 0400h BackCurrentList . . . . . . . . Byte 1298 _TEXT BackSonList . . . . . . . . . . Byte 1B30 _TEXT BufferHalf . . . . . . . . . . . DWord 25B4 _TEXT Public SYSCALL COUNT_REG . . . . . . . . . . . Number 0006h CURRENT_BUFFER . . . . . . . . . DWord 25EC _TEXT Public SYSCALL C_REPEAT . . . . . . . . . . . . Number 000Ch Critical . . . . . . . . . . . . Word 2580 _TEXT CurrentList . . . . . . . . . . Byte 0168 _TEXT DLENGTH . . . . . . . . . . . . Number 001Ch DMA0_ADDX_REG . . . . . . . . . Word 00EC _TEXT DMA0_AUTO_OUT . . . . . . . . . Byte 00E9 _TEXT DMA0_COUNT_REG . . . . . . . . . Word 00EE _TEXT DMA0_FF_REG . . . . . . . . . . Word 00F4 _TEXT DMA0_MASK1 . . . . . . . . . . . Byte 00EA _TEXT DMA0_MASK2 . . . . . . . . . . . Byte 00EB _TEXT DMA0_MASK_REG . . . . . . . . . Word 00F0 _TEXT DMA0_MODE_REG . . . . . . . . . Word 00F2 _TEXT DMA0_PAGE_REG . . . . . . . . . Word 00F6 _TEXT DMA0_VOICE_OUT . . . . . . . . . Byte 00E8 _TEXT DMA0 . . . . . . . . . . . . . . Number 00E8h DMA1_ADDX_REG . . . . . . . . . Word 00FC _TEXT DMA1_AUTO_OUT . . . . . . . . . Byte 00F9 _TEXT DMA1_COUNT_REG . . . . . . . . . Word 00FE _TEXT DMA1_FF_REG . . . . . . . . . . Word 0104 _TEXT DMA1_MASK1 . . . . . . . . . . . Byte 00FA _TEXT DMA1_MASK2 . . . . . . . . . . . Byte 00FB _TEXT DMA1_MASK_REG . . . . . . . . . Word 0100 _TEXT DMA1_MODE_REG . . . . . . . . . Word 0102 _TEXT DMA1_PAGE_REG . . . . . . . . . Word 0106 _TEXT DMA1_VOICE_OUT . . . . . . . . . Byte 00F8 _TEXT DMA1 . . . . . . . . . . . . . . Number 00F8h DMA3_ADDX_REG . . . . . . . . . Word 010C _TEXT DMA3_AUTO_OUT . . . . . . . . . Byte 0109 _TEXT DMA3_COUNT_REG . . . . . . . . . Word 010E _TEXT DMA3_FF_REG . . . . . . . . . . Word 0114 _TEXT DMA3_MASK1 . . . . . . . . . . . Byte 010A _TEXT DMA3_MASK2 . . . . . . . . . . . Byte 010B _TEXT DMA3_MASK_REG . . . . . . . . . Word 0110 _TEXT DMA3_MODE_REG . . . . . . . . . Word 0112 _TEXT DMA3_PAGE_REG . . . . . . . . . Word 0116 _TEXT DMA3_VOICE_OUT . . . . . . . . . Byte 0108 _TEXT DMA3 . . . . . . . . . . . . . . Number 0108h DMA5_ADDX_REG . . . . . . . . . Word 011C _TEXT DMA5_AUTO_OUT . . . . . . . . . Byte 0119 _TEXT DMA5_COUNT_REG . . . . . . . . . Word 011E _TEXT DMA5_FF_REG . . . . . . . . . . Word 0124 _TEXT DMA5_MASK1 . . . . . . . . . . . Byte 011A _TEXT DMA5_MASK2 . . . . . . . . . . . Byte 011B _TEXT DMA5_MASK_REG . . . . . . . . . Word 0120 _TEXT DMA5_MODE_REG . . . . . . . . . Word 0122 _TEXT DMA5_PAGE_REG . . . . . . . . . Word 0126 _TEXT DMA5_VOICE_OUT . . . . . . . . . Byte 0118 _TEXT DMA5 . . . . . . . . . . . . . . Number 0118h DMA6_ADDX_REG . . . . . . . . . Word 012C _TEXT DMA6_AUTO_OUT . . . . . . . . . Byte 0129 _TEXT DMA6_COUNT_REG . . . . . . . . . Word 012E _TEXT DMA6_FF_REG . . . . . . . . . . Word 0134 _TEXT DMA6_MASK1 . . . . . . . . . . . Byte 012A _TEXT DMA6_MASK2 . . . . . . . . . . . Byte 012B _TEXT DMA6_MASK_REG . . . . . . . . . Word 0130 _TEXT DMA6_MODE_REG . . . . . . . . . Word 0132 _TEXT DMA6_PAGE_REG . . . . . . . . . Word 0136 _TEXT DMA6_VOICE_OUT . . . . . . . . . Byte 0128 _TEXT DMA6 . . . . . . . . . . . . . . Number 0128h DMA7_ADDX_REG . . . . . . . . . Word 013C _TEXT DMA7_AUTO_OUT . . . . . . . . . Byte 0139 _TEXT DMA7_COUNT_REG . . . . . . . . . Word 013E _TEXT DMA7_FF_REG . . . . . . . . . . Word 0144 _TEXT DMA7_MASK1 . . . . . . . . . . . Byte 013A _TEXT DMA7_MASK2 . . . . . . . . . . . Byte 013B _TEXT DMA7_MASK_REG . . . . . . . . . Word 0140 _TEXT DMA7_MODE_REG . . . . . . . . . Word 0142 _TEXT DMA7_PAGE_REG . . . . . . . . . Word 0146 _TEXT DMA7_VOICE_OUT . . . . . . . . . Byte 0138 _TEXT DMA7 . . . . . . . . . . . . . . Number 0138h DMA_number . . . . . . . . . . . DWord 25AC _TEXT DMA . . . . . . . . . . . . . . DWord 25C0 _TEXT DSP_16MONO_MODE . . . . . . . . Number 0010h DSP_16STEREO_MODE . . . . . . . Number 0030h DSP_8MONO_MODE . . . . . . . . . Number 0000h DSP_8STEREO_MODE . . . . . . . . Number 0020h DSP_BSIZE_CMD . . . . . . . . . Number 0048h DSP_OFFSPK_CMD . . . . . . . . . Number 00D3h DSP_ONSPK_CMD . . . . . . . . . Number 00D1h DSP_RATE_CMD . . . . . . . . . . Number 0041h DSP_TIME_CMD . . . . . . . . . . Number 0040h DSP_VO16S_CMD . . . . . . . . . Number 00B0h DSP_VO16_CMD . . . . . . . . . . Number 00B6h DSP_VO8H_CMD . . . . . . . . . . Number 0090h DSP_VO8S_4_CMD . . . . . . . . . Number 00C0h DSP_VO8S_CMD . . . . . . . . . . Number 0014h DSP_VO8_4_CMD . . . . . . . . . Number 00C6h DSP_VO8_CMD . . . . . . . . . . Number 001Ch DoUpdate . . . . . . . . . . . . Word 2582 _TEXT Empty . . . . . . . . . . . . . Byte 257B _TEXT FF_REG . . . . . . . . . . . . . Number 000Ch FRACT . . . . . . . . . . . . . Number 0004h FlagPause . . . . . . . . . . . Byte 2559 _TEXT HANDLE . . . . . . . . . . . . . Number 0014h INCR . . . . . . . . . . . . . . Number 000Eh INFO0 . . . . . . . . . . . . . Number 0024h INTERPOL . . . . . . . . . . . . Number 0028h INT_number . . . . . . . . . . . DWord 25B0 _TEXT IRQ_mask . . . . . . . . . . . . Byte 2558 _TEXT IRQ_number . . . . . . . . . . . DWord 25A8 _TEXT LAST_SAMPLE . . . . . . . . . . Number 0029h LEFT . . . . . . . . . . . . . . Number 0008h LIST_SIZE . . . . . . . . . . . Number 0032h ListFuncs . . . . . . . . . . . DWord 00A0 _TEXT ListNames . . . . . . . . . . . DWord 2594 _TEXT ListVars . . . . . . . . . . . . Number 25A0h MASK1 . . . . . . . . . . . . . Number 0002h MASK2 . . . . . . . . . . . . . Number 0003h MASK_REG . . . . . . . . . . . . Number 0008h MID_BUFFER_DMA . . . . . . . . . DWord 25E8 _TEXT MODE_REG . . . . . . . . . . . . Number 000Ah NoLanguage . . . . . . . . . . . Text SYSCALL Old_18_Off . . . . . . . . . . . DWord 2590 _TEXT Old_18_Sel . . . . . . . . . . . Word 2588 _TEXT Old_PIRQ_Off . . . . . . . . . . DWord 258C _TEXT Old_PIRQ_Sel . . . . . . . . . . Word 2586 _TEXT Old_RIRQ_Off . . . . . . . . . . Word 258A _TEXT Old_RIRQ_Seg . . . . . . . . . . Word 2584 _TEXT PAGE_REG . . . . . . . . . . . . Number 000Eh PlayRate . . . . . . . . . . . . DWord 25A4 _TEXT Public SYSCALL RESET_TEST_CODE . . . . . . . . Number 00AAh SAMPLE16BIT . . . . . . . . . . Text SB16_IRQ . . . . . . . . . . . . Byte 257C _TEXT SB16 . . . . . . . . . . . . . . Text SBLASTER . . . . . . . . . . . . Number 0001h SHIFT_SAMPLE . . . . . . . . . . Number 0003h SLONG . . . . . . . . . . . . . Number 0001h SNAP_SIZE . . . . . . . . . . . Number 0008h SON . . . . . . . . . . . . . . Number 0010h SSIZE . . . . . . . . . . . . . Number 0004h START . . . . . . . . . . . . . Number 0018h STEREO . . . . . . . . . . . . . Text STRUCT_SIZE . . . . . . . . . . Number 002Ch SnapList . . . . . . . . . . . . Byte 23C8 _TEXT SonList . . . . . . . . . . . . Byte 0A00 _TEXT TAB_DMA . . . . . . . . . . . . DWord 0148 _TEXT TheVolumeL . . . . . . . . . . . DWord 25D0 _TEXT TheVolumeR . . . . . . . . . . . DWord 25CC _TEXT VOICE_HANDLE . . . . . . . . . . Number 1234h VOICE_OUT . . . . . . . . . . . Number 0000h VOL_LEFT . . . . . . . . . . . . Number 0020h VOL_RIGHT . . . . . . . . . . . Number 0022h WaveBase . . . . . . . . . . . . Byte 255A _TEXT WaveDMA . . . . . . . . . . . . Byte 256B _TEXT WaveIRQ . . . . . . . . . . . . Byte 2563 _TEXT WaveRate . . . . . . . . . . . . Byte 2573 _TEXT backfollow . . . . . . . . . . . DWord 25BC _TEXT backweirdcount . . . . . . . . . DWord 25C8 _TEXT driver_start . . . . . . . . . . DWord 0000 _TEXT Public SYSCALL follow . . . . . . . . . . . . . DWord 25B8 _TEXT jumps . . . . . . . . . . . . . Text ; local_DS . . . . . . . . . . . . Number 262Eh save_1 . . . . . . . . . . . . . DWord 25D4 _TEXT save_2 . . . . . . . . . . . . . DWord 25D8 _TEXT save_3 . . . . . . . . . . . . . DWord 25DC _TEXT save_4 . . . . . . . . . . . . . DWord 25E0 _TEXT weirdcount . . . . . . . . . . . DWord 25C4 _TEXT 0 Warnings 0 Errors