; ; ╔═════════════════════════════╗ ; ║ ║ TITLE ║ GRAVIS ULTRASOUND MODPLAYER ║ ; ║ ║ ; ╚═════════════════════════════╝ ; ; THIS MODULE PLAYER WAS CODED IN EARLY 1994 ; ; BY SILVIO TURELLO (FRONTMAN/CREW242) ; ; IT IS A COMPLETELY REVISED VERSION OF GUSPLAY 1.5 ; ; BY ROBERT ADOLFSSON (CASCADA) ; ; FEATURES: 4/6/8-CHANNEL-MODS (M.K./FLT4/FLT8/OCTA/8CHN/6CHN) ; ; 5-FX-CHANNELS, FULL MOD-FX SUPPORT, FULL 8/16-BIT DMA SUPPORT ; DOSSEG .MODEL TINY STACKLENGTH = 0100H ASSUME CS:DGROUP, DS:DGROUP; SS:DGROUP ;============================================================================= IRQ1 = 20H IRQ2 = 21H IRQ3 =0A0H IRQ4 =0A1H TIMER0 = 40H PIT1 = 43H UHR_INDEX = 70H UHR_PORT = 71H UHR_STATA = 0AH UHR_STATB = 0BH UHR_STATC = 0CH ;----------------------------------------------------------------------------- NumVoices = 14 ; Number of voices to use StatusPort = 6h ; UltraSound Ports TimerCtrlPort = 8h TimerDataPort = 9h DMASetPort = 0Bh MidiCtrlPort = 100h MidiDataPort = 101h ActiveVoicePort = 102h CommandPort = 103h DataLowPort = 104h DataHighPort = 105h DRAMIOPort = 107h WriteVoiceMode = 00h ; UltraSound Commands SetVoiceFreq = 01h ; Value=Freq/Divisor LoopStartLo = 02h LoopStartHi = 03h SampleEndLo = 04h SampleEndHi = 05h VolRampRate = 06h VolRampStart = 07h VolRampEnd = 08h SetVolume = 09h SampleStartLo = 0Ah SampleStartHi = 0Bh VoiceBalance = 0Ch VolumeCtrl = 0Dh VoicesActive = 0Eh DMACtrl = 41h DMAAddr = 42h DRAMAddrLo = 43h DRAMAddrHi = 44h Initialize = 4Ch ReadVolume = 89h VoicePosLo = 8Ah VoicePosHi = 8Bh ReadVolCtrl = 8Dh Voices14 = 4300 ; Divisors Voices15 = 4000 Voices16 = 3700 Voices17 = 3500 Voices18 = 3300 Voices19 = 3100 Voices20 = 3030 Voices21 = 2800 Voices22 = 2700 Voices23 = 2600 Voices24 = 2500 Voices25 = 2400 Voices26 = 2300 Voices27 = 2200 Voices28 = 2100 Voices29 = 2000 Voices30 = 2000 Voices31 = 1900 Voices32 = 1800 ;----------------------------------------------------------------------------- CHAN_SIZE = 52 CHAN_INFO STRUC SAMP_OFF DD 0 FREQ_VAL DW 0 VOL DW 0 OLD_VOL DW 0 FINE DW 0 REPEAT DW 0 REPLEN DW 0 LEN DW 0 AMIGA DW 0 EFFECT DW 0 VIBRATO_POINT DW 0 OLD_VIBRATO DW 0 PORT_TO DW 0 OLD_PORT_TO DW 0 EFFECT_TIME DW 0 CURR_SAMP DW 0 OLD_SAMP DW 0 ARP DW 0,0,0 ARP_COUNTER DW 0 INST_SET DB 0 BALANCE DB 0 LOOP_ONOFF DW 0 OFFSET_ADD DW 0 TRACK_OFF DW 0 CHAN_INFO ENDS ;============================================================================= .DATA ;============================================================================= PROG_START_SEG DW 0 PROG_END_SEG DW 0 GDDLENGTH DD 0 GDDREST DW 0 GDDHANDLE DW 0 ;GDDMIN DW -1 ;GDDNEW DW 0 ;GDDPOSL DW 0 ;GDDPOSH DW 0 GDDSEG DW 0 BUFSEG DW 0 GDDZEIG DB 0 SAM_CH DB 8 MOD_STAT DB 0 US_MODUS DB 0 SYSTEM DB 0 IRQCOUNT DB 56 COMP_SPEED2 DW 0106H COMP_SPEED3 DW 4006H COMP_SPEED4 DW 0 COMP_SPEED5 DW 1165 HOLD70 LABEL DWORD DW OFFSET CONTROL_CHANNELS, 0 PAN_REGS DB 3,12,12,3,3,12,12,3,3,12,5,10,7,8 ;----------------------------------------------------------------------------- ERROR1_TEXT DB "MOD ERROR",13,10,"$" ERROR2_TEXT DB "FX ERROR",13,10,"$" OUT_TEXT DB "+/- VOLUME",13,10 DB "1 PLAY SAMPLE",13,10 DB "9 INIT REPEAT",13,10 DB "0 MUSIC MODE",13,10,"$" SAMPLE_NAME DB "SAMPLE1.SAM",0 CONFIG_NAME DB "FD.CFG",0 VOL_NAME DB "FM.VOL",0 CFG_TEXT2 DB "DEFAULT MUSIC MODE = ",0 CFG_TEXT3 DB "SOUNDCARD BASE PORT = ",0 CFG_TEXT5 DB "SOUNDCARD DMA NUMBER = ",0 CFG_TEXT7 DB "SYSTEM COMPATIBILITY = ",0 DMA_ADR DB 0,2,4,6,0C0H,0C4H,0C8H,0CCH DMA_CNT DB 1,3,5,7,0C2H,0C6H,0CAH,0CEH DMA_PAGE DB 87H,83H,81H,82H,8FH,8BH,89H,8AH DMA_STAT DB 08H,08H,08H,08H,0D0H,0D0H,0D0H,0D0H DMA_BITS DB 1,2,4,8,1,2,4,8 DMA_MASK DB 0AH,0AH,0AH,0AH,0D4H,0D4H,0D4H,0D4H DMA_MOD DB 0BH,0BH,0BH,0BH,0D6H,0D6H,0D6H,0D6H DMA_FLIP DB 0CH,0CH,0CH,0CH,0D8H,0D8H,0D8H,0D8H DMA_RESET DB 0DH,0DH,0DH,0DH,0DAH,0DAH,0DAH,0DAH DMA_SET_DATA DB 0,1,0,2,0,3,4,5 ;----------------------------------------------------------------------------- ; PROTRACKER VARIABLEN ;----------------------------------------------------------------------------- ALIGN 2 BASE_PORT DW 220H DMA_CHANNEL DW 1 ;DMA 0 IS NO DMA (BYTE-PUSHING) MASTER_VOLUME DW 255 MUSIC_VOLUME DW 255 FX_VOLUME DW 255 MUSIC_VOL DW 255 FX_VOL DW 255 BPM_COUNT DD 0 BPM_SPEED DD 0 COUNTER DW 0 CH_NUMB DW 4 PATT_SPEED DW 0 PATT_COUNT DW 0 PATT_ROW DW 0 PATT_CURRENT DW 0 PATT_BREAK DW 0 ;----------------------------------------------------------------------------- ; MTM - TRACKSTRUKTUR ;----------------------------------------------------------------------------- ALIGN 2 TRACK_NUMBER DW 0 TRACK_INFO DB 8 DUP(0) TRACK_SEG DW 0 TRACKS_OFFSET DW OFFSET TRACK1_DATA, OFFSET TRACK2_DATA, OFFSET TRACK3_DATA DW OFFSET TRACK4_DATA, OFFSET TRACK5_DATA, OFFSET TRACK6_DATA DW OFFSET TRACK7_DATA, OFFSET TRACK8_DATA TRACK1_DATA DB 128 DUP(0) TRACK2_DATA DB 128 DUP(0) TRACK3_DATA DB 128 DUP(0) TRACK4_DATA DB 128 DUP(0) TRACK5_DATA DB 128 DUP(0) TRACK6_DATA DB 128 DUP(0) TRACK7_DATA DB 128 DUP(0) TRACK8_DATA DB 128 DUP(0) ;----------------------------------------------------------------------------- ; MOD - DATEISTRUKTUR ;----------------------------------------------------------------------------- ALIGN 2 PATTERN_SIZE DW 0 PATTERN_SEG DW 0 PATTERN_NUMBER DW 0 IOFFSET DD 31 DUP(0) ISIZE DW 31 DUP(0) IVOLUME DW 31 DUP(0) IFINETUNE DW 31 DUP(0) ILOOP_START DW 31 DUP(0) ILOOP_SIZE DW 31 DUP(0) SONG_SIZE DB 0 SONG_LOOP DB 0 ;----------------------------------------------------------------------------- ; PLAYER - KONTROLLSTRUKTUREN ;----------------------------------------------------------------------------- ALIGN 2 SONG_DATA LABEL BYTE FREQ_TABLE DW 716 DUP(0) ;908 QUEUE_BUFFER DW 128 DUP(0) MOD_NAME DB 128 DUP(0) SAMP_CHANS CHAN_INFO 8 DUP(<>) SAMPLE_CHAN CHAN_INFO <> ;----------------------------------------------------------------------------- ; SINGLE SAMPLE VARIABLES ;----------------------------------------------------------------------------- GUS_MEM DD 0 SAMPLE_ZEIG DW 0 SAMPLE_MEM DD 48 DUP(0) SAMPLE_BIG DW 48 DUP(0) SAM_COUNT DW 5 DUP(0) ;----------------------------------------------------------------------------- ALIGN 2 PattJumps DW OFFSET ARPeggioFix ; 0 DW OFFSET NoPattEFFECT ; 1 DW OFFSET NoPattEFFECT ; 2 DW OFFSET PORT_TOFix ; 3 DW OFFSET VibratoFix ; 4 DW OFFSET NoPattEFFECT ; 5 DW OFFSET NoPattEFFECT ; 6 DW OFFSET NoPattEFFECT ; 7 DW OFFSET NoPattEFFECT ; 8 DW OFFSET SampleOff ; 9 DW OFFSET NoPattEFFECT ; A DW OFFSET PosJump ; B DW OFFSET VOLume ; C DW OFFSET BreakPatt ; D DW OFFSET NoPattEFFECT ; E DW OFFSET SpeedSet ; F EPattJumps DW OFFSET NoPattEFFECT ; 0 DW OFFSET FINEPortUp ; 1 DW OFFSET FINEPortDown ; 2 DW OFFSET NoPattEFFECT ; 3 DW OFFSET NoPattEFFECT ; 4 DW OFFSET NoPattEFFECT ; 5 DW OFFSET NoPattEFFECT ; 6 DW OFFSET NoPattEFFECT ; 7 DW OFFSET PANNING ; 8 DW OFFSET NoPattEFFECT ; 9 DW OFFSET FINEVOLUP ; A DW OFFSET FINEVOLDown ; B DW OFFSET NoPattEFFECT ; C DW OFFSET NoPattEFFECT ; D DW OFFSET NoPattEFFECT ; E DW OFFSET NoPattEFFECT ; F EFFECTJumps DW OFFSET ARPeggio ; 0 DW OFFSET PortUp ; 1 DW OFFSET PortDown ; 2 DW OFFSET PORT_TOTone ; 3 DW OFFSET Vibrato ; 4 DW OFFSET PORT_TOVSlide ; 5 DW OFFSET VibratoVSlide ; 6 DW OFFSET NoEFFECT ; 7 DW OFFSET NoEFFECT ; 8 DW OFFSET NoEFFECT ; 9 DW OFFSET VOLSlide ; A DW OFFSET NoEFFECT ; B DW OFFSET NoEFFECT ; C DW OFFSET NoEFFECT ; D DW OFFSET NoEFFECT ; E DW OFFSET NoEFFECT ; F EEFFECTJumps DW OFFSET NoEFFECT ; 0 DW OFFSET NoEFFECT ; 1 DW OFFSET NoEFFECT ; 2 DW OFFSET NoEFFECT ; 3 DW OFFSET NoEFFECT ; 4 DW OFFSET NoEFFECT ; 5 DW OFFSET NoEFFECT ; 6 DW OFFSET NoEFFECT ; 7 DW OFFSET NoEFFECT ; 8 DW OFFSET RetrigNote ; 9 DW OFFSET NoEFFECT ; A DW OFFSET NoEFFECT ; B DW OFFSET CutNote ; C DW OFFSET DelayNote ; D DW OFFSET NoEFFECT ; E DW OFFSET NoEFFECT ; F SIN_TAB DB 0,25,50,74,98,120,142,162,180,197,212,225,236 DB 244,250,254,255,254,250,244,236,225,212,197,180 DB 162,142,120,98,74,50,25 PERIOD_TABLE LABEL WORD DW 856,808,762,720,678,640,604,570,538,508,480,453 ;C-1 to H-1 Finetune +0. DW 428,404,381,360,339,320,302,285,269,254,240,226 ;C-2 to H-2 Finetune +0. DW 214,202,190,180,170,160,151,143,135,127,120,113 ;C-3 to H-3 Finetune +0. DW 107,101, 95, 90, 85, 80, 75, 71, 67, 63, 60, 56 ;C-4 to H-4 Finetune +0. DW 850,802,757,715,674,637,601,567,535,505,477,450 ;C-1 to H-1 Finetune +1. DW 425,401,379,357,337,318,300,284,268,253,239,225 ;C-2 to H-2 Finetune +1. DW 213,201,189,179,169,159,150,142,134,126,119,113 ;C-3 to H-3 Finetune +1. DW 106,100, 94, 89, 84, 79, 75, 71, 67, 83, 59, 56 ;C-4 to H-4 Finetune +1. DW 844,796,752,709,670,632,597,563,532,502,474,447 ;C-1 to H-1 Finetune +2. DW 422,398,376,355,335,316,298,282,266,251,237,224 ;C-2 to H-2 Finetune +2. DW 211,199,188,177,167,158,149,141,133,125,118,112 ;C-3 to H-3 Finetune +2. DW 105, 99, 94, 88, 83, 79, 74, 70, 66, 62, 59, 56 ;C-4 to H-4 Finetune +2. DW 838,791,746,704,665,628,592,559,528,498,470,444 ;C-1 to H-1 Finetune +3. DW 419,395,373,352,332,314,296,280,264,249,235,222 ;C-2 to H-2 Finetune +3. DW 209,198,187,176,166,157,148,140,132,125,118,111 ;C-3 to H-3 Finetune +3. DW 104, 99, 93, 88, 83, 78, 74, 70, 66, 62, 59, 55 ;C-4 to H-4 Finetune +3. DW 832,785,741,699,660,623,588,555,524,495,467,441 ;C-1 to H-1 Finetune +4. DW 416,392,370,350,330,312,294,278,262,247,233,220 ;C-2 to H-2 Finetune +4. DW 208,196,185,175,165,156,147,139,131,124,117,110 ;C-3 to H-3 Finetune +4. DW 104, 98, 92, 87, 82, 78, 73, 69, 65, 62, 58, 55 ;C-4 to H-4 Finetune +4. DW 826,779,736,694,655,619,584,551,520,491,463,437 ;C-1 to H-1 Finetune +5. DW 413,390,368,347,328,309,292,276,260,245,232,219 ;C-2 to H-2 Finetune +5. DW 206,195,184,174,164,155,146,138,130,123,116,109 ;C-3 to H-3 Finetune +5. DW 103, 97, 92, 87, 82, 77, 73, 69, 65, 61, 58, 54 ;C-4 to H-4 Finetune +5. DW 820,774,730,689,651,614,580,547,516,487,460,434 ;C-1 to H-1 Finetune +6. DW 410,387,365,345,325,307,290,274,258,244,230,217 ;C-2 to H-2 Finetune +6. DW 205,193,183,172,163,154,145,137,129,122,115,109 ;C-3 to H-3 Finetune +6. DW 102, 96, 91, 86, 81, 77, 72, 68, 64, 61, 57, 54 ;C-4 to H-4 Finetune +6. DW 814,768,725,684,646,610,575,543,513,484,457,431 ;C-1 to H-1 Finetune +7. DW 407,384,363,342,323,305,288,272,256,242,228,216 ;C-2 to H-2 Finetune +7. DW 204,192,181,171,161,152,144,136,128,121,114,108 ;C-3 to H-3 Finetune +7. DW 102, 96, 90, 85, 80, 76, 72, 68, 64, 60, 57, 54 ;C-4 to H-4 Finetune +7. DW 907,856,808,762,720,678,640,604,570,538,504,480 ;C-1 to H-1 Finetune -8. DW 453,428,404,381,360,339,320,302,285,269,254,240 ;C-2 to H-2 Finetune -8. DW 226,214,202,190,180,170,160,151,143,135,127,120 ;C-3 to H-3 Finetune -8. DW 113,107,101, 95, 90, 85, 80, 75, 71, 67, 63, 60 ;C-4 to H-4 Finetune -8. DW 900,850,802,757,715,675,636,601,567,535,505,477 ;C-1 to H-1 Finetune -7. DW 450,425,401,379,357,337,318,300,284,268,253,238 ;C-2 to H-2 Finetune -7. DW 225,212,200,189,179,169,159,150,142,134,126,119 ;C-3 to H-3 Finetune -7. DW 112,106,100, 94, 89, 84, 79, 75, 71, 67, 63, 59 ;C-4 to H-4 Finetune -7. DW 894,844,796,752,709,670,632,597,563,532,502,474 ;C-1 to H-1 Finetune -6. DW 447,422,398,376,355,335,316,298,282,266,251,237 ;C-2 to H-2 Finetune -6. DW 223,211,199,188,177,167,158,149,141,133,125,118 ;C-3 to H-3 Finetune -6. DW 111,105, 99, 94, 88, 83, 79, 74, 70, 66, 62, 59 ;C-4 to H-4 Finetune -6. DW 887,838,791,746,704,665,628,592,559,528,498,470 ;C-1 to H-1 Finetune -5. DW 444,419,395,373,352,332,314,296,280,264,249,235 ;C-2 to H-2 Finetune -5. DW 222,209,198,187,176,166,157,148,140,132,125,118 ;C-3 to H-3 Finetune -5. DW 111,104, 99, 93, 88, 83, 78, 74, 70, 66, 62, 59 ;C-4 to H-4 Finetune -5. DW 881,832,785,741,699,660,623,588,555,524,494,467 ;C-1 to H-1 Finetune -4. DW 441,416,392,370,350,330,312,294,278,262,247,233 ;C-2 to H-2 Finetune -4. DW 220,208,196,185,175,165,156,147,139,131,123,117 ;C-3 to H-3 Finetune -4. DW 110,104, 98, 92, 87, 82, 78, 73, 69, 65, 61, 58 ;C-4 to H-4 Finetune -4. DW 875,826,779,736,694,655,619,584,551,520,491,463 ;C-1 to H-1 Finetune -3. DW 437,413,390,368,347,338,309,292,276,260,245,232 ;C-2 to H-2 Finetune -3. DW 219,206,195,184,174,164,155,146,138,130,123,116 ;C-3 to H-3 Finetune -3. DW 109,103, 97, 92, 87, 82, 77, 73, 69, 65, 61, 58 ;C-4 to H-4 Finetune -3. DW 868,820,774,730,689,651,614,580,547,516,487,460 ;C-1 to H-1 Finetune -2. DW 434,410,387,365,345,325,307,290,274,258,244,230 ;C-2 to H-2 Finetune -2. DW 217,205,193,183,172,163,154,145,137,129,122,115 ;C-3 to H-3 Finetune -2. DW 108,102, 96, 91, 86, 81, 77, 72, 68, 64, 61, 57 ;C-4 to H-4 Finetune -2. DW 862,814,768,725,684,646,610,575,543,513,484,457 ;C-1 to H-1 Finetune -1. DW 431,407,384,363,342,323,305,288,272,256,242,228 ;C-2 to H-2 Finetune -1. DW 216,203,192,181,171,161,152,144,136,128,121,114 ;C-3 to H-3 Finetune -1. DW 108,101, 96, 90, 85, 80, 76, 72, 68, 64, 60, 57 ;C-4 to H-4 Finetune -1. GUS_VOL DW 05000H,08FF0H,09FF0H,0A800H,0AFF0H,0B400H,0B800H,0BC00H DW 0BFF0H,0C200H,0C400H,0C600H,0C800H,0CA00H,0CC00H,0CE00H DW 0CFF0H,0D100H,0D200H,0D300H,0D400H,0D500H,0D600H,0D700H DW 0D800H,0D900H,0DA00H,0DB00H,0DC00H,0DD00H,0DE00H,0DF00H DW 0DFF0H,0E080H,0E100H,0E180H,0E200H,0E280H,0E300H,0E380H DW 0E400H,0E480H,0E500H,0E580H,0E600H,0E680H,0E700H,0E780H DW 0E800H,0E880H,0E900H,0E980H,0EA00H,0EA80H,0EB00H,0EB80H DW 0EC00H,0EC80H,0ED00H,0ED80H,0EE00H,0EE80H,0EF00H,0EF80H DW 0F800H ;SINGLE SAMPLE MAX VOL > SONG MAX VOL ;----------------------------------------------------------------------------- PROG_END LABEL BYTE ;MUST BE LAST ROW IN DATA SEGMENT! ;----------------------------------------------------------------------------- .386 .CODE ORG 100H ;============================================================================= MAIN PROC NEAR JMP MAIN_CONT ;0100 RETF CALL CONFIG_INIT ;0104 RETF CALL LOAD_MOD ;0108 RETF CALL PLAY_MUSIC ;010C RETF CALL STOP_MUSIC ;0110 RETF CALL END_MUSIC ;0114 RETF CALL LOAD_SAMPLE ;0118 RETF CALL PLAY_SAMPLE ;011C RETF CALL END_SAMPLE ;0120 RETF JMP NOFUNC ;0124 NOFUNC: RETF CALL GET_VOLUME ;0128 RETF CALL SET_VOLUME ;012C RETF CALL SET_SONGLOOP ;0130 RETF CALL GET_SONGPOSITION ;0134 RETF CALL SET_SONGPOSITION ;0138 RETF CALL GET_SONGMOD ;013C RETF CALL SET_SONGMOD ;0140 RETF CALL US_OFF ;0144 RETF CALL INIT_DEVICE ;0148 RETF CALL LOAD_MOD_FROM_VOL ;014C RETF CALL LOAD_SAMPLE_FROM_VOL ;0150 RETF MAIN ENDP ;============================================================================= MAIN_CONT: MOV AX,CS ;DS SET MOV DS,AX MOV PROG_START_SEG,ES ;PROGRAMM START MOV AX,SS ;AND -END SET MOV BX,OFFSET PROG_END ADD BX,STACKLENGTH MOV SP,BX SHR BX,4 INC BX ADD AX,BX MOV PROG_END_SEG,AX XOR BX,BX GL1: MOV AL,ES:[82H+BX] OR AL,AL JZ SHORT GL2 CMP AL,20H JE SHORT GL2 CMP AL,0DH JE SHORT GL2 MOV [MOD_NAME+BX],AL INC BX CMP BX,40H JB GL1 GL2: OR BX,BX JZ GMEND XOR AL,AL MOV [MOD_NAME+BX],0 MOV BX,PROG_END_SEG ;RESIZE OWN ALLOCATION SUB BX,PROG_START_SEG MOV ES,PROG_START_SEG MOV AH,4AH INT 21H ;----------------------------------------------------------------------------- ; INITIALIZING & STARTING ; MOV AL,255 ;SET MAXIMUM VOLUME ; MOV BL,AL ; MOV BH,AL ; CALL SET_VOLUME CALL CONFIG_INIT ;GET CONFIG MOV DX,OFFSET MOD_NAME ;FIRST, TRY LOADING CALL LOAD_MOD JNC SHORT GM1 MOV AH,9 MOV DX,OFFSET ERROR1_TEXT INT 21H JMP SHORT GM4 GM1: MOV DX,OFFSET SAMPLE_NAME ;GET SAMPLE MOV CL,80H ;PC-SAMPLE CALL LOAD_SAMPLE JNC SHORT GM2 MOV AH,9 MOV DX,OFFSET ERROR2_TEXT INT 21H GM2: CALL PLAY_MUSIC ;TRY STARTING ;----------------------------------------------------------------------------- ; THIS COULD BE THE MAIN ROUTINE MOV AH,9 MOV DX,OFFSET OUT_TEXT INT 21H LM1: XOR AH,AH INT 16H CMP AL,27 JE SHORT GM5 CMP AL,"+" JNE SHORT G1 CALL GET_VOLUME INC AL CALL SET_VOLUME JMP LM1 G1: CMP AL,"-" JNE SHORT G2 CALL GET_VOLUME DEC AL CALL SET_VOLUME JMP LM1 G2: CMP AL,"9" JNE SHORT G3 MOV AL,0 CALL SET_SONGLOOP JMP LM1 G3: CMP AL,"0" JNE SHORT G4 INC US_MODUS AND US_MODUS,3 JMP LM1 G4: CMP AL,"1" JNE LM1 XOR BX,BX ;HANDLE MOV CX,22222 ;FREQUENCE CALL PLAY_SAMPLE JMP LM1 ;----------------------------------------------------------------------------- ; CUTTING OFF GM5: CALL STOP_MUSIC ;STOP MUSIC CALL END_SAMPLE ;UNLOAD SAMPLES GM4: CALL END_MUSIC ;UNLOAD MUSIC GMEND: MOV AX,4C00H ;DOS INT 21H ;============================================================================= ;============================================================================= ALIGN 2 CONTROL_CHANNELS PROC NEAR PUSH EAX EBX ECX EDX ESI EDI EBP PUSH DS ES CS POP DS CMP SYSTEM,0 JNE SHORT WT6 MOV AL,UHR_STATC OUT UHR_INDEX,AL JMP SHORT WT1 WT1: JMP SHORT WT2 WT2: IN AL,UHR_PORT WT6: MOV AL,20H OUT IRQ3,AL OUT IRQ1,AL STI INC COUNTER MOV AX,WORD PTR [BPM_SPEED+2] ADD WORD PTR [BPM_COUNT+2],AX MOV AX,WORD PTR [BPM_SPEED] ADC WORD PTR [BPM_COUNT],AX JC JumpPattern CMP COUNTER,4 JE SHORT ClearNotes CMP COUNTER,5 JE SetNotes JMP EndPattern ;----------------------------------------------------------------------------- ClearNotes: CMP MOD_STAT,0 JE SHORT NOT_FINISHED MOV PATT_CURRENT,0 MOV DI,OFFSET SAMP_CHANS MOV CX,CH_NUMB FINISH: MOV [DI.OLD_VOL],0 MOV [DI.VOL],0 MOV [DI.AMIGA],0 MOV [DI.FREQ_VAL],0 ADD DI,CHAN_SIZE LOOP FINISH NOT_FINISHED: MOV DI,OFFSET SAMP_CHANS MOV CX,CH_NUMB MOV DX,BASE_PORT ADD DX,CommandPort StopVoices: DEC DX MOV AL,BYTE PTR CH_NUMB SUB AL,CL OUT DX,AL INC DX CMP [DI.INST_SET],2 JE SHORT VoiceOff1 CMP [DI.INST_SET],1 JE SHORT VoiceOff2 CMP [DI.OFFSET_ADD],0 JNE SHORT VoiceOff1 JMP SHORT NoVoiceOff VoiceOff2: MOV AX,[DI.CURR_SAMP] CMP AX,[DI.OLD_SAMP] JNE SHORT VoiceOff1 JMP SHORT NoVoiceOff VoiceOff1: MOV AX,[DI.OLD_VOL] MOV [DI.OLD_VOL],0 MOV BP,GUS_VOL MOV BX,MUSIC_VOL MUL BL MOVZX BX,AH SHL BX,1 MOV BX,[GUS_VOL+BX] TEST US_MODUS,2 JZ SHORT WITH_SOUND1 MOV BX,10000 MOV BP,BX WITH_SOUND1: CALL SEND_RAMP NoVoiceOff: ADD DI,CHAN_SIZE LOOP StopVoices JMP EndPattern ;----------------------------------------------------------------------------- SetNotes: MOV COUNTER,1 MOV DI,OFFSET SAMP_CHANS MOV CX,CH_NUMB MOV DX,BASE_PORT ADD DX,CommandPort ChangeSamps: DEC DX MOV AL,BYTE PTR CH_NUMB SUB AL,CL OUT DX,AL INC DX MOV AL,[DI.BALANCE] ;PANNING MOV AH,AL SHR AL,4 AND AH,0FH CMP AL,AH JE SHORT NO_PANNING MOV AL,AH SHL AL,4 OR AL,AH MOV [DI.BALANCE],AL MOV AL,VoiceBalance OUT DX,AL ADD DX,2 MOV AL,AH OUT DX,AL SUB DX,2 NO_PANNING: CMP [DI.INST_SET],2 JE SHORT SampChange1 CMP [DI.INST_SET],1 JE SHORT SampChange2 CMP [DI.OFFSET_ADD],0 JNE SHORT ChangeOffset JMP SHORT NoChangeSamp ChangeOffset: CALL SEND_SAMPLE_START JMP SHORT NoChangeSamp SampChange1: MOV AH,3 CALL SEND_WRITE_VOICE CALL WAIT_PORT CALL SEND_SAMPLE_START MOV AX,[DI.OLD_SAMP] CMP AX,[DI.CURR_SAMP] JE SHORT NoChangeSamp CALL SEND_SAMPLE_END CALL SEND_SAMPLE_LOOP MOV AH,3 CALL SEND_WRITE_VOICE JMP SHORT NoChangeSamp SampChange2: MOV AX,[DI.OLD_SAMP] CMP AX,[DI.CURR_SAMP] JE SHORT NoChangeSamp MOV AL,VoicePosLo OUT DX,AL INC DX IN AX,DX MOV BX,AX DEC DX MOV AL,VoicePosHi OUT DX,AL INC DX IN AX,DX DEC DX XCHG AX,BX SHL AX,7 SHR BX,9 AND BX,7FH OR AX,BX MOV BX,[DI.OLD_SAMP] DEC BX SHL BX,2 SUB AX,WORD PTR [IOFFSET+BX] MOV BX,AX CMP BX,[DI.LEN] JB SHORT NoFixStart MOV BX,[DI.LEN] DEC BX NoFixStart: CMP [DI.OFFSET_ADD],0 JNE SHORT NoOffsetEff MOV [DI.OFFSET_ADD],BX NoOffsetEff: CALL SEND_SAMPLE_START CALL SEND_SAMPLE_END CALL SEND_SAMPLE_LOOP MOV AH,BYTE PTR [DI.LOOP_ONOFF] CALL SEND_WRITE_VOICE CALL WAIT_PORT NoChangeSamp: MOV AX,[DI.OLD_VOL] MOV BX,MUSIC_VOL MUL BL MOVZX BX,AH SHL BX,1 MOV BX,[GUS_VOL+BX] MOV AX,[DI.VOL] MOV BP,MUSIC_VOL MUL BP MOVZX BP,AH SHL BP,1 MOV BP,CS:[GUS_VOL+BP] TEST US_MODUS,2 JZ SHORT WITH_SOUND2 MOV BX,10000 MOV BP,BX WITH_SOUND2: MOV DX,BP MOV DL,BH CMP DL,DH JNE SHORT SetVOL MOV DX,BASE_PORT ADD DX,CommandPort MOV AL,VOLumeCtrl OUT DX,AL ADD DX,2 MOV AL,3 OUT DX,AL SUB DX,2 MOV AL,SetVOLume OUT DX,AL MOV AX,BP INC DX OUT DX,AX DEC DX JMP SHORT NoSetVOL SetVOL: CALL SEND_RAMP NoSetVOL: MOV AL,SetVoiceFreq OUT DX,AL INC DX MOV AX,[DI.FREQ_VAL] OUT DX,AX DEC DX SHL COUNTER,1 ADD DI,CHAN_SIZE DEC CX JNZ ChangeSamps MOV DI,OFFSET SAMP_CHANS MOV CX,CH_NUMB StartVoices: DEC DX MOV AL,BYTE PTR CH_NUMB SUB AL,CL OUT DX,AL INC DX CMP [DI.INST_SET],2 JNE SHORT NoVoiceStart MOV AH,BYTE PTR [DI.LOOP_ONOFF] CALL SEND_WRITE_VOICE CALL WAIT_PORT NoVoiceStart: MOV [DI.INST_SET],0 MOV [DI.OFFSET_ADD],0 ADD DI,CHAN_SIZE LOOP StartVoices JMP EndPattern ;----------------------------------------------------------------------------- JumpPattern: MOV COUNTER,0 DEC PATT_COUNT JZ DoPattern MOV DI,OFFSET SAMP_CHANS MOV CX,CH_NUMB EFFECTLoop: MOV AX,[DI.VOL] MOV [DI.OLD_VOL],AX INC [DI.EFFECT_TIME] ADD [DI.ARP_COUNTER],2 CMP [DI.ARP_COUNTER],6 JB SHORT NoWrapARP MOV [DI.ARP_COUNTER],0 NoWrapARP: MOV AX,[DI.EFFECT] OR AX,AX JZ NoEFFECT MOVZX BX,AL CMP BL,0EH JE SHORT DoEEFFECTs SHL BX,1 JMP [EFFECTJumps+BX] DoEEFFECTs: MOV BL,AH AND AH,0FH SHR BL,4 SHL BX,1 JMP [EEFFECTJumps+BX] ARPeggio: MOV BX,[DI.ARP_COUNTER] MOV BX,[DI.ARP+BX] SHL BX,1 MOV AX,[FREQ_TABLE+BX] MOV [DI.FREQ_VAL],AX JMP NoEFFECT PortUp: XCHG AL,AH XOR AH,AH MOV SI,[DI.FINE] MOV BP,[PERIOD_TABLE+47*2+SI] ;35 MOV BX,[DI.AMIGA] SUB BX,AX JNC SHORT NoFix1 MOV BX,BP NoFix1: CMP BX,BP JAE SHORT NotSmall1 MOV BX,BP NotSmall1: MOV [DI.AMIGA],BX SHL BX,1 MOV AX,[FREQ_TABLE+BX] MOV [DI.FREQ_VAL],AX JMP NoEFFECT PortDown: XCHG AL,AH XOR AH,AH MOV SI,[DI.FINE] MOV BP,[PERIOD_TABLE+SI] MOV BX,[DI.AMIGA] ADD BX,AX CMP BX,BP JBE SHORT NotBig1 MOV BX,BP NotBig1: MOV [DI.AMIGA],BX SHL BX,1 MOV AX,[FREQ_TABLE+BX] MOV [DI.FREQ_VAL],AX JMP NoEFFECT PORT_TOTone: XCHG AL,AH XOR AH,AH GOTO_PORT_TO: MOV DX,[DI.PORT_TO] MOV BX,[DI.AMIGA] CMP BX,DX JAE SHORT NoPORT_TOUp ADD BX,AX CMP BX,DX JBE SHORT NoPORT_TOUp MOV [DI.AMIGA],DX NoPORT_TOUp: CMP BX,DX JBE SHORT NoPORT_TODown SUB BX,AX JNC SHORT NoPORT_TOError MOV BX,DX NoPORT_TOError: CMP BX,DX JAE SHORT NoPORT_TODown MOV BX,DX NoPORT_TODown: MOV [DI.AMIGA],BX SHL BX,1 MOV AX,[FREQ_TABLE+BX] MOV [DI.FREQ_VAL],AX JMP NoEFFECT Vibrato: MOV SI,[DI.FINE] MOV BP,[PERIOD_TABLE+47*2+SI] ;35 MOV SI,[PERIOD_TABLE+SI] MOV DL,AH AND AH,0F0H SHR AH,2 AND DL,0FH MOV BL,BYTE PTR [DI.VIBRATO_POINT] ADD BL,AH MOV BYTE PTR [DI.VIBRATO_POINT],BL SHR BL,2 AND BX,1Fh MOV AL,[SIN_TAB+BX] MUL DL ROL AX,1 XCHG AL,AH AND AH,1 TEST BYTE PTR [DI.VIBRATO_POINT],80H JNE SHORT VibUp1 NEG AX VibUp1: ADD AX,[DI.AMIGA] CMP AX,BP JAE SHORT NoHighVibrato1 MOV AX,BP NoHighVibrato1: CMP AX,SI JBE SHORT NoLowVibrato1 MOV AX,SI NoLowVibrato1: SHL AX,1 MOV BX,AX MOV AX,[FREQ_TABLE+BX] MOV [DI.FREQ_VAL],AX JMP NoEFFECT PORT_TOVSlide: MOV AL,AH AND AH,0FH SHR AL,4 SUB AH,AL MOV AL,BYTE PTR [DI.VOL] SUB AL,AH JNS SHORT NoSlideLow2 XOR AL,AL NoSlideLow2: CMP AL,40H JBE SHORT NoSlideHigh2 MOV AL,40H NoSlideHigh2: MOV BYTE PTR [DI.VOL],AL MOV AX,[DI.OLD_PORT_TO] JMP GOTO_PORT_TO VibratoVSlide: MOV AL,AH AND AH,0FH SHR AL,4 SUB AH,AL MOV AL,BYTE PTR [DI.VOL] SUB AL,AH JNS SHORT NoSlideLow3 XOR AL,AL NoSlideLow3: CMP AL,40H JBE SHORT NoSlideHigh3 MOV AL,40H NoSlideHigh3: MOV BYTE PTR [DI.VOL],AL JMP Vibrato VOLSlide: MOV AL,AH AND AH,0FH SHR AL,4 OR AL,AL JZ SHORT NoVOLSlideUp NEG AL MOV AH,AL NoVOLSlideUp: MOV AL,BYTE PTR [DI.VOL] SUB AL,AH JNS SHORT NoSlideLow1 XOR AL,AL NoSlideLow1: CMP AL,40H JBE SHORT NoSlideHigh1 MOV AL,40H NoSlideHigh1: MOV BYTE PTR [DI.VOL],AL JMP SHORT NoEFFECT RetrigNote: CMP AH,BYTE PTR [DI.EFFECT_TIME] JNE SHORT NoRetrig MOV [DI.EFFECT_TIME],0 MOV [DI.INST_SET],2 NoRetrig: JMP SHORT NoEFFECT CutNote: CMP AH,BYTE PTR [DI.EFFECT_TIME] JNE SHORT NoCutNote MOV [DI.AMIGA],0 MOV [DI.FREQ_VAL],0 NoCutNote: JMP SHORT NoEFFECT DelayNote: CMP AH,BYTE PTR [DI.EFFECT_TIME] JNE SHORT NoDelayNote MOV [DI.INST_SET],2 MOV [DI.VIBRATO_POINT],0 MOV BX,[DI.PORT_TO] MOV [DI.AMIGA],BX SHL BX,1 MOV BX,[FREQ_TABLE+BX] MOV [DI.FREQ_VAL],BX NoDelayNote: JMP SHORT NoEFFECT NoEFFECT: ADD DI,CHAN_SIZE DEC CX JNZ EFFECTLoop JMP EndPattern ;----------------------------------------------------------------------------- DoPattern: MOV AX,PATT_SPEED MOV PATT_COUNT,AX CMP PATT_ROW,64 JB SHORT NoPatternWrap MOV AX,PATT_CURRENT CMP AL,SONG_SIZE JB SHORT NoTrackWrap MOV AL,SONG_LOOP CMP AL,SONG_SIZE JB SHORT NoRestart MOV MOD_STAT,3 XOR AL,AL NoRestart: MOV PATT_CURRENT,AX NoTrackWrap: MOV BX,PATT_CURRENT INC PATT_CURRENT MOV DI,OFFSET SAMP_CHANS XOR SI,SI NewTracks: PUSH SI SHL SI,1 MOV SI,[TRACKS_OFFSET+SI] MOV AX,PATT_BREAK MOV PATT_ROW,AX SHL AX,2 ADD AH,[SI+BX] MOV [DI.TRACK_OFF],AX POP SI ADD DI,CHAN_SIZE INC SI CMP SI,CH_NUMB JB NewTracks MOV PATT_BREAK,0 NoPatternWrap: MOV ES,TRACK_SEG MOV DI,OFFSET SAMP_CHANS MOV CX,CH_NUMB PattLoop: MOV SI,[DI.TRACK_OFF] MOV AX,[DI.VOL] MOV [DI.OLD_VOL],AX MOV BH,ES:[SI] ; New Sample MOV BL,ES:[SI+2] AND BH,0F0H SHR BL,4 ADD BL,BH JZ SHORT NoNewSample MOV BH,BYTE PTR [DI.CURR_SAMP] MOV BYTE PTR [DI.OLD_SAMP],BH MOV BYTE PTR [DI.CURR_SAMP],BL XOR BH,BH DEC BX SHL BX,1 MOV AX,[IVOLUME+BX] MOV [DI.VOL],AX MOV [DI.INST_SET],1 SHL BX,1 MOV EAX,[IOFFSET+BX] MOV [DI.SAMP_OFF],EAX SHR BX,1 MOV AX,[IFINETUNE+BX] SHL AX,5 MOV [DI.FINE],AX SHL AX,1 ADD [DI.FINE],AX MOV [DI.LOOP_ONOFF],0 MOV AX,[ISIZE+BX] MOV [DI.LEN],AX MOV AX,[ILOOP_START+BX] MOV [DI.REPEAT],AX MOV AX,[ILOOP_SIZE+BX] MOV [DI.REPLEN],AX CMP AX,2 JBE SHORT NoNewSample MOV [DI.LOOP_ONOFF],8 MOV AX,[DI.REPEAT] ADD AX,[DI.REPLEN] CMP AX,[DI.LEN] JA SHORT NoNewSample MOV [DI.LEN],AX NoNewSample: MOV BX,ES:[SI] XCHG BL,BH AND BX,0FFFH JZ SHORT NoNewNote CALL GET_PERIOD_INDEX ADD BX,[DI.FINE] MOV BX,[PERIOD_TABLE+BX] MOV [DI.PORT_TO],BX MOV AX,ES:[SI+2] AND AL,0FH AND AH,0F0H CMP AL,3 JE SHORT NoNewNote CMP AL,5 JE SHORT NoNewNote CMP AX,0D00EH JNE SHORT NewNote MOV AL,ES:[SI+2] OR AL,AL JZ SHORT NewNote MOV [DI.INST_SET],0 JMP SHORT NoNewNote NewNote: MOV [DI.INST_SET],2 MOV [DI.VIBRATO_POINT],0 MOV [DI.AMIGA],BX SHL BX,1 MOV BX,[FREQ_TABLE+BX] MOV [DI.FREQ_VAL],BX NoNewNote: MOV [DI.ARP_COUNTER],0 MOV AX,ES:[SI+2] AND AL,0FH MOV [DI.EFFECT],AX CMP AL,7 JB SHORT NoSetOldFreq MOV BX,AX AND BH,0F0H CMP BX,0C00EH JE SHORT NoSetOldFreq CMP BX,0D00EH JE SHORT NoSetOldFreq MOV BX,[DI.AMIGA] SHL BX,1 MOV BX,[FREQ_TABLE+BX] MOV [DI.FREQ_VAL],BX NoSetOldFreq: MOVZX BX,AL CMP BL,0EH JE SHORT DoEPattEFFECTs SHL BX,1 JMP [PattJumps+BX] DoEPattEFFECTs: MOV BL,AH AND AH,0FH SHR BL,4 SHL BX,1 JMP [EPattJumps+BX] ARPeggioFix: MOV BX,[DI.AMIGA] CALL GET_PERIOD_INDEX MOV BP,BX ADD BX,[DI.FINE] MOV DX,[PERIOD_TABLE+BX] MOV [DI.ARP],DX XCHG AL,AH XOR AH,AH MOV DX,AX SHR DX,4 AND AX,0FH SHL DX,1 SHL AX,1 MOV BX,BP ADD BX,DX CMP BX,94 JBE SHORT NoWrapARP1 MOV BX,94 NoWrapARP1: ADD BX,[DI.FINE] MOV DX,[PERIOD_TABLE+BX] MOV [DI.ARP+2],DX MOV BX,BP ADD BX,AX CMP BX,94 JBE SHORT NoWrapARP2 MOV BX,94 NoWrapARP2: ADD BX,[DI.FINE] MOV DX,[PERIOD_TABLE+BX] MOV [DI.ARP+4],DX JMP NoPattEFFECT PORT_TOFix: OR AH,AH JNZ SHORT NoPortPekFix MOV AH,BYTE PTR [DI.OLD_PORT_TO] NoPortPekFix: MOV BYTE PTR [DI.OLD_PORT_TO],AH MOV BYTE PTR [DI.EFFECT+1],AH JMP NoPattEFFECT VibratoFix: MOV AL,AH AND AL,0FH AND AH,0F0H OR AL,AL JNZ SHORT NoVibratoFix1 MOV AL,BYTE PTR [DI.OLD_VIBRATO] NoVibratoFix1: OR AH,AH JNZ SHORT NoVibratoFix2 MOV AH,BYTE PTR [DI.OLD_VIBRATO+1] NoVibratoFix2: MOV BYTE PTR [DI.OLD_VIBRATO],AL MOV BYTE PTR [DI.OLD_VIBRATO+1],AH OR AL,AH MOV BYTE PTR [DI.EFFECT+1],AL JMP NoPattEFFECT SampleOff: XOR AL,AL CMP AX,[DI.LEN] JB SHORT NoFixOffset MOV AX,[DI.LEN] DEC AX NoFixOffset: MOV [DI.OFFSET_ADD],AX JMP NoPattEFFECT PosJump: MOV [PATT_ROW],63 MOV BYTE PTR [PATT_CURRENT],AH JMP NoPattEFFECT VOLume: CMP AH,40H JBE SHORT NoFixVOL1 MOV AH,40H NoFixVOL1: MOV BYTE PTR [DI.VOL],AH JMP NoPattEFFECT BreakPatt: MOV [PATT_ROW],63 CMP AH,64H JB SHORT NoFixBreak MOV AH,63H NoFixBreak: MOV AL,AH AND AL,0FH SHR AH,4 SHL AH,1 MOV BYTE PTR [PATT_BREAK],AL ADD BYTE PTR [PATT_BREAK],AH SHL AH,2 ADD BYTE PTR [PATT_BREAK],AH JMP NoPattEFFECT SpeedSet: OR AH,AH JZ NoPattEFFECT CMP AH,1FH JBE SHORT UsualSpeed XCHG AL,AH XOR AH,AH SHL AX,1 MOV BL,5 DIV BL ; EFFECTS 50Hz MOV DL,AL XOR DH,DH ; PATT_SPEED Hz=2*BPM/5 XOR AX,AX MOV BX,1024 DIV BX MOV WORD PTR BPM_SPEED,AX XOR AX,AX DIV BX MOV WORD PTR BPM_SPEED+2,AX JMP SHORT NoPattEFFECT UsualSpeed: MOV BYTE PTR [PATT_SPEED],AH MOV BYTE PTR [PATT_COUNT],AH JMP SHORT NoPattEFFECT FINEPortUp: XCHG AL,AH XOR AH,AH SUB [DI.AMIGA],AX MOV BX,[DI.FINE] MOV BX,[PERIOD_TABLE+47*2+BX] ;35 CMP [DI.AMIGA],BX JAE SHORT NoFixFINEUp MOV [DI.AMIGA],BX NoFixFINEUp: JMP SHORT NoPattEFFECT FINEPortDown: XCHG AL,AH XOR AH,AH ADD [DI.AMIGA],AX MOV BX,[DI.FINE] MOV BX,[PERIOD_TABLE+BX] CMP [DI.AMIGA],BX JBE SHORT NoFixFINEDown MOV [DI.AMIGA],BX NoFixFINEDown: JMP SHORT NoPattEFFECT PANNING: AND [DI.BALANCE],0F0H OR [DI.BALANCE],AH JMP SHORT NoPattEFFECT FINEVOLUP: ADD BYTE PTR [DI.VOL],AH CMP BYTE PTR [DI.VOL],40H JBE SHORT NoFixFINEVOLUp MOV BYTE PTR [DI.VOL],40H NoFixFINEVOLUp: JMP SHORT NoPattEFFECT FINEVOLDown: SUB BYTE PTR [DI.VOL],AH JNC SHORT NoFixFINEVOLDown MOV BYTE PTR [DI.VOL],0 NoFixFINEVOLDown: JMP SHORT NoPattEFFECT NoPattEFFECT: ADD [DI.TRACK_OFF],4 MOV [DI.EFFECT_TIME],0 ADD DI,CHAN_SIZE DEC CX JNZ PattLoop INC PATT_ROW EndPattern: CALL CONTROL_SAMPLE POP ES DS POP EBP EDI ESI EDX ECX EBX EAX CMP CS:SYSTEM,0 JE SHORT WT7 DEC CS:IRQCOUNT JNZ SHORT WT7 MOV CS:IRQCOUNT,56 JMP DWORD PTR CS:[HOLD70] WT7: IRET CONTROL_CHANNELS ENDP ;----------------------------------------------------------------------------- GET_PERIOD_INDEX PROC NEAR MOV BP,BX XOR BH,BH MOV DX,6000H ;BINARY SEARCH LGP1: MOV BL,DL ADD BL,DH SHR BL,1 AND BL,0FEH JZ SHORT GGP2 CMP BL,94 JE SHORT GGP2 CMP BP,[PERIOD_TABLE+BX] JAE SHORT GGP1 MOV DL,BL JMP LGP1 GGP1: MOV DH,BL CMP BP,[PERIOD_TABLE-2+BX] JAE LGP1 ;FOUND MOV DX,[PERIOD_TABLE-2+BX] ;GET NEAREST PERIOD SUB DX,BP SUB BP,[PERIOD_TABLE+BX] CMP DX,BP JAE SHORT GGP2 SUB BX,2 GGP2: RET GET_PERIOD_INDEX ENDP ;----------------------------------------------------------------------------- CONTROL_SAMPLE PROC NEAR MOV CL,8 XOR SI,SI LCS1: CMP [SAM_COUNT+SI],0 JE SHORT GCS1 JL SHORT GCS2 DEC [SAM_COUNT+SI] JNZ SHORT GCS1 MOV [SAM_COUNT+SI],-256 ;RAMP DOWN SAMPLE MOV DX,BASE_PORT ADD DX,CommandPort DEC DX MOV AL,CL OUT DX,AL INC DX MOV BP,GUS_VOL MOV BX,FX_VOL INC BX SHR BX,2 CMP BL,40H JBE SHORT FIXVOL MOV BL,40H FIXVOL: SHL BX,1 MOV BX,[GUS_VOL+BX] CALL SEND_RAMP JMP SHORT GCS1 GCS2: INC [SAM_COUNT+SI] ;STOP SAMPLE JNZ SHORT GCS1 MOV DX,BASE_PORT ADD DX,ActiveVoicePort MOV AL,CL OUT DX,AL INC DX MOV AL,WriteVoiceMode OUT DX,AL ADD DX,2 MOV AL,3 ;Voice Off OUT DX,AL SUB DX,2 MOV AL,VolumeCtrl OUT DX,AL ADD DX,2 MOV AL,3 ;Ramp Off OUT DX,AL SUB DX,3 GCS1: INC SI INC SI INC CL CMP CL,13 JB LCS1 RET CONTROL_SAMPLE ENDP ;============================================================================= ;============================================================================= ; ; ULTRASOUND INIT ; ;============================================================================= INIT_DEVICE PROC NEAR PUSH CS POP DS CLI MOV BX,BASE_PORT ;Init the UltraSound MOV CX,BX ADD BX,CommandPort ADD CX,DataHighPort MOV DX,BX MOV AL,Initialize OUT DX,AL MOV DX,CX MOV AL,0 OUT DX,AL MOV DX,BASE_PORT MOV AH,10 LID1: IN AL,DX DEC AH JNZ LID1 MOV DX,BX MOV AL,Initialize OUT DX,AL MOV DX,CX MOV AL,1 OUT DX,AL MOV DX,BASE_PORT MOV AH,10 LID2: IN AL,DX DEC AH JNZ LID2 MOV DX,BX MOV AL,DMACtrl OUT DX,AL MOV DX,CX MOV AL,0 OUT DX,AL MOV DX,BX MOV AL,45H OUT DX,AL MOV DX,CX MOV AL,0 OUT DX,AL MOV DX,BX MOV AL,49H OUT DX,AL MOV DX,CX MOV AL,0 OUT DX,AL MOV DX,BX MOV AL,VoicesActive OUT DX,AL MOV DX,CX MOV AL,NumVoices DEC AL OR AL,0C0H OUT DX,AL MOV DX,BASE_PORT ;Clear IRQs ADD DX,StatusPort IN AL,DX MOV DX,BX MOV AL,DMACtrl OUT DX,AL MOV DX,CX IN AL,DX MOV DX,BX MOV AL,49H OUT DX,AL MOV DX,CX IN AL,DX MOV DX,BX MOV AL,8FH OUT DX,AL MOV DX,CX IN AL,DX PUSH CX MOV CX,32 VoiceClearLoop: MOV DX,BASE_PORT ADD DX,ActiveVoicePort MOV AL,CL DEC AL OUT DX,AL INC DX MOV AL,0 OUT DX,AL ADD DX,2 MOV AL,3 ;Voice Off OUT DX,AL SUB DX,2 MOV AL,0DH OUT DX,AL ADD DX,2 MOV AL,3 ;Ramp Off OUT DX,AL MOV DX,BASE_PORT MOV AH,10 LID3: IN AL,DX DEC AH JNZ LID3 LOOP VoiceClearLoop POP CX CMP DMA_CHANNEL,0 ;NO DMA JE SHORT LID5 MOV DX,BASE_PORT ;SETUP FOR DIGITAL ASIC ADD DX,0FH MOV AL,5 OUT DX,AL SUB DX,0FH MOV AL,3 OUT DX,AL ADD DX,DMASetPort MOV AL,0 OUT DX,AL ADD DX,0FH-DMASetPort OUT DX,AL SUB DX,0FH MOV AL,3 ;SET DMA CHANNEL OUT DX,AL ADD DX,DMASetPort PUSH BX MOV BX,DMA_CHANNEL MOV AL,[DMA_SET_DATA+BX] POP BX OR AL,0C0H ;SET DMA OUT DX,AL SUB DX,DMASetPort PUSH AX MOV AL,43H OUT DX,AL ADD DX,DMASetPort MOV AL,45H ;SET IRQ11 OUT DX,AL SUB DX,DMASetPort MOV AL,3 OUT DX,AL ADD DX,DMASetPort POP AX AND AL,7FH ;SET DMA OUT DX,AL SUB DX,DMASetPort MOV AL,43H OUT DX,AL ADD DX,DMASetPort MOV AL,45H ;SET IRQ11 OUT DX,AL ADD DX,ActiveVoicePort-DMASetPort MOV AL,0 OUT DX,AL SUB DX,ActiveVoicePort MOV AL,9 ;SETUP DMA LATCH OUT DX,AL ADD DX,ActiveVoicePort MOV AL,0 OUT DX,AL LID5: MOV DX,BX ;Clear IRQs MOV AL,DMACtrl OUT DX,AL MOV DX,CX IN AL,DX MOV DX,BX MOV AL,49H OUT DX,AL MOV DX,CX IN AL,DX MOV DX,BX MOV AL,8FH OUT DX,AL MOV DX,CX IN AL,DX MOV DX,BX MOV AL,Initialize OUT DX,AL MOV DX,CX MOV AL,3 OUT DX,AL MOV CX,NumVoices SetRampRateLoop: MOV DX,BASE_PORT ADD DX,ActiveVoicePort MOV AL,NumVoices SUB AL,CL OUT DX,AL MOV DX,BASE_PORT ADD DX,CommandPort MOV AL,VOLRampRate OUT DX,AL MOV AL,00111111B MOV DX,BASE_PORT ADD DX,DataHighPort OUT DX,AL MOV DX,BASE_PORT ADD DX,CommandPort MOV AL,SetVOLume OUT DX,AL MOV AX,GUS_VOL MOV DX,BASE_PORT ADD DX,DataLowPort OUT DX,AX MOV DX,BASE_PORT MOV AH,10 LID4: IN AL,DX DEC AH JNZ LID4 LOOP SetRampRateLoop STI RET INIT_DEVICE ENDP ;----------------------------------------------------------------------------- SEND_SAMPLE_START PROC NEAR MOV AL,SampleStartLo OUT DX,AL INC DX MOV AX,WORD PTR [DI.SAMP_OFF] MOV BP,WORD PTR [DI.SAMP_OFF+2] ADD AX,[DI.OFFSET_ADD] ADC BP,0 SHR AX,7 SHL BP,9 OR AX,BP OUT DX,AX DEC DX MOV AL,SampleStartHi OUT DX,AL INC DX MOV AX,WORD PTR [DI.SAMP_OFF] ADD AX,[DI.OFFSET_ADD] SHL AX,9 OUT DX,AX DEC DX SUB DX,CommandPort Rept 6 IN AL,DX EndM ADD DX,CommandPort RET SEND_SAMPLE_START ENDP ;----------------------------------------------------------------------------- SEND_SAMPLE_END PROC NEAR MOV AL,SampleEndLo OUT DX,AL INC DX MOV AX,WORD PTR [DI.SAMP_OFF] MOV BP,WORD PTR [DI.SAMP_OFF+2] ADD AX,[DI.LEN] ADC BP,0 SHR AX,7 SHL BP,9 OR AX,BP OUT DX,AX DEC DX MOV AL,SampleEndHi OUT DX,AL INC DX MOV AX,WORD PTR [DI.SAMP_OFF] ADD AX,[DI.LEN] SHL AX,9 OUT DX,AX DEC DX RET SEND_SAMPLE_END ENDP ;----------------------------------------------------------------------------- SEND_SAMPLE_LOOP PROC NEAR MOV AL,LoopStartLo OUT DX,AL INC DX MOV AX,WORD PTR [DI.SAMP_OFF] MOV BP,WORD PTR [DI.SAMP_OFF+2] ADD AX,[DI.REPEAT] ADC BP,0 SHR AX,7 SHL BP,9 OR AX,BP OUT DX,AX DEC DX MOV AL,LoopStartHi OUT DX,AL INC DX MOV AX,WORD PTR [DI.SAMP_OFF] ADD AX,[DI.REPEAT] SHL AX,9 OUT DX,AX DEC DX RET SEND_SAMPLE_LOOP ENDP ;----------------------------------------------------------------------------- SEND_WRITE_VOICE PROC NEAR MOV AL,WriteVoiceMode OUT DX,AL ADD DX,2 MOV AL,AH OUT DX,AL SUB DX,2 RET SEND_WRITE_VOICE ENDP ;----------------------------------------------------------------------------- WAIT_PORT PROC NEAR SUB DX,CommandPort Rept 6 IN AL,DX EndM ADD DX,CommandPort RET WAIT_PORT ENDP ;----------------------------------------------------------------------------- SEND_RAMP PROC NEAR MOV DX,BASE_PORT ADD DX,CommandPort MOV AL,VOLumeCtrl OUT DX,AL ADD DX,2 MOV AL,3 OUT DX,AL SUB DX,2 MOV AH,0 CMP BX,BP JB SHORT NoFixVOLDir MOV AH,01000000B XCHG BX,BP NoFixVOLDir: MOV AL,VOLRampStart OUT DX,AL XCHG AX,BX INC DX OUT DX,AX DEC DX MOV AL,VOLRampEnd OUT DX,AL MOV AX,BP INC DX OUT DX,AX DEC DX MOV AL,VOLumeCtrl OUT DX,AL MOV AL,BH ADD DX,2 OUT DX,AL SUB DX,2 RET SEND_RAMP ENDP ;----------------------------------------------------------------------------- ; CX= NUMBER OF WORDS, EDI= GUSMEM POINTER, BX= 0000H AMIGA, 8080H PC SAMPLE ; DS:SI= POINTER TO SAMPLE DATA ;----------------------------------------------------------------------------- SEND_SAMPLE_DATA PROC NEAR CMP CS:DMA_CHANNEL,0 JNE DMA_INIT MOV DX,CS:BASE_PORT ADD DX,CommandPort LHP1: LODSW CLI XOR AX,BX MOV BP,AX MOV AL,DRAMAddrLo OUT DX,AL INC DX MOV AX,DI OUT DX,AX DEC DX MOV AL,DRAMAddrHi OUT DX,AL ADD DX,2 MOV EAX,EDI SHR EAX,16 OUT DX,AL ADD DX,2 MOV AX,BP OUT DX,AL SUB DX,4 INC EDI MOV AL,DRAMAddrLo OUT DX,AL INC DX MOV AX,DI OUT DX,AX DEC DX MOV AL,DRAMAddrHi OUT DX,AL ADD DX,2 MOV EAX,EDI SHR EAX,16 OUT DX,AL ADD DX,2 MOV AX,BP MOV AL,AH OUT DX,AL SUB DX,4 INC EDI STI LOOP LHP1 CLI MOV AL,DRAMAddrLo ;MAKE SAMPLE 1 WORD LONGER OUT DX,AL INC DX MOV AX,DI OUT DX,AX DEC DX MOV AL,DRAMAddrHi OUT DX,AL ADD DX,2 MOV EAX,EDI SHR EAX,16 OUT DX,AL ADD DX,2 MOV AX,BP MOV AL,AH OUT DX,AL SUB DX,4 INC EDI MOV CS:GUS_MEM,EDI STI RET SEND_SAMPLE_DATA ENDP ;----------------------------------------------------------------------------- ; SET DMA READY FOR TRANSFER WITH AUTOINIT ; IN: DS:SI= BLOCKPOINTER, CX= SIZE IN WORDS, EDI, BX WIE OBEN ;----------------------------------------------------------------------------- DMA_INIT PROC NEAR MOV DX,CS:BASE_PORT ;STOP GUS DMA & CLEAR ALL PENDING IRQs ADD DX,CommandPort MOV AL,DMACtrl OUT DX,AL INC DX INC DX IN AL,DX ;CLEAR IRQ, BUT MASTER IRQ IS DISABLED MOV DX,CS:BASE_PORT ;THERE HAPPENED NO IRQ ADD DX,StatusPort IN AL,DX MOV BP,CS:DMA_CHANNEL MOVZX DX,CS:[DMA_RESET+BP] OUT DX,AL ;DMA MASTER CLEAR MOV BP,BX MOVZX EAX,CX ;CHECK 256K GUS DRAM BOUNDARY SHL EAX,1 ;BECAUSE DMA IS NOT ABLE TO CROSS INC EAX ;1 WORD LONGER-1 BYTE IS LAST BYTE ADD EAX,EDI SHR EAX,18 MOV EDX,EDI SHR EDX,18 CMP EAX,EDX JE SHORT DMA_NORMAL PUSH SI CX SHL EAX,18 SUB EAX,EDI MOV CX,AX SHR CX,1 PUSH CX DEC CX CALL DMA_PORTION ;FIRST PORTION POP AX CX SI SUB CX,AX ADD SI,AX ADD SI,AX ;REST: CORRECT OFFSET & SIZE DMA_NORMAL: MOV BX,CX ;MAKE SAMPLE 1 WORD LONGER SHL BX,1 DEC BX MOV AL,[SI+BX] MOV AH,AL INC BX MOV [SI+BX],AX DMA_PORTION: CLI MOV BX,SI ;SETUP PC DMA CONTROLLER MOV DX,DS MOV AX,DX ;CONVERT ADDRESS TO PAGE AND OFFSET SHL DX,4 SHR AH,4 ;PAGE ADD BX,DX ;OFFSET NEW ADC AH,0 MOV AL,AH MOV SI,CS:DMA_CHANNEL CMP SI,4 JB SHORT GDMI1 SHRD BX,AX,1 ;ADDRESS FOR 16-BIT DMA JMP SHORT GDMI2 GDMI1: SHL CX,1 ;COUNTER FOR 8-BIT DMA INC CX ;SAMPLE IS 1 WORD LONGER GDMI2: MOVZX DX,CS:[DMA_MASK+SI] MOV AL,BYTE PTR CS:DMA_CHANNEL OR AL,4 OUT DX,AL ;MASK DMA-CHANNEL MOVZX DX,CS:[DMA_MOD+SI] AND AL,3 OR AL,01001000B OUT DX,AL ;DMA-MODUS FOR GUS MOVZX DX,CS:[DMA_FLIP+SI] OUT DX,AL ;FLIP-FLOP CLEAR MOVZX DX,CS:[DMA_ADR+SI] MOV AL,BL ;DMA CHANNEL 1-4 OUT DX,AL ;OFFSET LOW MOV AL,BH OUT DX,AL ;OFFSET HIGH MOVZX DX,CS:[DMA_CNT+SI] MOV AL,CL OUT DX,AL ;SIZE LOW MOV AL,CH OUT DX,AL ;SIZE HIGH MOVZX DX,CS:[DMA_PAGE+SI] MOV AL,AH OUT DX,AL ;PAGE MOVZX DX,CS:[DMA_MASK+SI] MOV AX,SI AND AL,3 OUT DX,AL ;DEMASK DMA-KANAL MOV DX,CS:BASE_PORT ;SETUP GUS FOR DMA TRANSFER ADD DX,CommandPort MOV AL,DMAAddr ;SET DMA ADDRESS OUT DX,AL MOV EAX,EDI SHR EAX,4 CMP SI,4 JB SHORT GDMI3 MOV BX,AX ;CONVERT FOR 16-BIT TRANSFER AND AX,03FFFH SHR AX,1 AND BX,0C000H OR AX,BX GDMI3: INC DX OUT DX,AX DEC DX MOV AL,DMACtrl OUT DX,AL INC DX INC DX MOV AX,SI AND AL,4 ;SELECT 8/16-BIT CHANNEL OR AX,BP ;SELECT AMIGA/PC OR AL,00100001B ;START DMA TRANSFER OUT DX,AL STI MOVZX DX,CS:[DMA_STAT+SI] MOV AH,CS:[DMA_BITS+SI] MOV EBX,800000H ;TIMEOUT GDMI4: DEC EBX JZ SHORT GDMI5 OR BL,BL JNZ GDMI4 IN AL,DX ;WAIT FOR TRANSFER END TEST AL,AH JZ GDMI4 GDMI5: MOV DX,CS:BASE_PORT ;STOP GUS DMA ADD DX,CommandPort MOV AL,DMACtrl OUT DX,AL INC DX INC DX IN AL,DX ;CLEAR IRQ, BUT MASTER IRQ IS DISABLED MOV DX,CS:BASE_PORT ;THERE HAPPENED NO IRQ ADD DX,StatusPort IN AL,DX MOVZX DX,CS:[DMA_RESET+SI] OUT DX,AL ;DMA MASTER CLEAR AND ECX,0FFFFH ;INCREASE GUSMEM-POINTER INC CX CMP SI,4 JB SHORT GDMI6 SHL CX,1 GDMI6: ADD EDI,ECX MOV CS:GUS_MEM,EDI RET DMA_INIT ENDP ;============================================================================= ;============================================================================= PLAY_MUSIC PROC NEAR PUSH CS POP DS CLI MOV SI,54*2 MOV EBP,54 MOV CX,908-54+1 CountLoop: XOR EDX,EDX MOV EAX,369DE4H DIV EBP MOV EDX,100 MUL EDX MOV EBX,Voices14 DIV EBX SHR BX,1 ADC BX,0 CMP DX,BX JB SHORT NoHigherFreq INC AX NoHigherFreq: MOV [FREQ_TABLE+SI],AX INC BP ADD SI,2 LOOP CountLoop MOV SAM_CH,8 MOV MOD_STAT,0 MOV PATT_ROW,64 MOV PATT_CURRENT,0 MOV PATT_SPEED,6 MOV PATT_COUNT,1 MOV DI,OFFSET SAMP_CHANS XOR BX,BX MOV CX,CH_NUMB ClearVarLoop: MOV [DI.FREQ_VAL],0 MOV [DI.VOL],0 MOV AL,[PAN_REGS+BX] SHL AL,4 OR AL,[PAN_REGS+BX] MOV [DI.BALANCE],AL INC BX ADD DI,CHAN_SIZE LOOP ClearVarLoop XOR BX,BX ;Set Pan Regs!! MOV CX,NumVoices LLDM14: MOV DX,BASE_PORT ADD DX,ActiveVoicePort MOV AL,NumVoices SUB AL,CL OUT DX,AL MOV DX,BASE_PORT ADD DX,CommandPort MOV AL,VoiceBalance OUT DX,AL MOV DX,BASE_PORT ADD DX,DataHighPort MOV AL,[PAN_REGS+BX] OUT DX,AL INC BX LOOP LLDM14 XOR AX,AX MOV DX,50 MOV BX,1024 DIV BX MOV WORD PTR BPM_SPEED,AX XOR AX,AX DIV BX MOV WORD PTR BPM_SPEED+2,AX MOV BPM_COUNT,0 MOV COUNTER,20 MOV DX,BASE_PORT ;Speaker On!!! MOV AL,00000001B OUT DX,AL STI CALL IRQ_INIT RET PLAY_MUSIC ENDP ;----------------------------------------------------------------------------- STOP_MUSIC PROC NEAR PUSH CS POP DS CALL IRQ_INIT US_OFF: PUSH CS POP DS MOV DX,BASE_PORT ;Speaker Off!!! MOV AL,00000011B OUT DX,AL MOV DX,BASE_PORT ADD DX,ActiveVoicePort MOV CX,NumVoices VoiceClearL: MOV AL,CL DEC AL OUT DX,AL INC DX MOV AL,WriteVoiceMode OUT DX,AL ADD DX,2 MOV AL,3 ;Voice Off OUT DX,AL SUB DX,2 MOV AL,VolumeCtrl OUT DX,AL ADD DX,2 MOV AL,3 ;Ramp Off OUT DX,AL SUB DX,3 LOOP VoiceClearL RET STOP_MUSIC ENDP ;----------------------------------------------------------------------------- ; SERVICE IRQ SWAPPING; USES THE REAL-TIME-CLOCK OR TIMER IRQ ;----------------------------------------------------------------------------- IRQ_INIT PROC NEAR CLI XOR AX,AX MOV ES,AX CMP SYSTEM,0 JNE SHORT WU11 MOV AX,COMP_SPEED2 ;XCHANGE INIT & STOP DATA FOR DOS MOV DX,COMP_SPEED3 MOV COMP_SPEED2,DX MOV COMP_SPEED3,AX MOV AL,UHR_STATA ;CLOCK-IRQ-RATE (1024 HZ) OUT UHR_INDEX,AL JMP SHORT WU1 WU1: JMP SHORT WU2 WU2: XCHG AL,AH IN AL,UHR_PORT AND AL,0F0H OR AL,DL XCHG AL,AH OUT UHR_INDEX,AL JMP SHORT WU3 WU3: JMP SHORT WU4 WU4: XCHG AL,AH OUT UHR_PORT,AL JMP SHORT WU5 WU5: JMP SHORT WU6 WU6: MOV AL,UHR_STATB ;CLOCK-IRQ-MODUS OUT UHR_INDEX,AL JMP SHORT WU7 WU7: JMP SHORT WU8 WU8: XCHG AL,AH IN AL,UHR_PORT AND AL,08FH MOV DL,DH AND DL,40H OR AL,DL XCHG AL,AH OUT UHR_INDEX,AL JMP SHORT WU9 WU9: JMP SHORT WU10 WU10: XCHG AL,AH OUT UHR_PORT,AL IN AL,IRQ4 ;IRQ8 DE-/MASK AND AL,0FEH MOV DL,DH AND DL,1 OR AL,DL OUT IRQ4,AL MOV BX,4*70H ;UHR-IRQ DETOUR MOV EAX,ES:[BX] MOV EDX,HOLD70 MOV ES:[BX],EDX MOV HOLD70,EAX JMP SHORT WU12 WU11: MOV AX,COMP_SPEED4 ;FOR WINDOWS MOV DX,COMP_SPEED5 MOV COMP_SPEED4,DX MOV COMP_SPEED5,AX MOV AL,00110110B ;SET TIMER0 TO 1.024 KHZ OUT PIT1,AL ;DIVIDER =1193 MOV AL,DL OUT TIMER0,AL JMP SHORT OUT40 OUT40: MOV AL,DH OUT TIMER0,AL MOV BX,4*8H ;TIMEOUT-IRQ DETOUR MOV EAX,ES:[BX] MOV EDX,HOLD70 MOV ES:[BX],EDX MOV HOLD70,EAX WU12: MOV AL,20H OUT IRQ3,AL OUT IRQ1,AL STI RET IRQ_INIT ENDP ;----------------------------------------------------------------------------- GET_SONGMOD PROC NEAR MOV AL,CS:US_MODUS RET GET_SONGMOD ENDP ;----------------------------------------------------------------------------- SET_SONGMOD PROC NEAR AND AL,3 MOV CS:US_MODUS,AL RET SET_SONGMOD ENDP ;----------------------------------------------------------------------------- GET_SONGPOSITION PROC NEAR MOV AL,BYTE PTR CS:PATT_CURRENT RET GET_SONGPOSITION ENDP ;----------------------------------------------------------------------------- SET_SONGPOSITION PROC NEAR AND AL,7FH MOV BYTE PTR CS:PATT_CURRENT,AL MOV CS:PATT_ROW,64 RET SET_SONGPOSITION ENDP ;----------------------------------------------------------------------------- SET_SONGLOOP PROC NEAR MOV CS:SONG_LOOP,AL RET SET_SONGLOOP ENDP ;----------------------------------------------------------------------------- GET_VOLUME PROC NEAR MOV AL,BYTE PTR CS:MASTER_VOLUME ;0= MIN VOLUME,255= MAX VOLUME MOV BL,BYTE PTR CS:MUSIC_VOLUME ;0= MIN VOLUME,255= MAX VOLUME MOV BH,BYTE PTR CS:FX_VOLUME ;0= MIN VOLUME,255= MAX VOLUME RET GET_VOLUME ENDP ;----------------------------------------------------------------------------- SET_VOLUME PROC NEAR MOV BYTE PTR CS:MASTER_VOLUME,AL ;0= MIN VOLUME,255= MAX VOLUME MOV BYTE PTR CS:MUSIC_VOLUME,BL ;0= MIN VOLUME,255= MAX VOLUME MOV BYTE PTR CS:FX_VOLUME,BH ;0= MIN VOLUME,255= MAX VOLUME PUSH AX DX MOVZX DX,AL INC DX PUSH DX MOVZX AX,BL MUL DX MOV BYTE PTR CS:MUSIC_VOL,AH POP DX MOVZX AX,BH MUL DX MOV BYTE PTR CS:FX_VOL,AH POP DX AX RET SET_VOLUME ENDP ;----------------------------------------------------------------------------- ; START FX SAMPLE ; BX= SAMPLE-HANDLE, CX= FREQUENCE (HZ) ;----------------------------------------------------------------------------- PLAY_SAMPLE PROC NEAR PUSH CS POP DS TEST US_MODUS,1 JNZ GPSMP1 CLI MOV DI,OFFSET SAMPLE_CHAN MOV [DI.OFFSET_ADD],0 MOV [DI.REPEAT],0 MOV AX,[SAMPLE_BIG+BX] MOV [DI.LEN],AX MOV DX,1024 MUL DX DIV CX SUB AX,64 JNC SHORT LOW_COUNT MOV AX,1 LOW_COUNT: MOVZX SI,SAM_CH SUB SI,8 SHL SI,1 MOV [SAM_COUNT+SI],AX MOV AX,100 MUL CX MOV BP,Voices14 DIV BP SHR BP,1 ADC BP,0 CMP DX,BP JB SHORT NoHigherFreq2 INC AX NoHigherFreq2: MOV [DI.FREQ_VAL],AX SHL BX,1 MOV EAX,[SAMPLE_MEM+BX] MOV [DI.SAMP_OFF],EAX MOV DX,BASE_PORT ADD DX,CommandPort DEC DX MOV AL,SAM_CH OUT DX,AL INC DX MOV AH,3 CALL SEND_WRITE_VOICE CALL WAIT_PORT CALL SEND_SAMPLE_START CALL SEND_SAMPLE_END CALL SEND_SAMPLE_LOOP MOV AH,3 CALL SEND_WRITE_VOICE MOV BP,GUS_VOL ;SET VOLUME MOV BX,FX_VOL INC BX SHR BX,2 CMP BL,40H JBE SHORT FIXVL MOV BL,40H FIXVL: SHL BX,1 MOV BX,[GUS_VOL+BX] XCHG BX,BP CALL SEND_RAMP MOV AL,SetVoiceFreq ;SET FREQUENCE OUT DX,AL INC DX MOV AX,[DI.FREQ_VAL] OUT DX,AX DEC DX DEC DX ;START VOICE MOV AL,SAM_CH OUT DX,AL INC DX MOV AH,0 ;NO LOOP CALL SEND_WRITE_VOICE CALL WAIT_PORT STI INC SAM_CH CMP SAM_CH,13 JB SHORT GPSMP1 MOV SAM_CH,8 GPSMP1: RET PLAY_SAMPLE ENDP ;----------------------------------------------------------------------------- END_SAMPLE PROC NEAR MOV CS:SAMPLE_ZEIG,0 RET END_SAMPLE ENDP ;============================================================================= ;============================================================================= ; LOAD CONFIG DATA (PARSER) ;----------------------------------------------------------------------------- CONFIG_INIT PROC NEAR MOV AX,CS ;SAVE SEGMENT OF CODE MOV DS,AX MOV WORD PTR HOLD70+2,AX ;THIS LINE IS IMPORTANT MOV DX,OFFSET CONFIG_NAME MOV AH,3DH MOV AL,80H INT 21H JC SHORT GCFG1 MOV GDDHANDLE,AX LCFG1: XOR SI,SI MOV DX,OFFSET QUEUE_BUFFER LCFG2: MOV AH,3FH MOV BX,GDDHANDLE MOV CX,1 INT 21H JC SHORT GCFG2 OR AX,AX JZ SHORT GCFG2 MOV DI,DX CMP BYTE PTR [DI],0AH JE SHORT GCFG6 INC DX INC SI CMP SI,256 JB LCFG2 GCFG6: MOV BX,OFFSET CFG_TEXT2 CALL SEEK_LINE JNC SHORT GCFG4 LODSB AND AL,3 MOV US_MODUS,AL JMP LCFG1 GCFG4: MOV BX,OFFSET CFG_TEXT3 CALL SEEK_LINE JNC SHORT GCFG5 INC SI LODSB DEC AL AND AL,7 INC AL SHL AL,4 MOV AH,2 MOV BASE_PORT,AX JMP LCFG1 GCFG5: MOV BX,OFFSET CFG_TEXT5 CALL SEEK_LINE JNC SHORT GCFG7 LODSB AND AX,7 MOV DMA_CHANNEL,AX JMP LCFG1 GCFG7: MOV BX,OFFSET CFG_TEXT7 CALL SEEK_LINE JNC LCFG1 LODSB AND AL,1 MOV SYSTEM,AL JMP LCFG1 GCFG2: MOV BX,GDDHANDLE MOV AH,3EH INT 21H GCFG1: RET CONFIG_INIT ENDP ;----------------------------------------------------------------------------- SEEK_LINE PROC NEAR CLD MOV SI,OFFSET QUEUE_BUFFER LSKL1: PUSH BX LSKL2: CMP BYTE PTR [BX],0 JE SHORT GSKL1 CMP SI,DX JAE SHORT GSKL2 LODSB CMP AL,[BX] JNE SHORT GSKL3 INC BX JMP LSKL2 GSKL3: POP BX JMP LSKL1 GSKL2: POP BX CLC RET GSKL1: POP BX STC RET SEEK_LINE ENDP ;============================================================================= ;============================================================================= ; ; MOD LOAD ROUTINES ; ;============================================================================= LOAD_MOD_FROM_VOL PROC NEAR CALL SET_VOLUME_POINTER JMP SHORT GLDM0 LOAD_MOD_FROM_VOL ENDP ;----------------------------------------------------------------------------- ; LOAD A MODFILE ; DS:DX= FILENAME ;----------------------------------------------------------------------------- LOAD_MOD PROC NEAR MOV AX,3D00H ;OPEN MOD INT 21H JC GLDM1 PUSH CS POP DS MOV GDDHANDLE,AX GLDM0: CALL SET_TMEM ;ALLOCATE TRACK-BUFFER MOV BX,GDDHANDLE MOV GDDZEIG,0 MOV CX,10 ;GET SONG-NAME LLDM1: CALL GET_QUEUE JC GLDM2 LOOP LLDM1 XOR SI,SI ;31 INSTRUMENTS LLDM2: MOV CX,11 ;INSTRUMENT NAME LLDM3: CALL GET_QUEUE JC GLDM2 LOOP LLDM3 XOR EAX,EAX CALL GET_QUEUE ;INSTRUMENT SIZE XCHG AL,AH CMP AX,2 JAE SHORT GLDM20 XOR AX,AX GLDM20: SHL AX,1 MOV [ISIZE+SI],AX ;NO MORE THAN 64K CALL GET_QUEUE ;IVOLUME & FINETUNE PUSH AX XOR AH,AH MOV [IFINETUNE+SI],AX POP AX SHR AX,8 CMP AX,40H JBE SHORT GLDM9 MOV AX,40H GLDM9: MOV [IVOLUME+SI],AX CALL GET_QUEUE ;ILOOP_START XCHG AL,AH SHL AX,1 MOV [ILOOP_START+SI],AX CALL GET_QUEUE ;ILOOP_SIZE XCHG AL,AH SHL AX,1 MOV [ILOOP_SIZE+SI],AX INC SI INC SI CMP SI,62 JB LLDM2 CALL GET_QUEUE ;SONG_SIZE & LOOP_BYTE OR NOTHING JC GLDM2 MOV SONG_SIZE,AL MOV SONG_LOOP,AH XOR DX,DX MOV CX,64 ;SONG_DATA MOV DI,OFFSET SONG_DATA LLDM4: CALL GET_QUEUE JC GLDM2 MOV [DI],AX CMP AL,DL ;FIND HIGHEST PATTERN NUMBER JBE SHORT GLDM12 MOV DL,AL GLDM12: CMP AH,DL JBE SHORT GLDM13 MOV DL,AH GLDM13: INC DI INC DI LOOP LLDM4 INC DL CLD MOV PATTERN_NUMBER,DX CALL GET_QUEUE PUSH AX CALL GET_QUEUE SHL EAX,16 POP AX CMP EAX,"NHC8" ;8CHN-MOD JE SHORT GLDM3 CMP EAX,"8TLF" ;FLT8-MOD JE SHORT GLDM3 CMP EAX,"ATCO" ;OCTA-MOD JE SHORT GLDM3 CMP EAX,"NHC6" ;6CHN-MOD JE SHORT GLDM16 CMP EAX,".K.M" ;M.K.-MOD JE SHORT GLDM10 CMP EAX,"4TLF" ;FLT4-MOD JNE GLDM2 GLDM10: MOV CH_NUMB,4 ;4-CHANNEL-MOD MOV PATTERN_SIZE,1024 MOV AH,0 MOV TRACK_INFO+4,AH MOV TRACK_INFO+5,AH MOV TRACK_INFO+6,AH MOV TRACK_INFO+7,AH JMP SHORT GLDM11 GLDM16: MOV CH_NUMB,6 ;6-CHANNEL-MOD MOV PATTERN_SIZE,1536 MOV AH,0 MOV TRACK_INFO+6,AH MOV TRACK_INFO+7,AH JMP SHORT GLDM11 GLDM3: MOV CH_NUMB,8 ;8-CHANNEL-MOD: GET-PATTERNS MOV PATTERN_SIZE,2048 GLDM11: MOV PATT_CURRENT,0 MOV TRACK_NUMBER,0 LLDM7: MOV ES,PATTERN_SEG MOV BX,GDDHANDLE XOR DI,DI LLDM6: XOR SI,SI LLDM5: CALL GET_QUEUE ;GET PATTERNS AND SPLIT INTO TRACKS JC GLDM2 MOV DX,AX CALL GET_QUEUE JC GLDM2 PUSH DI ADD DI,SI SHL EAX,16 MOV AX,DX STOSD POP DI ADD SI,256 CMP SI,PATTERN_SIZE ;NEXT TRACK/CHANNEL JB LLDM5 ADD DI,4 ;NEXT NOTE CMP DI,256 JB LLDM6 MOV ES,TRACK_SEG ;INTEGRATE TRACK1-8 MOV DX,TRACK_NUMBER XCHG DL,DH MOV DS,PATTERN_SEG XOR SI,SI XOR BX,BX LLDM8: XOR DI,DI LLDM9: CMP DX,DI JBE SHORT GLDM4 PUSH SI DI MOV CX,256/4 REPE CMPSD ;TRACK ALREADY EXISTS? POP DI SI PUSHF ADD DI,256 POPF JNE LLDM9 JMP SHORT GLDM5 GLDM4: INC DH ;NO, ADD TRACK TO BUFFER PUSH SI MOV CX,256/4 REP MOVSD POP SI GLDM5: MOV AX,DI ;YES DEC AH MOV CS:[TRACK_INFO+BX],AH INC BX ADD SI,256 CMP BX,CS:CH_NUMB JB LLDM8 PUSH CS POP DS XCHG DL,DH MOV TRACK_NUMBER,DX XOR BX,BX ;MAKE TRACKLIST MOV AX,PATT_CURRENT LLDM10: CMP [SONG_DATA+BX],AL JNE SHORT GLDM6 MOV AH,TRACK_INFO MOV [TRACK1_DATA+BX],AH MOV AH,TRACK_INFO+1 MOV [TRACK2_DATA+BX],AH MOV AH,TRACK_INFO+2 MOV [TRACK3_DATA+BX],AH MOV AH,TRACK_INFO+3 MOV [TRACK4_DATA+BX],AH MOV AH,TRACK_INFO+4 MOV [TRACK5_DATA+BX],AH MOV AH,TRACK_INFO+5 MOV [TRACK6_DATA+BX],AH MOV AH,TRACK_INFO+6 MOV [TRACK7_DATA+BX],AH MOV AH,TRACK_INFO+7 MOV [TRACK8_DATA+BX],AH GLDM6: INC BX CMP BL,128 JB LLDM10 INC PATT_CURRENT ;GET NEXT PATTERN MOV AX,PATT_CURRENT CMP AX,PATTERN_NUMBER JB LLDM7 GLDM7: MOV ES,PATTERN_SEG ;CLEAR PATTERN SEGMENT MOV AH,49H INT 21H MOV PATTERN_SEG,0 MOV BX,TRACK_NUMBER ;RESIZE TRACK SEGMENT SHL BX,4 MOV ES,TRACK_SEG MOV AH,4AH INT 21H MOVZX AX,GDDZEIG ;SET FILEPOINTER BACK OR AX,AX ;BUFFER QUIT JZ SHORT GLDM30 MOV DX,GDDREST SUB DX,AX JZ SHORT GLDM30 XOR CX,CX MOV GDDZEIG,CL MOV BX,GDDHANDLE NEG DX DEC CX MOV AX,4201H INT 21H GLDM30: MOV AH,48H ;SAMPLE BUFFER READY MOV BX,2000H ;128K BECAUSE OF 64K DMA PAGE INT 21H MOV GDDSEG,AX TEST AX,0FFFH JZ SHORT GLDM31 AND AX,0F000H ADD AX,1000H GLDM31: MOV BUFSEG,AX CALL INIT_DEVICE ;IS PROBABLY THE FIRST INIT XOR EDI,EDI ;LOAD SAMPLES MOV GUS_MEM,EDI XOR SI,SI LLDM12: PUSH SI MOV CX,[ISIZE+SI] JCXZ SHORT GLDM8 SHL SI,1 TEST EDI,31 JZ SHORT GLDM32 AND EDI,-32 ;32 BYTE BOUND FOR DMA ADD EDI,32 GLDM32: MOV [IOFFSET+SI],EDI MOV BX,GDDHANDLE ;SAMPLE IN BUFFER PUSH DS XOR DX,DX MOV SI,DX MOV DS,BUFSEG MOV AH,3FH INT 21H SHR CX,1 XOR BX,BX ;AMIGA-SAMPLE CALL SEND_SAMPLE_DATA POP DS GLDM8: POP SI INC SI INC SI CMP SI,62 JB LLDM12 MOV ES,GDDSEG ;CLEAR SAMPLE BUFFER MOV AH,49H INT 21H MOV GDDSEG,0 CLC JMP SHORT GLDM15 GLDM2: STC GLDM15: PUSHF MOV AH,3EH MOV BX,GDDHANDLE INT 21H POPF GLDM1: RET LOAD_MOD ENDP ;----------------------------------------------------------------------------- ; GET A WORD FROM BUFFER ; IN: AX= WORD, BX= HANDLE ;----------------------------------------------------------------------------- GET_QUEUE PROC NEAR CMP GDDZEIG,0 JNE SHORT GTQ1 PUSH CX DX MOV DX,OFFSET QUEUE_BUFFER MOV CX,256 MOV AH,3FH INT 21H MOV GDDREST,AX POP DX CX GTQ1: PUSH BX MOV BL,GDDZEIG XOR BH,BH CMP BX,GDDREST JAE SHORT GTQ2 MOV AX,[QUEUE_BUFFER+BX] ADD GDDZEIG,2 POP BX CLC RET GTQ2: POP BX STC RET GET_QUEUE ENDP ;---------------------------------------------------------------------------- ; MEMORY FOR TRACKS, CARRY-FLAG 0=OK 1=ERROR ;---------------------------------------------------------------------------- SET_TMEM PROC NEAR MOV AH,48H MOV BX,1000H ;64K TRACK BUFFER (WIRD RESIZED) INT 21H JC SHORT STCM1 MOV TRACK_SEG,AX MOV AH,48H MOV BX,80H ;2K PATTERN BUFFER INT 21H JC SHORT STCM1 MOV PATTERN_SEG,AX STCM1: RET SET_TMEM ENDP ;---------------------------------------------------------------------------- END_MUSIC PROC NEAR CALL INIT_DEVICE MOV AH,49H MOV ES,TRACK_SEG INT 21H CMP PATTERN_SEG,0 JE SHORT LEM3 MOV AH,49H MOV ES,PATTERN_SEG INT 21H MOV PATTERN_SEG,0 LEM3: CMP GDDSEG,0 JE SHORT LEM4 MOV AH,49H MOV ES,GDDSEG INT 21H MOV GDDSEG,0 LEM4: XOR EAX,EAX MOV GDDLENGTH,EAX MOV GDDREST,AX MOV GDDHANDLE,AX MOV GDDSEG,AX MOV BUFSEG,AX MOV GDDZEIG,AL ;RESET VARIABLES MOV SAM_CH,8 MOV MOD_STAT,AL XOR BX,BX MOV CX,11 LEM1: MOV WORD PTR [BPM_COUNT+BX],AX ADD BX,2 LOOP LEM1 MOV CH_NUMB,4 MOV TRACK_NUMBER,AX MOV DWORD PTR TRACK_INFO,EAX MOV DWORD PTR TRACK_INFO+4,EAX MOV TRACK_SEG,AX MOV BX,OFFSET TRACK1_DATA LEM2: MOV [BX],AL INC BX CMP BX,OFFSET PATTJUMPS JB LEM2 MOV IRQCOUNT,56 RET END_MUSIC ENDP ;============================================================================= ; LOAD A SAMPLE ; INPUT: DS:DX= FILENAME, CL= 00H AMIGA-SAMPLE, 80H PC-SAMPLE ; OUTPUT: AX= SAMPLE-HANDLE FOR PLAYING ;----------------------------------------------------------------------------- LOAD_SAMPLE_FROM_VOL PROC NEAR PUSH CX CALL SET_VOLUME_POINTER POP CX MOV AX,WORD PTR GDDLENGTH JMP SHORT GSMP0 LOAD_SAMPLE_FROM_VOL ENDP ;----------------------------------------------------------------------------- LOAD_SAMPLE PROC NEAR MOV AX,3D00H ;OPEN SAMPLE INT 21H JC GSMP1 PUSH CS POP DS MOV GDDHANDLE,AX MOV BX,AX PUSH CX CALL GET_FILESIZE POP CX GSMP0: AND CL,80H MOV CH,CL PUSH DS CX MOV GDDZEIG,0 MOV CX,AX AND CX,0FFFEH MOV AH,48H ;SAMPLE BUFFER READY MOV BX,2000H ;128K BECAUSE OF 64K DMA PAGE INT 21H MOV GDDSEG,AX TEST AX,0FFFH JZ SHORT GSMP2 AND AX,0F000H ADD AX,1000H GSMP2: MOV BUFSEG,AX MOV EDI,GUS_MEM TEST EDI,31 JZ SHORT GSMP3 AND EDI,-32 ;32 BYTE BOUND FOR DMA ADD EDI,32 GSMP3: MOV SI,SAMPLE_ZEIG MOV [SAMPLE_BIG+SI],CX SHL SI,1 MOV [SAMPLE_MEM+SI],EDI MOV BX,GDDHANDLE ;SAMPLE IN BUFFER XOR DX,DX MOV SI,DX MOV DS,BUFSEG MOV AH,3FH INT 21H SHR CX,1 POP BX CLD CALL SEND_SAMPLE_DATA POP DS MOV ES,GDDSEG ;CLEAR SAMPLE BUFFER MOV AH,49H INT 21H MOV GDDSEG,0 MOV BX,GDDHANDLE MOV AH,3EH INT 21H MOV AX,SAMPLE_ZEIG ADD SAMPLE_ZEIG,2 CLC GSMP1: RET LOAD_SAMPLE ENDP ;----------------------------------------------------------------------------- GET_FILESIZE PROC NEAR MOV AX,4202H XOR CX,CX XOR DX,DX INT 21H PUSH AX MOV AX,4200H XOR CX,CX XOR DX,DX INT 21H POP AX RET GET_FILESIZE ENDP ;----------------------------------------------------------------------------- SET_VOLUME_POINTER PROC NEAR PUSH CS POP DS MOV BP,AX MOV DX,OFFSET VOL_NAME MOV AX,3D80H INT 21H JC GLDM1 MOV GDDHANDLE,AX MOV BX,AX ; CMP BP,GDDMIN ; JAE SHORT LGDM3 ; MOV GDDNEW,1 ; MOV GDDMIN,BP ; JMP SHORT LGDM1 ;LGDM3: SUB BP,GDDMIN ; INC BP ; MOV DX,GDDPOSL ; MOV CX,GDDPOSH ; MOV AX,4200H ; INT 21H LGDM1: MOV DX,OFFSET GDDLENGTH MOV CX,4 MOV AH,3FH INT 21H DEC BP JZ SHORT LGDM2 MOV DX,WORD PTR GDDLENGTH MOV CX,WORD PTR GDDLENGTH+2 MOV AX,4201H INT 21H ; CMP BP,1 ; JNE LGDM1 ; CMP GDDNEW,1 ; JNE LGDM1 ; MOV GDDNEW,0 ; MOV GDDPOSL,AX ; MOV GDDPOSH,DX JMP LGDM1 LGDM2: RET SET_VOLUME_POINTER ENDP ;============================================================================= END MAIN