;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Music Module ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ %include "switch.inc" %include "network.inc" ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Externals ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ extern D_GotoStartingDirectory:Far extern D_SetDriveDirectoryFar:Far extern D_GetFileName:Far extern D_Showtime:Far extern E_EMSAvailable:Far extern E_SaveEMSPageFrame:Far extern E_RestoreEMSPageFrame:Far extern E_UnInitEMS:Far extern E_AllocateEMS:Far extern E_MapEMSMemory:Far extern E_GetEMSPageFrame:Far extern E_ReleaseEMS:Far extern E_AllocateBlockEMS:Far, E_ReleaseBlockEMS:Far extern E_MapAlignedBlockEMS:Far extern E_GetInternalEMSHandle:Far extern I_TagInstrument:Far extern I_TagSample:Far extern O1_OutOfSoundCardMemoryList:Far extern M_FunctionHandler:Far extern M_Object1List:Far extern Network_UpdatePatternIfIdle:Far extern PE_GetCurrentPattern:Far extern PE_FillHeader:Far extern S_GetDestination:Far extern S_UnInitScreen:Far extern S_DirectDrawString:Far extern S_DrawString:Far extern S_SetDirectMode:Far extern S_SaveScreen:Far extern S_RestoreScreen:Far extern S_DrawBox:Far extern S_DrawString:Far extern S_UpdateScreen:Far extern S_DrawSmallBox:Far extern F_DrawHeader:Far extern K_GetKey:Far extern StartClock:Far extern SetInfoLine:Far, SetInfoLine2:Far extern M_Object1List:Far extern MaxRow extern IdleUpdateInfoLine:Far extern GlobalKeyList:Far extern GetEnvironment:Far extern MIDIBufferEmpty:Far, MIDISend:Far, MIDI_ClearTable:Far extern O1_ShowTime ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Globals ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Global Music_GetDisplayVariables:Far Global Music_AutoDetectSoundCard:Far Global Music_Poll:Far Global Music_ReinitSoundCard:Far Global Music_InitMusic:Far Global Music_UnInitMusic:Far Global Music_GetSongSegment:Far Global Music_GetInstrumentMode:Far Global Music_ReleasePattern:Far Global Music_GetPattern:Far Global Music_GetPatternLocation:Far Global Music_GetPatternLocationNoCount:Far Global Music_AllocatePattern:Far Global Music_AllocateSample:Far Global Music_IncreaseSpeed:Far Global Music_DecreaseSpeed:Far Global Music_GetOutputWaveform:Far Global Music_PlayPartSong:Far Global Music_GetPatternLength:Far Global Music_ShowAutodetectSoundcard:Far Global Music_GetWaveForm:Far Global Music_ToggleOrderUpdate:Far Global Music_NextOrder:Far Global Music_LastOrder:Far Global Music_SetSoundCard:Far Global Music_SetDMA:Far Global Music_SetMixSpeed:Far Global Music_SetIRQ:Far Global Music_SetAddress:Far Global Music_SetLimit:Far Global Music_ReverseChannels:Far Global Music_GetNumChannels:Far Global Music_InitStereo:Far Global Music_ReleaseSample:Far Global Music_ReleaseAllSamples:Far Global Music_ReleaseAllPatterns:Far Global Music_ClearSampleName:Far Global Music_ClearAllSampleNames:Far Global Music_GetNumberOfSamples:Far Global Music_GetNumberOfInstruments:Far Global Music_ClearInstrument:Far Global Music_ClearAllInstruments:Far Global Music_GetHostChannelInformationTable:Far Global Music_GetSlaveChannelInformationTable:Far Global Music_SetGlobalVolume:Far Global Music_InitMuteTable:Far Global Music_UnmuteAll:Far Global Music_GetPlayMode:Far Global Music_GetPlayMode2:Far Global Music_PlayPattern:Far Global Music_PlaySample:Far Global Music_PlayNote:Far Global Music_Stop:Far Global Music_PlaySong:Far Global Music_ToggleChannel:Far Global Music_SoloChannel:Far Global Music_InitMixTable:Far Global Music_GetSampleLocation:Far Global Music_UpdatePatternOffset:Far Global Music_AssignSampleToInstrument:Far Global Music_KBPlaySong:Far Global Music_IncreaseVolume:Far Global Music_DecreaseVolume:Far Global Music_SetSoundCardDriver:Far Global Music_RegetLoopInformation:Far Global Music_SoundCardLoadSample:Far Global Music_SoundCardLoadAllSamples:Far Global Music_GetFreeSoundCardMemory:Far Global Music_GetPitchTable:Far Global Music_GetMIDIDataArea:Far Global Music_ToggleReverse:Far Global Music_PatternStorage:Far Global Music_GetDriverScreen:Far Global Music_GetLastChannel:Far Global SongDataArea:Word Global MixDataArea:Word Global Music_GetDriverVariable:Far, Music_SetDriverVariable:Far Public Music_GetDelay Public Music_SetNextOrder Public Music_TimeSong Public Music_ShowTime Public Music_SaveMIDIConfig Public MIDIDataArea Public Music_ToggleSoloInstrument, Music_ToggleSoloSample extern PE_GetLastInstrument:Far Public CurrentPattern ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; ; Functions for playing control ; Music_PlaySong........ parameters, AX = order ; Music_Stop............ parameters, None ; Music_PlayPattern..... parameters, AX = pattern, BX = number of rows, CX = row ; Music_ToggleChannel... parameters, AX = channel ; Music_SoloChannel..... parameters, AX = channel ; Segment SongData PARA Public 'Data' EndS Segment Music DWORD Public 'Code' USE16 ;Assume CS:Music CREATENEWLOGFILE EQU 0 %include "debug.inc" ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Variables ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ HOSTCHANNELSIZE EQU 80 SLAVECHANNELSIZE EQU 128 MAXSLAVECHANNELS EQU 256 NONOTE EQU 0FDh MIDICOMMAND_START EQU 0 MIDICOMMAND_STOP EQU 20h MIDICOMMAND_TICK EQU 40h MIDICOMMAND_PLAYNOTE EQU 60h MIDICOMMAND_STOPNOTE EQU 80h MIDICOMMAND_CHANGEVOLUME EQU 0A0h MIDICOMMAND_CHANGEPAN EQU 0C0h MIDICOMMAND_BANKSELECT EQU 0E0h MIDICOMMAND_PROGRAMSELECT EQU 100h MIDICOMMAND_CHANGEPITCH EQU 0FFFFh FineSineData Label Byte DB 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23 DB 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44 DB 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59 DB 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64 DB 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60 DB 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46 DB 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26 DB 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2 DB 0, -2, -3, -5, -6, -8, -9,-11,-12,-14,-16,-17,-19,-20,-22,-23 DB -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44 DB -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59 DB -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64 DB -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60 DB -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46 DB -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26 DB -24,-23,-22,-20,-19,-17,-16,-14,-12,-11, -9, -8, -6, -5, -3, -2 FineRampDownData Label Byte DB 64, 63, 63, 62, 62, 61, 61, 60, 60, 59, 59, 58, 58, 57, 57, 56 DB 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48 DB 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40 DB 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32 DB 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24 DB 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16 DB 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8 DB 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0 DB 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -8 DB -8, -9, -9,-10,-10,-11,-11,-12,-12,-13,-13,-14,-14,-15,-15,-16 DB -16,-17,-17,-18,-18,-19,-19,-20,-20,-21,-21,-22,-22,-23,-23,-24 DB -24,-25,-25,-26,-26,-27,-27,-28,-28,-29,-29,-30,-30,-31,-31,-32 DB -32,-33,-33,-34,-34,-35,-35,-36,-36,-37,-37,-38,-38,-39,-39,-40 DB -40,-41,-41,-42,-42,-43,-43,-44,-44,-45,-45,-46,-46,-47,-47,-48 DB -48,-49,-49,-50,-50,-51,-51,-52,-52,-53,-53,-54,-54,-55,-55,-56 DB -56,-57,-57,-58,-58,-59,-59,-60,-60,-61,-61,-62,-62,-63,-63,-64 FineSquareWave Label Byte DB 128 Dup (64), 128 Dup (0) EmptyPattern Label DW 64, 64, 0, 0 DB 64 Dup (0) ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; Zero globals. LastSample DW 0 PlayMode DW 0 ; Playmode 0 = Freeplay ; Playmode 1 = Pattern ; Playmode 2 = Song CurrentOrder DW 0 ; } Must follow CurrentPattern DW 0 ; } CurrentRow DW 0 ; } ProcessOrder DW 0 ProcessRow DW 0 BytesToMix DW 0 ; = Bytes per frame PatternOffset DW 0 PatternSegment DW 0 BreakRow DW 0 RowDelay DB 0 ; } Must join on. RowDelayOn DB 0 ; } PatternArray DB 0 ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ALIGN 4 PitchDepthConstant DD 98304.0 HostChannelInformationTable DB 64*HOSTCHANNELSIZE Dup(?) SlaveChannelInformationTable DB MAXSLAVECHANNELS*SLAVECHANNELSIZE Dup(?) MuteChannelTable DB 64 Dup (?) ChannelCountTable DB 400 Dup (?) ;AllocateCount1 DB 0 ;AllocateCount2 DB 0 ;AllocateCount3 DB 0 ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ALIGN 2 PatternDataSegment DW ? CurrentEditPattern DW ? PatternEditMaxRow DW ? ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ NumberOfRows DW 64 ; Non zero globals CurrentTick DW 6 CurrentSpeed DW 6 ProcessTick DW 0 Tempo DB 125 GlobalVolume DB 128 NumChannels DW 256 SoloSample DB 0FFh ; * ORDER IS IMPORTANT SoloInstrument DB 0FFh ; * ORDER IS IMPORTANT AllocateNumChannels DW 0 AllocateSlaveOffset DW 0 LastSlaveChannel DW 0 DecodeExpectedPattern DW 0FFFEh DecodeExpectedRow DW 0FFFEh ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ CmdLineNumChannels DW 0FFFFh DriverRequiredVariables Label ; * ORDER IS IMPORTANT BasePort DW 0FFFFh ; * ORDER IS IMPORTANT IRQ DW 0FFFFh ; * ORDER IS IMPORTANT DMA DW 0FFFFh ; * ORDER IS IMPORTANT CmdLineMixSpeed DW 0 ; * ORDER IS IMPORTANT SongDataArea DW SongData ; * ORDER IS IMPORTANT MIDIDataArea DW SongData + 4076 CmdLineDMASize DW 1024 ; default ReverseChannels DB 0 InstrumentHeader Label Byte DB "IMPI" DB 19 Dup (0), 60, 128, 32+128, 34 Dup (0) DB 0, 0FFh, 0FFh, 0FFh DB 0, 0, 1, 0, 2, 0, 3, 0, 4, 0 DB 5, 0, 6, 0, 7, 0, 8, 0, 9, 0 DB 10, 0, 11, 0, 12, 0, 13, 0, 14, 0 DB 15, 0, 16, 0, 17, 0, 18, 0, 19, 0 DB 20, 0, 21, 0, 22, 0, 23, 0, 24, 0 DB 25, 0, 26, 0, 27, 0, 28, 0, 29, 0 DB 30, 0, 31, 0, 32, 0, 33, 0, 34, 0 DB 35, 0, 36, 0, 37, 0, 38, 0, 39, 0 DB 40, 0, 41, 0, 42, 0, 43, 0, 44, 0 DB 45, 0, 46, 0, 47, 0, 48, 0, 49, 0 DB 50, 0, 51, 0, 52, 0, 53, 0, 54, 0 DB 55, 0, 56, 0, 57, 0, 58, 0, 59, 0 DB 60, 0, 61, 0, 62, 0, 63, 0, 64, 0 DB 65, 0, 66, 0, 67, 0, 68, 0, 69, 0 DB 70, 0, 71, 0, 72, 0, 73, 0, 74, 0 DB 75, 0, 76, 0, 77, 0, 78, 0, 79, 0 DB 80, 0, 81, 0, 82, 0, 83, 0, 84, 0 DB 85, 0, 86, 0, 87, 0, 88, 0, 89, 0 DB 90, 0, 91, 0, 92, 0, 93, 0, 94, 0 DB 95, 0, 96, 0, 97, 0, 98, 0, 99, 0 DB 100, 0, 101, 0, 102, 0, 103, 0, 104, 0 DB 105, 0, 106, 0, 107, 0, 108, 0, 109, 0 DB 110, 0, 111, 0, 112, 0, 113, 0, 114, 0 DB 115, 0, 116, 0, 117, 0, 118, 0, 119, 0 DB 0, 2, 4 Dup (0), 64, 0, 0, 64, 100, 0, 70 Dup (0) DB 0, 2, 4 Dup (0), 0, 0, 0, 0, 100, 0, 70 Dup (0) DB 0, 2, 4 Dup (0), 0, 0, 0, 0, 100, 0, 70 Dup (0) DB 7 Dup (0) SampleHeader Label Byte DB "IMPS", 13 Dup (0), 64, 0, 64, 40 Dup (0) DW 8363 DB 18 Dup (0) MidiPitchSendString DB 65h, 0, 64h, 0, 06 PatternLooping DB 0 PatternStorage DB 1 ; 0 = conventional only ; 1 = selective ; 2 = EMS only. PrepareSamplesMsg DB "Preparing Samples", 0 ReverseMsg DB "Left/right outputs reversed", 0 NoSoundCardMsg DB " No sound card detected", 0 MIDIConfigFileName DB "ITMIDI.CFG", 0 OrderUpdateEnabledMsg DB "Order list unlocked", 0 OrderUpdateDisabledMsg DB "Order list locked", 0 OrderLockFlag DB 0 UnsoloMsg DB "Solo disabled", 0 SoloSampleMsg DB "Solo sample ", 0FDh, "D", 0 SoloInstrumentMsg DB "Solo instrument ", 0FDh, "D", 0 %IF DEF DEBUG LoadDriverMessage DB "Loading driver:", 0 UnableToReadFileMessage DB "Unable to read file", 0 DetectingMessage DB "Testing driver", 0 ScreenOffset DW 0 %ENDIF PCSpeakerDriver DB "ITPCSPKR.DRV", 0 SBDriver DB "ITSB.DRV", 0 SB2Driver DB "ITSB2.DRV", 0 SBProDriver DB "ITSBPRO.DRV", 0 SB16Driver DB "ITSB16.DRV", 0 AWE32Driver DB "ITAWE32.DRV", 0 GUSDriver DB "ITGUS.DRV", 0 InterwaveDriver DB "ITIW.DRV", 0 PASDriver DB "ITPAS.DRV", 0 PAS16Driver DB "ITPAS16.DRV", 0 WSSDriver DB "ITWSS.DRV", 0 ESSDriver DB "ITES1868.DRV", 0 MIDIDriver DB "ITMPU401.DRV", 0 EWSCodecDriver DB "ITEWSCOD.DRV", 0 VIVOCodecDriver DB "ITVIVO.DRV", 0 ST97PCICodecDriver DB "ITSTCODE.DRV", 0 WAVDriver DB "ITWAV.DRV", 0 MIDDriver DB "ITMID.DRV", 0 VSoundMMXDriver DB "ITVSOUND.MMX", 0 VSoundDriver DB "ITVSOUND.DRV", 0 DefaultDriver DB "ITSOUND.DRV", 0 DriverNameTable Label DW 0FFFFh DW Offset PAS16Driver, SB16Driver DW Offset InterwaveDriver, Offset GUSDriver DW Offset AWE32Driver, Offset SBProDriver DW Offset SBDriver, Offset PCSpeakerDriver DW Offset SB2Driver, Offset PASDriver DW Offset WAVDriver, Offset WSSDriver DW Offset ESSDriver, MIDIDriver DW Offset EWSCodecDriver, VIVOCodecDriver DW Offset ST97PCICodecDriver, Offset MIDDRIVER DW Offset DefaultDriver, Offset VSoundMMXDriver DW Offset VSoundDriver DriverName DD 0 DriverDetectionOrder DW 19, 20, 21, 17, 16, 15, 13, 1, 10, 2, 12, 3, 4, 5, 6, 9, 7, 8, 0FFFFh DriverSoundCard DW 0, 8, 7, 9, 6 DW 2, 5, 4, 3, 10 DW 1, 12, 13, 15, 16 DW 0, 0, 0, 0, 14 DW 11, 18 ALIGN 4 PitchTable Label DWord DW 2048, 0, 2170, 0, 2299, 0, 2435, 0, 2580, 0, 2734, 0 DW 2896, 0, 3069, 0, 3251, 0, 3444, 0, 3649, 0, 3866, 0 DW 4096, 0, 4340, 0, 4598, 0, 4871, 0, 5161, 0, 5468, 0 DW 5793, 0, 6137, 0, 6502, 0, 6889, 0, 7298, 0, 7732, 0 DW 8192, 0, 8679, 0, 9195, 0, 9742, 0, 10321, 0, 10935, 0 DW 11585, 0, 12274, 0, 13004, 0, 13777, 0, 14596, 0, 15464, 0 DW 16384, 0, 17358, 0, 18390, 0, 19484, 0, 20643, 0, 21870, 0 DW 23170, 0, 24548, 0, 26008, 0, 27554, 0, 29193, 0, 30929, 0 DW 32768, 0, 34716, 0, 36781, 0, 38968, 0, 41285, 0, 43740, 0 DW 46341, 0, 49097, 0, 52016, 0, 55109, 0, 58386, 0, 61858, 0 DW 0, 1, 3897, 1, 8026, 1, 12400, 1, 17034, 1, 21944, 1 DW 27146, 1, 32657, 1, 38496, 1, 44682, 1, 51236, 1, 58179, 1 DW 0, 2, 7794, 2, 16051, 2, 24800, 2, 34068, 2, 43888, 2 DW 54292, 2, 65314, 2, 11456, 3, 23828, 3, 36936, 3, 50823, 3 DW 0, 4, 15588, 4, 32103, 4, 49600, 4, 2601, 5, 22240, 5 DW 43048, 5, 65092, 5, 22912, 6, 47656, 6, 8336, 7, 36110, 7 DW 0, 8, 31176, 8, 64205, 8, 33663, 9, 5201, 10, 44481, 10 DW 20559, 11, 64648, 11, 45823, 12, 29776, 13, 16671, 14, 6684, 15 DW 0, 16, 62352, 16, 62875, 17, 1790, 19, 10403, 20, 23425, 21 DW 41118, 22, 63761, 23, 26111, 25, 59552, 26, 33342, 28, 13368, 30 ; Pitch extention for loading some XIs DW 0, 32, 59167, 33, 60214, 35, 3580, 38, 20806, 40, 46850, 42 DW 16701, 45, 61986, 47, 52221, 50, 53567, 53, 1148, 57, 26736, 60 %IF USEFPUCODE FPSave DB 128 Dup (0) Const_14317456 DD 14317456.0 Const1_On_768 DD 3AAAAAABh SlideValue DW 0 NewControlWord DW 7Fh %ELSE FineLinearSlideUpTable Label DW 0, 1, 59, 1, 118, 1, 178, 1, 237, 1 ; 0->4 DW 296, 1, 356, 1, 415, 1, 475, 1, 535, 1 ; 5->9 DW 594, 1, 654, 1, 714, 1, 773, 1, 833, 1 ; 10->14 DW 893, 1 ; 15 LinearSlideUpTable Label ; Value = 2^(Val/192) DW 0, 1, 237, 1, 475, 1, 714, 1, 953, 1 ; 0->4 DW 1194, 1, 1435, 1, 1677, 1, 1920, 1, 2164, 1 ; 5->9 DW 2409, 1, 2655, 1, 2902, 1, 3149, 1, 3397, 1 ; 10->14 DW 3647, 1, 3897, 1, 4148, 1, 4400, 1, 4653, 1 ; 15->19 DW 4907, 1, 5157, 1, 5417, 1, 5674, 1, 5932, 1 ; 20->24 DW 6190, 1, 6449, 1, 6710, 1, 6971, 1, 7233, 1 ; 25->29 DW 7496, 1, 7761, 1, 8026, 1, 8292, 1, 8559, 1 ; 30->34 DW 8027, 1, 9096, 1, 9366, 1, 9636, 1, 9908, 1 ; 35->39 DW 10181, 1, 10455, 1, 10730, 1, 11006, 1, 11283,1 ; 40->44 DW 11560, 1, 11839, 1, 12119, 1, 12400, 1, 12682,1 ; 45->49 DW 12965, 1, 13249, 1, 13533, 1, 13819, 1, 14106,1 ; 50->54 DW 14394, 1, 14684, 1, 14974, 1, 15265, 1, 15557,1 ; 55->59 DW 15850, 1, 16145, 1, 16440, 1, 16737, 1, 17034,1 ; 60->64 DW 17333, 1, 17633, 1, 17933, 1, 18235, 1, 18538,1 ; 65->69 DW 18842, 1, 19147, 1, 19454, 1, 19761, 1, 20070,1 ; 70->74 DW 20379, 1, 20690, 1, 21002, 1, 21315, 1, 21629,1 ; 75->79 DW 21944, 1, 22260, 1, 22578, 1, 22897, 1, 23216,1 ; 80->84 DW 23537, 1, 23860, 1, 24183, 1, 24507, 1, 24833,1 ; 85->89 DW 25160, 1, 25488, 1, 25817, 1, 26148, 1, 26479,1 ; 90->94 DW 26812, 1, 27146, 1, 27481, 1, 27818, 1, 28155,1 ; 95->99 DW 28494, 1, 28834, 1, 29175, 1, 29518, 1, 29862,1 ; 100->104 DW 30207, 1, 30553, 1, 30900, 1, 31248, 1, 31599,1 ; 105->109 DW 31951, 1, 32303, 1, 32657, 1, 33012, 1, 33369,1 ; 110->114 DW 33726, 1, 34085, 1, 34446, 1, 34807, 1, 35170,1 ; 115->119 DW 35534, 1, 35900, 1, 36267, 1, 36635, 1, 37004,1 ; 120->124 DW 37375, 1, 37747, 1, 38121, 1, 38496, 1, 38872,1 ; 125->129 DW 39250, 1, 39629, 1, 40009, 1, 40391, 1, 40774,1 ; 130->134 DW 41158, 1, 41544, 1, 41932, 1, 42320, 1, 42710,1 ; 135->139 DW 43102, 1, 43495, 1, 43889, 1, 44285, 1, 44682,1 ; 140->144 DW 45081, 1, 45481, 1, 45882, 1, 46285, 1, 46690,1 ; 145->149 DW 47095, 1, 47503, 1, 47917, 1, 48322, 1, 48734,1 ; 150->154 DW 49147, 1, 49562, 1, 49978, 1, 50396, 1, 50815,1 ; 155->159 DW 51236, 1, 51658, 1, 52082, 1, 52507, 1, 52934,1 ; 160->164 DW 53363, 1, 53793, 1, 54224, 1, 54658, 1, 55092,1 ; 165->169 DW 55529, 1, 55966, 1, 56406, 1, 56847, 1, 57289,1 ; 170->174 DW 57734, 1, 58179, 1, 58627, 1, 59076, 1, 59527,1 ; 175->179 DW 59979, 1, 60433, 1, 60889, 1, 61346, 1, 61805,1 ; 180->184 DW 62265, 1, 62727, 1, 63191, 1, 63657, 1, 64124,1 ; 185->189 DW 64593, 1, 65064, 1, 0, 2, 474, 2, 950, 2 ; 190->194 DW 1427, 2, 1906, 2, 2387, 2, 2870, 2, 3355, 2 ; 195->199 DW 3841, 2, 4327, 2, 4818, 2, 5310, 2, 5803, 2 ; 200->204 DW 6298, 2, 6795, 2, 7294, 2, 7794, 2, 8296, 2 ; 205->209 DW 8800, 2, 9306, 2, 9814, 2, 10323, 2, 10835,2 ; 210->214 DW 11348, 2, 11863, 2, 12380, 2, 12899, 2, 13419,2 ; 215->219 DW 13942, 2, 14467, 2, 14993, 2, 15521, 2, 16051,2 ; 220->224 DW 16583, 2, 17117, 2, 17653, 2, 18191, 2, 18731,2 ; 225->229 DW 19273, 2, 19817, 2, 20362, 2, 20910, 2, 21460,2 ; 230->234 DW 22011, 2, 22565, 2, 23121, 2, 23678, 2, 24238,2 ; 235->239 DW 24800, 2, 25363, 2, 25929, 2, 25497, 2, 27067,2 ; 240->244 DW 27639, 2, 28213, 2, 28789, 2, 29367, 2, 29947,2 ; 245->249 DW 30530, 2, 31114, 2, 31701, 2, 32289, 2, 32880, 2 ; 250->254 DW 33473, 2, 34068, 2 ; 255->256 FineLinearSlideDownTable Label DW 65535, 65477, 65418, 65359, 65300, 65241, 65182, 65359 ; 0->7 DW 65065, 65006, 64947, 64888, 64830, 64772, 64713, 64645 ; 8->15 LinearSlideDownTable Label DW 65535, 65300, 65065, 64830, 64596, 64364, 64132, 63901 ; 0->7 DW 63670, 63441, 63212, 62984, 62757, 62531, 62306, 62081 ; 8->15 DW 61858, 61635, 61413, 61191, 60971, 60751, 60532, 60314 ; 16->23 DW 60097, 59880, 59664, 59449, 59235, 59022, 58809, 58597 ; 24->31 DW 58386, 58176, 57966, 57757, 57549, 57341, 57135, 56929 ; 32->39 DW 56724, 56519, 56316, 56113, 55911, 55709, 55508, 55308 ; 40->47 DW 55109, 54910, 54713, 54515, 54319, 54123, 53928, 53734 ; 48->55 DW 53540, 53347, 53155, 52963, 52773, 52582, 52393, 52204 ; 56->63 DW 52016, 51829, 51642, 51456, 51270, 51085, 50901, 50718 ; 64->71 DW 50535, 50353, 50172, 49991, 49811, 49631, 49452, 49274 ; 72->79 DW 49097, 48920, 48743, 48568, 48393, 48128, 48044, 47871 ; 80->87 DW 47699, 47527, 47356, 47185, 47015, 46846, 46677, 46509 ; 88->95 DW 46341, 46174, 46008, 45842, 45677, 45512, 45348, 45185 ; 96->103 DW 45022, 44859, 44698, 44537, 44376, 44216, 44057, 43898 ;104->111 DW 43740, 43582, 43425, 43269, 43113, 42958, 42803, 42649 ;112->119 DW 42495, 42342, 42189, 42037, 41886, 41735, 41584, 41434 ;120->127 DW 41285, 41136, 40988, 40840, 40639, 40566, 40400, 40253 ;128->135 DW 40110, 39965, 39821, 39678, 39535, 39392, 39250, 39109 ;136->143 DW 38968, 38828, 38688, 38548, 38409, 38271, 38133, 37996 ;144->151 DW 37859, 37722, 37586, 37451, 37316, 37181, 37047, 36914 ;152->159 DW 36781, 36648, 36516, 36385, 36254, 36123, 35993, 35863 ;160->167 DW 35734, 35605, 35477, 35349, 35221, 35095, 34968, 34842 ;168->175 DW 34716, 34591, 34467, 34343, 34219, 34095, 33973, 33850 ;176->183 DW 33728, 33607, 33486, 33365, 33245, 33125, 33005, 32887 ;184->191 DW 32768, 32650, 32532, 32415, 32298, 32182, 32066, 31950 ;192->199 DW 31835, 31720, 31606, 31492, 31379, 31266, 31153, 31041 ;200->207 DW 30929, 30817, 30706, 30596, 30485, 30376, 30226, 30157 ;208->215 DW 30048, 29940, 29832, 29725, 29618, 29511, 29405, 29299 ;216->223 DW 29193, 29088, 28983, 28879, 28774, 28671, 28567, 28464 ;224->231 DW 28362, 28260, 28158, 28056, 27955, 27855, 27754, 27654 ;232->239 DW 27554, 27455, 27356, 27258, 27159, 27062, 26964, 26867 ;240->247 DW 26770, 26674, 26577, 26482, 26386, 26291, 26196, 26102 ;248->255 DW 26008 ; 256 %ENDIF ; USEFPUCODE ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ InitCommandTable Label Word DW Offset InitNoCommand, Offset InitCommandA DW Offset InitCommandB, Offset InitCommandC DW Offset InitCommandD, Offset InitCommandE DW Offset InitCommandF, Offset InitCommandG DW Offset InitCommandH, Offset InitCommandI DW Offset InitCommandJ, Offset InitCommandK DW Offset InitCommandL, Offset InitCommandM DW Offset InitCommandN, Offset InitCommandO DW Offset InitCommandP, Offset InitCommandQ DW Offset InitCommandR, Offset InitCommandS DW Offset InitCommandT, Offset InitCommandU DW Offset InitCommandV, Offset InitCommandW DW Offset InitCommandX, Offset InitCommandY DW Offset InitCommandZ, Offset InitNoCommand DW Offset InitNoCommand, Offset InitNoCommand DW Offset InitNoCommand, Offset InitNoCommand CommandTable Label Word DW Offset NoCommand, Offset NoCommand DW Offset NoCommand, Offset NoCommand DW Offset CommandD, Offset CommandE DW Offset CommandF, Offset CommandG DW Offset CommandH, Offset CommandI DW Offset CommandJ, Offset CommandK DW Offset CommandL, Offset NoCommand DW Offset CommandN, Offset NoCommand DW Offset CommandP, Offset CommandQ DW Offset CommandR, Offset CommandS DW Offset CommandT, Offset CommandH DW Offset NoCommand, Offset CommandW DW Offset NoCommand, Offset CommandY DW Offset NoCommand, Offset NoCommand DW Offset NoCommand, Offset NoCommand VolumeEffectTable Label Word DW Offset NoCommand, Offset NoCommand ; Last 2 of command ; table + VolumeComA ; and VolumeComB DW Offset VolumeCommandC, Offset VolumeCommandD DW Offset VolumeCommandE, Offset VolumeCommandF DW Offset VolumeCommandG, Offset CommandH RetrigOffsets Label DW CommandQ_0, CommandQ_1, CommandQ_2, CommandQ_3 DW CommandQ_4, CommandQ_5, CommandQ_6, CommandQ_7 DW CommandQ_8, CommandQ_9, CommandQ_A, CommandQ_B DW CommandQ_C, CommandQ_D, CommandQ_E, CommandQ_F ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Sound Driver Data ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ %IF OLDDRIVER DriverID DB "Impulse Tracker Sound Driver" %ELSE DriverID DB "Impulse Tracker Advanced Sound Driver" %ENDIF ALIGN 2 SoundDriverSegment DW 0 ;******************* DriverVariableTable Label DriverMaxChannels DW 32 StopEndOfPlaySection DW 0 DefaultChannels DW 32 DriverFlags DW 0 ; Bit 1 = MIDI Out supported ; Bit 2 = Hiqual ; Bit 3 = Output waveform data available %IF OLDDRIVER DB 64 - ($ - DriverVariableTable) Dup (0) %ELSE DB 16 - ($ - DriverVariableTable) Dup (0) %ENDIF ALIGN 4 StartDriverFunctions Label DriverDetectCard DD 0 DriverInitSound DD 0 DriverReinitSound DD 0 DriverUninitSound DD 0 DriverPoll DD 0 DriverSetTempo DD 0 DriverSetMixVolume DD 0 DriverSetStereo DD 0 DriverLoadSample DD 0 DriverReleaseSample DD 0 DriverResetMemory DD 0 DriverGetStatus DD 0 DriverSoundCardScreen DD 0 DriverGetVariable DD 0 DriverSetVariable DD 0 DriverMIDIOut DD 0 DriverGetWaveform DD 0 EndDriverFunctions Label %IF OLDDRIVER DD 63-(EndDriverFunctions-StartDriverFunctions)/4 Dup (0) %ELSE DD 31-(EndDriverFunctions-StartDriverFunctions)/4 Dup (0) %ENDIF DW 0 DriverLength DW 0 DriverRequiredFunctions Label DD DWord Ptr Update DD DWord Ptr Music_GetSampleHeader DD DWord Ptr Music_GetSampleLocation DD DWord Ptr Music_FarUpdateSampleLocation DD DWord Ptr E_GetEMSPageFrame DD DWord Ptr E_SaveEMSPageFrame DD DWord Ptr E_RestoreEMSPageFrame DD DWord Ptr Music_GetTempo DD DWord Ptr M_FunctionHandler DD DWord Ptr SetInfoLine2 DD DWord Ptr Music_SoundCardLoadAllSamples DD DWord Ptr GlobalKeyList DD DWord Ptr IdleUpdateInfoLine DD DWord Ptr F_DrawHeader DD DWord Ptr PE_FillHeader DD DWord Ptr D_GotoStartingDirectory DD DWord Ptr D_GetFileName DD DWord Ptr D_SetDriveDirectoryFar DD DWord Ptr Music_Stop DD DWord Ptr GetEnvironment DD DWord Ptr Music_GetSlaveChannelInformationTable DD DWord Ptr RecalculateAllVolumes DD DWord Ptr MIDIBufferEmpty DD DWord Ptr MIDISend DD DWord Ptr S_GetDestination DD DWord Ptr S_DrawString ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Functions ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Command/Effect (call it what you like) information here!! ³ ;³ ³ ;³ For initialisation, DS:DI points to host channel data. ³ ;³ Registers for use: All except DS:DI & ES (points to SongDataSegment) ³ ;³ ³ ;³ For update, DS:DI points to host channel data. ³ ;³ Registers for use: AX, BX, DX, ES, SI ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Proc RecalculateAllVolumes Far Mov CX, NumChannels Mov SI, Offset SlaveChannelInformationTable RecalculateAllVolumes1: Or Byte Ptr [SI], 18 Add SI, SLAVECHANNELSIZE Dec CX JNZ RecalculateAllVolumes1 Ret ;EndP RecalculateAllVolumes ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc InitPlayInstrument ; BX = instrument offset Push ECX Mov [SI+30h], BX ; InsOffset Mov AL, [ES:BX+11h] ; NNA Mov [SI+3Bh], AL Mov AX, [ES:BX+12h] ; DCT and DCA Mov [SI+28h], AX Mov AX, [DI+0Ch] ; MCh and MPr Test AL, AL JZ InitPlayInstrumentNoMIDI Mov [SI+3Ch], AX Mov AX, [ES:BX+3Eh] ; MidiBank Mov [SI+3Eh], AX Mov AL, [DI+3] Mov [SI+0Bh], AL InitPlayInstrumentNoMIDI: Mov DX, [DI+2Eh] ; ChannelVol=DH, Pan=DL Mov AL, [ES:BX+19h] ; Instrument pan Mov [SI+23h], DH Test AL, 80h JNZ AllocatePan1 Mov DL, AL AllocatePan1: Push BX ; Check for sample pan Mov BL, [DI+0Fh] And BX, 0FFh JZ InitPlayInstrumentNoSamplePan Add BX, BX Mov BX, [ES:64910+BX] ; BX = sample offset Mov AL, [ES:BX+2Fh] Test AL, AL JNS InitPlayInstrumentNoSamplePan And AL, 7Fh Mov DL, AL InitPlayInstrumentNoSamplePan: Pop BX Cmp DL, 100 JE AllocatePanSurround Xor DH, DH Mov AL, [DI+3] ; Note Mov CX, [ES:BX+16h] ; Pitch pan separation Sub AL, CH IMul CL SAR AX, 3 Add AX, DX JS AllocatePan2 Cmp AX, 64 JBE AllocatePan3 Mov AL, 64 Jmp AllocatePan3 AllocatePan2: Xor AL, AL Jmp AllocatePan3 AllocatePanSurround: Mov AL, 100 AllocatePan3: Mov AH, AL Xor ECX, ECX ; Envelope init Mov [SI+2Ah], AX ; Write panning Mov [SI+58h], ECX Mov [SI+5Ch], CX Mov [SI+60h], ECX Mov [SI+68h], ECX Mov [SI+6Ch], CX Mov [SI+70h], ECX Mov [SI+78h], ECX Mov [SI+7Ch], CX Mov DWord Ptr [SI+50h], 400000h ; 64*65536 Mov AH, [ES:BX+1D4h] Mov AL, [ES:BX+182h] And AX, 101h ShL AH, 1 Or AH, AL Mov AL, [ES:BX+130h] ShL AH, 1 And AL, 1 Or AH, AL ShL AH, 4 Or AX, 133h Mov Word Ptr [SI], AX Push DI Mov DI, LastSlaveChannel Test DI, DI JZ InitInstrumentCarry InitInstrumentVolumeCarry: Mov AL, [ES:BX+130h] And AL, 9 Cmp AL, 9 JNE InitInstrumentPanCarry ; Transfer volume data Mov ECX, [DI+50h] Mov EDX, [DI+54h] Mov [SI+50h], ECX Mov [SI+54h], EDX Mov ECX, [DI+58h] Mov DX, [DI+5Ch] Mov [SI+58h], ECX Mov [SI+5Ch], DX InitInstrumentPanCarry: Mov AL, [ES:BX+182h] And AL, 9 Cmp AL, 9 JNE InitInstrumentPitchCarry ; Transfer pan data Mov ECX, [DI+60h] Mov EDX, [DI+64h] Mov [SI+60h], ECX Mov [SI+64h], EDX Mov ECX, [DI+68h] Mov DX, [DI+6Ch] Mov [SI+68h], ECX Mov [SI+6Ch], DX InitInstrumentPitchCarry: Mov AL, [ES:BX+1D4h] And AL, 9 Cmp AL, 9 JNE InitInstrumentCarry ; Transfer pitch data Mov ECX, [DI+70h] Mov EDX, [DI+74h] Mov [SI+70h], ECX Mov [SI+74h], EDX Mov ECX, [DI+78h] Mov DX, [DI+7Ch] Mov [SI+78h], ECX Mov [SI+7Ch], DX InitInstrumentCarry: Pop DI Or Byte Ptr [DI], 80h ; Apply random volume/pan Cmp Byte Ptr [DI+0Ch], 0 JNE InitPlayInstrumentNoSample Push BX Mov BX, [ES:BX+3Ah] ; Initial filter cutoff ; If IFC bit 7 == 1, then set filter cutoff Mov Word Ptr [SI+3Eh], 0FFh ; Test BL, 8080h ; JNZ InitPlayInstrumentFilter ; ;; No filters, reset devices. ; Mov BL, 7Fh ; Call SetFilterCutoff ; Xor BL, BL ; Call SetFilterResonance ; ; Jmp InitPlayInstrumentFilterResonance ; ;InitPlayInstrumentFilter: Test BL, BL JNS InitPlayInstrumentFilterCutoff And BL, 7Fh ; Mov [SI+3Eh], BL Call SetFilterCutoff InitPlayInstrumentFilterCutoff: ; If IFR bit 7 == 1, then set filter resonance Test BX, BX JNS InitPlayInstrumentFilterResonance Mov BL, BH And BL, 7Fh Mov [SI+3Fh], BL Call SetFilterResonance InitPlayInstrumentFilterResonance: Pop BX InitPlayInstrumentNoSample: Pop ECX Ret ;EndP InitPlayInstrument ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc ApplyRandomValues Mov SI, [DI+24h] Mov BX, [SI+30h] And Byte Ptr [DI], Not 80h Call Random ; AL = -128->+127 Mov AH, [ES:BX+1Ah] ; Random volume, 0->100 Test AH, AH JZ RandomVolumeEnd IMul AH ; AX = -12800->12700 SAR AX, 6 ; AX = -200->+198(.4) Inc AX ; AX = -199->+199 MovZX DX, Byte Ptr [SI+24h] ; Sample volume set Mov CX, 199 Push DX IMul DX ; AX = -199*128->199*128 ; AX = -25472->25472 IDiv CX ; AX = -128->+128 Pop CX Add AX, CX Cmp AX, 0 JL RandomVolume3 Cmp AX, 128 JG RandomVolume4 Mov [SI+24h], AL Jmp RandomVolumeEnd RandomVolume3: Mov Byte Ptr [SI+24h], 0 Jmp RandomVolumeEnd RandomVolume4: Mov Byte Ptr [SI+24h], 128 RandomVolumeEnd: Call Random ; AL = -128->+127 Mov AH, [ES:BX+1Bh] ; Random pan, 0->64 Test AH, AH JZ RandomPanEnd Xor DX, DX IMul AH ; AX = -64*128->64*127, -8192->8128 Mov DL, [SI+2Ah] SAR AX, 7 Cmp DL, 100 JE RandomPanEnd Add DX, AX JS RandomPan1 Cmp DX, 64 JA RandomPan2 Mov DH, DL Mov [SI+2Ah], DX Ret RandomPan2: Mov Word Ptr [SI+2Ah], 4040h Ret RandomPan1: Mov Word Ptr [SI+2Ah], 0 RandomPanEnd: Ret ;EndP ApplyRandomValues ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ LastMIDIByte DB 0FFh Proc MIDISendFilter Test CS:DriverFlags, 1 JZ MIDISendFilter2 Test AL, AL JNS MIDISendFilter1 Cmp AL, 0F0h JAE MIDISendFilter1 Cmp AL, CS:LastMIDIByte JE MIDISendFilter2 Mov CS:LastMIDIByte, AL MIDISendFilter1: Call DriverMIDIOut MIDISendFilter2: Ret ;EndP MIDISendFilter ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc SetFilterCutoff ; Given BL = filtervalue. ; Assumes that channel is non-disowned Push DI Mov DI, [SI+38h] Mov AL, 0F0h Call MIDISendFilter Mov AL, 0F0h Call MIDISendFilter Xor AL, AL Call MIDISendFilter Mov AL, BL Call MIDISendFilter Pop DI Ret ;EndP SetFilterCutoff ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc SetFilterResonance ; Given BL = filtervalue. ; Assumes that channel is non-disowned Push DI Mov DI, [SI+38h] Mov AL, 0F0h Call MIDISendFilter Mov AL, 0F0h Call MIDISendFilter Mov AL, 1 Call MIDISendFilter Mov AL, BL Call MIDISendFilter Pop DI Ret ;EndP SetFilterResonance ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MIDIPitchDepthSent DW 0 Proc MIDITranslate ; Assumes DS:SI points to slave ; And DS:DI points to host. ; BX = offset of MIDI command to interpret ;Assume DS:Music Test DriverFlags, 1 JZ MIDITranslateEnd PushA Cmp BX, 0F000h JB MIDITranslateParameterised ; Internal MIDI commands. Test Byte Ptr [ES:2Ch], 64 ; Do pitch wheel? JZ MIDITranslateInternalEnd ; Pitch wheel ; Formula is: Depth = 16384*12 / PitchWheelDepth * log2(Freq / OldFreq) ; Do calculation, check whether pitch needs to be sent. Xor EAX, EAX Mov AL, [ES:35h] ; AL = PWD Test AL, AL ; No depth! JZ MIDITranslateInternalEnd Mov DWord Ptr [ChannelCountTable+200], EAX ; scratch area %IF E USEFPUCODE ; If FPU code is being used, FP registers are already saved FNSave [ChannelCountTable] ; Scratch area FNInit %ENDIF FLd [PitchDepthConstant] FIDiv DWord Ptr [ChannelCountTable+200] FILd DWord Ptr [SI+10h] ; Current pitch FIDiv DWord Ptr [SI+1Ch] ; Original pitch FYL2X FIStP DWord Ptr [ChannelCountTable+200] %IF E USEFPUCODE FRstor [ChannelCountTable] %ENDIF ; OK.. [ChannelCountTable] contains pitch depth. ; Have to check: ; a) Within ranges? ; b) Comparison to old pitch for this channel Mov CL, [SI+3Ch] Mov AX, 1 Dec CL JS MIDITranslateInternalEnd Cmp DWord Ptr [ChannelCountTable+200], 0 JE MIDIPitchDepthSent1 ShL AX, CL Test MIDIPitchDepthSent, AX JNZ MIDIPitchDepthSent1 Or MIDIPitchDepthSent, AX ; Send MIDI Pitch depth stuff Push SI Mov AL, 0B0h Or AL, CL Call MIDISendFilter Mov DX, 5 Mov SI, Offset MIDIPitchSendString Music_SendPitchDepth1: LodsB Call MIDISendFilter Dec DX JNZ Music_SendPitchDepth1 Pop SI Mov AL, [ES:35h] Call MIDISendFilter MIDIPitchDepthSent1: Mov EAX, DWord Ptr [ChannelCountTable+200] Add EAX, 2000h JNS PitchRange1 Xor EAX, EAX PitchRange1: Cmp EAX, 4000h JL PitchRange2 Mov AX, 3FFFh PitchRange2: Mov BL, [SI+3Ch] ; BL = channel And BX, 0FFh Add BX, BX Cmp [MIDIPitch+BX-2], AX JE MIDITranslateInternalEnd Mov [MIDIPitch+BX-2], AX ; Output pitch change Mov AL, 0E0h Or AL, CL Call MIDISendFilter ; Ec command Mov AL, Byte Ptr [MIDIPitch+BX-2] And AL, 7Fh Call MIDISendFilter Mov AX, [MIDIPitch+BX-2] ShR AX, 7 And AL, 7Fh Call MIDISendFilter MIDITranslateInternalEnd: PopA Ret ; Now for user input MIDI stuff. MIDITranslateParameterised: Push FS Xor AX, AX Xor CX, CX Mov FS, MIDIDataArea MIDITranslate1: Mov AH, [FS:BX] Inc BX Test AH, AH JZ MIDITranslate2 Cmp AH, ' ' ; Interpretation time. JNE MIDITranslateNoSpace Test CX, CX JZ MIDITranslate1 Jmp MIDITranslateSend MIDITranslateNoSpace: Sub AH, '0' JC MIDITranslate1 Cmp AH, 9 JA MIDITranslateValue1 ShL AL, 4 Or AL, AH Inc CX Jmp MIDITranslateValueEnd MIDITranslateValue1: Sub AH, 'A'-'0' JC MIDITranslate1 Cmp AH, 'F'-'A' JA MIDITranslateValue2 ShL AL, 4 Add AH, 10 Or AL, AH Inc CX Jmp MIDITranslateValueEnd MIDITranslateValue2: Sub AH, 'a'-'A' JC MIDITranslate1 Cmp AH, 'z'-'a' JA MIDITranslate1 Cmp AH, 'c'-'a' JNE MIDITranslateValue3 Test SI, SI JZ MIDITranslate1 ; Mov AH, [DI+0Ch] Mov AH, [SI+3Ch] ShL AL, 4 Dec AH Or AL, AH Inc CX Jmp MIDITranslateValueEnd MIDITranslateValue3: Test CX, CX JZ MIDITranslateValue4 Call MIDISendFilter Xor CX, CX MIDITranslateValue4: Mov AL, [DI+7] ; Effect. Cmp AH, 'z'-'a' ; Zxx? JE MIDITranslateSend Mov AL, [DI+12h] Cmp AH, 'o'-'a' JE MIDITranslateSend Test SI, SI JZ MIDITranslate1 Mov AL, [SI+32h] ; [DI+0Eh] Cmp AH, 'n'-'a' ; Note? JE MIDITranslateSend Mov AL, [SI+0Bh] Cmp AH, 'm'-'a' JE MIDITranslateSend Cmp AH, 'v'-'a' ; Velocity? JNE MIDITranslateValue7 Xor AL, AL Test Word Ptr [SI], 800h JNZ MIDITranslateSend Mov AL, [SI+22h] ; 0->2^6 Xor DX, DX Mul GlobalVolume ; 0->2^13 Mov DL, [SI+23h] ; Channel volume Mul DX ; 0->2^19 SHRD AX, DX, 4 ; 0->2^15 Mov DL, [SI+24h] ; Sample & Instrument Volume Mul DX ; 0->2^22 SHRD AX, DX, 15 ; 0->2^7 Sub AL, 1 AdC AL, 1 ; 1->2^7 JNS MIDITranslateSend Dec AX ; Mov AL, 7Fh Jmp MIDITranslateSend Comment ~ Mov AL, [SI+22h] ; 0->64 Add AL, AL ; 0->128 Sub AL, 1 AdC AL, 1 ; 1->128 Cmp AL, 128 JB MIDITranslateSend Dec AX Jmp MIDITranslateSend ~ MIDITranslateValue7: Cmp AH, 'u'-'a' ; Volume? JNE MIDITranslateValue8 Xor AL, AL Test Word Ptr [SI], 800h JNZ MIDITranslateSend Mov AL, [SI+20h] ; 0->128 Sub AL, 1 AdC AL, 1 ; 1->128 Cmp AL, 128 JB MIDITranslateSend Dec AX Jmp MIDITranslateSend MIDITranslateValue8: Mov AL, [SI+3Ah] ; HCN And AL, 7Fh Cmp AH, 'h'-'a' JE MIDITranslateSend Mov AL, [SI+2Ah] ; Pan set Cmp AH, 'x'-'a' JE MIDITranslatePanValue Mov AL, [SI+25h] ; Final pan Cmp AH, 'y'-'a' JE MIDITranslatePanValue Mov AL, [SI+3Dh] Cmp AH, 'p'-'a' ; Program? JE MIDITranslateSend Mov DX, [SI+3Eh] Mov AL, DL Add AL, 1 AdC AX, 0 Dec AX Cmp AH, 'b'-'a' JE MIDITranslateSend Mov AL, DH Add AL, 1 AdC AX, 0 Dec AX Cmp AH, 'a'-'a' JE MIDITranslateSend Xor AX, AX Jmp MIDITranslate1 MIDITranslatePanValue: Add AL, AL Cmp AL, 7Fh JBE MIDITranslateSend Dec AX Cmp AL, 7Fh JBE MIDITranslateSend Mov AL, 40h Jmp MIDITranslateSend MIDITranslateValueEnd: Cmp CL, 2 JB MIDITranslate1 MIDITranslateSend: Call MIDISendFilter Xor AX, AX Xor CX, CX Jmp MIDITranslate1 MIDITranslate2: Test CX, CX JZ MIDITranslate3 Call MIDISendFilter MIDITranslate3: Pop FS PopA MIDITranslateEnd: Ret ;EndP MIDITranslate ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc AllocateChannel ; Returns SI. Carry set if problems ;Assume DS:Music Push CX Mov LastSlaveChannel, 0 Test Byte Ptr [ES:2Ch], 4 JNZ AllocateChannel1 AllocateChannel15: ; Sample handler MovZX SI, Byte Ptr [DI+20h] Mov AX, SI ShL SI, 7 ; SLAVECHANNELSIZE Add SI, Offset SlaveChannelInformationTable Test Byte Ptr CS:DriverFlags, 2 JZ AllocateChannelHiQual1 Test Byte Ptr [SI], 1 ; Channel on? JZ AllocateChannelHiQual1 ; copy out channel Push CX Push SI Push DI Push ES Push DS Pop ES Or Word Ptr [SI], 200h Or Byte Ptr [SI+3Ah], 80h LEA DI, [SI+64*SLAVECHANNELSIZE] Mov CX, SLAVECHANNELSIZE/4 Rep MovsD Pop ES Pop DI Pop SI Pop CX AllocateChannelHiQual1: Mov [DI+24h], SI Mov [SI+38h], DI Mov [SI+3Ah], AL Mov Word Ptr [SI], 133h ; Recalc freq,vol&pan Channel on. Mov AX, [DI+2Eh] ; ChannelVol=AH, Pan=AL Mov [SI+23h], AH Mov AH, AL Mov [SI+2Ah], AX ; Get sample offset. AllocateChannel3: ; General stuff. Pop CX Mov Word Ptr [SI+26h], 0400h ; FadeOut Mov Word Ptr [SI+52h], 64 Mov Word Ptr [SI+3Eh], 0FFh ; Filter cutoff Mov AX, [DI+3] Mov [SI+32h], AX ; Nte&Ins Mov BL, [DI+0Fh] And BX, 0FFh JZ AllocateChannel21 Dec BX Call I_TagSample Mov [SI+36h], BL Add BX, BX Mov BX, [ES:64912+BX] Mov [SI+34h], BX ; Sample memory offset. Xor EAX, EAX Mov [SI+18h], EAX ; Reset vibrato info. Mov Word Ptr [SI+62h], AX ; No pan deviation Mov Word Ptr [SI+72h], AX ; No pitch deviation Mov Byte Ptr [SI+0Bh], AL ; Reset loop dirn Cmp [ES:BX+30h], EAX ; No sample! JE AllocateChannel21 Mov AX, [ES:BX+11h] Test AH, 1 JZ AllocateChannel21 ; No sample! And AH, 2 Add AL, AL Mov [SI+18h], AH Mov [SI+24h], AL ; Sample volume ClC Ret AllocateChannel21: Mov Word Ptr [SI], 200h And CH, Not 4 StC Ret AllocateChannel5: Pop CX StC Ret AllocateChannel1: ; Instrument handler! Mov DX, NumChannels Mov AllocateSlaveOffset, Offset SlaveChannelInformationTable Mov AllocateNumChannels, DX Mov BX, MAXSLAVECHANNELS Cmp Byte Ptr [DI+0Fh], 101 JNE AllocateChannelNoMIDI Cmp DX, BX JE AllocateChannelNoMIDI Sub BX, DX ; CX = number of channels remaining ShL DX, 7 Mov AllocateNumChannels, BX Add DX, Offset SlaveChannelInformationTable Mov AllocateSlaveOffset, DX AllocateChannelNoMIDI: Mov BL, [DI+4] Cmp BL, 0FFh JE AllocateChannel15 And EBX, 0FFh JZ AllocateChannel5 Call I_TagInstrument Mov BX, [ES:64710+EBX*2] ; ES:BX points to instrument Test CH, 4 ; Test Byte Ptr [DI], 4 JZ AllocateChannel8 ; New note action handling... Mov SI, [DI+24h] Cmp [SI+30h], BX JNE AllocateLastChannelDifferentInstrument Mov LastSlaveChannel, SI AllocateLastChannelDifferentInstrument: Mov AL, [SI+3Bh] Test AL, AL JZ AllocateChannel20 ; Notecut. Or Byte Ptr [SI+3Ah], 80h ; Disown channel AllocateHandleNNA: Cmp Byte Ptr [SI+22h], 0 ; Is volume set = 0? JE AllocateChannel20 Cmp Byte Ptr [SI+23h], 0 ; Is channel volume = 0? JE AllocateChannel20 Cmp Byte Ptr [SI+24h], 0 ; Is sample volume = 0? JE AllocateChannel20 Cmp AL, 2 JB AllocateChannel8 ; Note continue JE AllocateChannel14 ; Note off. ; AL = 3 -> Fade Or Byte Ptr [SI], 8 ; Fade flag. Jmp AllocateChannel8 AllocateChannel14: Or Byte Ptr [SI], 4 ; Note off.. Push BX Call GetLoopInformation Pop BX Jmp AllocateChannel8 AllocateChannel20MIDI: Or Word Ptr [SI], 200h Or Byte Ptr [SI+3Ah], 80h ; Disown channel Cmp Byte Ptr [DI+0Fh], 101 JNE AllocateChannel4 ; Sample.. AllocateChannelMIDIDC: Mov SI, AllocateSlaveOffset Mov CX, AllocateNumChannels Mov DL, [DI+0Eh] Mov DH, [DI+4] Mov BP, 32h Mov AH, [DI+0Ch] Mov CH, [ES:BX+13h] ; CH = DCA Jmp AllocateChannel6 AllocateChannel20: Cmp Byte Ptr [SI+36h], 100 ; MIDI? JE AllocateChannel20MIDI AllocateChannel20Samples: Test Byte Ptr CS:DriverFlags, 2 JNZ AllocateChannelHiQual Mov AL, [ES:BX+12h] Mov Word Ptr [SI], 200h Test AL, AL JZ AllocateChannelInstrument Jmp AllocateChannel11 AllocateChannelHiQual: Or Word Ptr [SI], 200h Or Byte Ptr [SI+3Ah], 80h ; Disown channel Jmp AllocateChannel4 AllocateChannel8: Cmp Byte Ptr [DI+0Fh], 101 JE AllocateChannelMIDIDC Mov AL, [ES:BX+12h] Test AL, AL JZ AllocateChannel4 ; Duplicate check off. AllocateChannel11: ; Duplicate check... Mov SI, AllocateSlaveOffset Mov CX, AllocateNumChannels Mov DX, [DI+3] ; DX = note Mov BP, 32h Cmp AL, 1 JE AllocateDCT Mov BP, 33h ; Duplicate instrument Mov DL, DH Cmp AL, 3 JE AllocateDCT Mov BP, 36h ; Duplicate sample Mov DL, [DI+0Fh] Dec DL JS AllocateChannel4 AllocateDCT: Mov AH, [DI+20h] ; AH = HCN Or AH, 80h Mov CH, [ES:BX+13h] ; CH = DCA AllocateChannel6: Test Byte Ptr [SI], 1 JZ AllocateChannel7 Cmp Byte Ptr [DI+0Fh], 101 JE AllocateChannelMIDIDCT Mov AL, [SI+3Ah] ; AL = HCN of slave. Cmp AH, AL JNE AllocateChannel7 ; OK. same channel... now.. AllocateChannelMIDIDCT: Cmp DH, [SI+33h] ; Same inst? JNE AllocateChannel7 Cmp DL, [DS:SI+BP] ; Same note/sample/inst? JNE AllocateChannel7 Cmp Byte Ptr [DI+0Fh], 101 ; New note is a MIDI? JE AllocateChannelMIDIHandling Cmp CH, [SI+29h] JNE AllocateChannel7 Test CH, CH ; Checks for hiqual JZ AllocateChannel20Samples Mov Word Ptr [SI+28h], 0 Mov AL, CH Inc AX Jmp AllocateHandleNNA AllocateChannelMIDIHandling: Cmp Byte Ptr [SI+36h], 100 ; Is current channel a MIDI chan JNE AllocateChannel7 Cmp AH, [SI+3Ch] JNE AllocateChannel7 Or Word Ptr [SI], 200h Test Byte Ptr [SI+3Ah], 80h JNZ AllocateChannel7 Mov BP, [SI+38h] Or Byte Ptr [SI+3Ah], 80h And Byte Ptr [DS:BP], Not 4 AllocateChannel7: Add SI, SLAVECHANNELSIZE Dec CL JNZ AllocateChannel6 AllocateChannel4: Mov CX, AllocateNumChannels Mov SI, AllocateSlaveOffset Cmp Byte Ptr [DI+0Fh], 101 JNE AllocateChannel10 ; MIDI 'slave channels' have to be maintained if still referenced Push DI AllocateMIDIChannel1: Test Byte Ptr [SI], 1 JNZ AllocateMIDIChannel2 ; Have a channel.. check that it's host's slave isn't SI Mov DI, [SI+38h] Test DI, DI JZ AllocateMIDIChannelFound Cmp SI, [DI+24h] JNE AllocateMIDIChannelFound AllocateMIDIChannel2: Add SI, SLAVECHANNELSIZE Dec CX JNZ AllocateMIDIChannel1 Pop DI Jmp AllocateChannel17 AllocateChannel10: Test Byte Ptr [SI], 1 JZ AllocateChannelInstrument Add SI, SLAVECHANNELSIZE Dec CX JNZ AllocateChannel10 AllocateChannel17: ; Common sample search Push BX Push DI Push ES Push CS Pop ES Mov DI, Offset ChannelCountTable Xor AX, AX Mov CX, (100+200)/2 Rep StosW ; Clear table Dec AX Mov CX, 100/2 ; Volumes Rep StosW Pop ES Mov CX, AllocateNumChannels Xor EBX, EBX Mov DI, AllocateSlaveOffset AllocateChannelCommonSample1: Mov BL, [DI+36h] ; BX = sample pointer into ; table. Cmp BL, 99 ; Just for safety JA AllocateChannelCommonSample2 Inc Byte Ptr [ChannelCountTable+BX] Mov AH, [ChannelCountTable+BX+300] ; Volume Test Byte Ptr [DI+3Ah], 80h ; Disowned channel? JZ AllocateChannelCommonSample2 Cmp AH, [DI+20h] ; Lower Volume? JBE AllocateChannelCommonSample2 Mov AH, [DI+20h] ; Get volume Mov Word Ptr [ChannelCountTable+EBX+EBX+100], DI ; Store location Mov [ChannelCountTable+BX+300], AH ; Store volume AllocateChannelCommonSample2: Add DI, SLAVECHANNELSIZE Dec CX JNZ AllocateChannelCommonSample1 ; OK.. now search table for maximum ; occurrence of sample... Xor EDI, EDI Xor SI, SI Mov AH, 2 ; Find maximum count, has to be ; greater than 2 channels Mov CX, 100 AllocateChannelCommonSample3: Cmp AH, [ChannelCountTable+DI] JAE AllocateChannelCommonSample4 Mov AH, [ChannelCountTable+DI] Mov SI, Word Ptr [ChannelCountTable+EDI+EDI+100] AllocateChannelCommonSample4: Inc DI Dec CX JNZ AllocateChannelCommonSample3 Pop DI Pop BX ; Inc AllocateCount1 Test SI, SI JNZ AllocateChannelInstrument ; Dec AllocateCount1 ; Find out which host channel has the most ; (disowned) slave channels ; Then find the softest non-single sample ; in that channel. Push BX Push ES Push DI Push CS Pop ES Mov DI, Offset ChannelCountTable Xor AX, AX Mov CX, 32 Rep StosW Pop DI Pop ES Xor BX, BX Mov CX, AllocateNumChannels Mov SI, AllocateSlaveOffset AllocateChannelCount1: Mov BL, [SI+3Ah] ; Host channel number And BL, 3Fh Inc Byte Ptr [ChannelCountTable+BX] AllocateChannelCount2: Add SI, SLAVECHANNELSIZE Dec CX JNZ AllocateChannelCount1 AllocateChannelCountEnd: ; OK.. search through and find ; the most heavily used channel Mov AX, 100h ; AH = channel count Xor BX, BX ; AL = channel Mov CX, 64 ; 64 = physical channels AllocateChannelCountSearch1: Cmp AH, [BX+ChannelCountTable] JAE AllocateChannelCountSearch2 Mov AH, [BX+ChannelCountTable] Mov AL, BL AllocateChannelCountSearch2: Inc BX Dec CX JNZ AllocateChannelCountSearch1 Pop BX ; AH = channel to use. Cmp AH, 1 JBE AllocateChannelSoftestSearch Or AL, 80h ; Search for disowned only Push BX Push DI Mov BH, [DI+0Fh] Dec BH Mov CX, AllocateNumChannels Mov DI, AllocateSlaveOffset Xor SI, SI ; Offset Mov AH, 0FFh AllocateChannelNonSingle1: Cmp AL, [DI+3Ah] JNE AllocateChannelNonSingle3 Cmp AH, [DI+20h] ; Lower Volume? JBE AllocateChannelNonSingle3 ; Now check if any other ; channel contains this ; sample Cmp BH, [DI+36h] JE AllocateChannelNonSingle6 Push CX Push SI Mov BL, [DI+36h] ; Sample number Mov Byte Ptr [DI+36h], 0FFh Mov SI, AllocateSlaveOffset Mov CX, AllocateNumChannels AllocateChannelNonSingle2: Cmp BH, [SI+36h] JE AllocateChannelNonSingle5 Cmp BL, [SI+36h] ; A second sample? JE AllocateChannelNonSingle5 AllocateChannelNonSingle4: Add SI, SLAVECHANNELSIZE Dec CX JNZ AllocateChannelNonSingle2 Mov [DI+36h], BL Pop SI Pop CX Jmp AllocateChannelNonSingle3 AllocateChannelNonSingle5: Mov [DI+36h], BL Pop SI Pop CX AllocateChannelNonSingle6: ; OK found a second sample. Mov SI, DI ; get offset. Mov AH, [DI+20h] ; Get volume AllocateChannelNonSingle3: Add DI, SLAVECHANNELSIZE Dec CX JNZ AllocateChannelNonSingle1 Pop DI Pop BX Test SI, SI JNZ AllocateChannelSampleSearch ; JNZ AllocateChannelInstrument Push BX Mov SI, AX And SI, 03Fh Mov Byte Ptr [ChannelCountTable+SI], 0 Jmp AllocateChannelCountEnd ; Next cycle... AllocateChannelSampleSearch: ; Inc AllocateCount2 Push DI Mov AL, [SI+36h] Mov CX, AllocateNumChannels Mov DI, AllocateSlaveOffset Mov AH, 0FFh AllocateChannelSampleSearch1: Cmp AL, [DI+36h] ; Same sample? JNE AllocateChannelSampleSearch2 Test Byte Ptr [DI+3Ah], 80h ; Disowned channel? JZ AllocateChannelSampleSearch2 Cmp AH, [DI+20h] ; Lower Volume? JBE AllocateChannelSampleSearch2 Mov SI, DI ; get offset. Mov AH, [DI+20h] ; Get volume AllocateChannelSampleSearch2: Add DI, SLAVECHANNELSIZE Dec CX JNZ AllocateChannelSampleSearch1 Pop DI Jmp AllocateChannelInstrument AllocateChannelSoftestSearch: Push DI ; Now search for softest ; disowned sample ; (not non-single) Mov CX, AllocateNumChannels Mov DI, AllocateSlaveOffset Xor SI, SI ; Offset Mov AH, 0FFh AllocateChannel18: Test Byte Ptr [DI+3Ah], 80h ; Disowned??? JZ AllocateChannel19 ; No.. then look for next Cmp AH, [DI+20h] ; Volume set... JB AllocateChannel19 Mov SI, DI ; get offset. Mov AH, [DI+20h] ; Get volume AllocateChannel19: Add DI, SLAVECHANNELSIZE Dec CX JNZ AllocateChannel18 Pop DI ; Inc AllocateCount3 Test SI, SI JNZ AllocateChannelInstrument Pop CX And CH, Not 4 StC Ret AllocateMIDIChannelFound: Pop DI AllocateChannelInstrument: Mov [DI+24h], SI ; SCOffset Mov AL, [DI+20h] Mov [SI+3Ah], AL ; HCN Mov [SI+38h], DI ; HCOffset Xor EAX, EAX Mov [SI+18h], EAX ; Reset vibrato info. Mov Byte Ptr [SI+0Bh], AL ; Reset loop dirn Call InitPlayInstrument Mov AL, [ES:BX+18h] Mov [SI+24h], AL Pop CX Mov Word Ptr [SI+26h], 0400h ; FadeOut, VolEnv&Pos Mov AX, [DI+3] Cmp Byte Ptr [DI+0Fh], 101 JNE NoMIDINote Mov AL, [DI+0Eh] NoMIDINote: Mov [SI+32h], AX ; Nte&Ins Mov BL, [DI+0Fh] And BX, 0FFh JZ AllocateChannel21 Dec BX Call I_TagSample Mov [SI+36h], BL Add BX, BX Mov BX, [ES:64912+BX] Mov [SI+34h], BX ; Sample memory offset. Cmp DWord Ptr [ES:BX+30h], 0 JE AllocateChannelInstrument2 ; No sample! Mov AX, [ES:BX+11h] Test AH, 1 JZ AllocateChannelInstrument2 ; No sample! And AH, 2 Mov [SI+18h], AH Mul Byte Ptr [SI+24h] ShR AX, 6 Mov [SI+24h], AL ; SI = 0->128 ClC Ret AllocateChannelInstrument2: Mov Word Ptr [SI], 200h And CH, Not 4 StC Ret ;EndP AllocateChannel ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Seed1 DW 1234h Seed2 DW 5678h Proc Random Push BX Push CX Push DX Mov AX, Seed1 Mov BX, Seed2 Mov CX, BX Mov DX, BX Add AX, BX Rol AX, CL Xor AX, DX XChg CL, CH Add BX, CX Add DX, BX Add CX, AX Ror BX, 1 SBB AX, DX Mov Seed2, DX Mov Seed1, AX Pop DX Pop CX Pop BX Ret ;EndP Random ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc GetLoopInformation ; Destroys AX, BX, CX, DX Mov BX, [SI+34h] ; ES:BX points to sample header Mov AL, [ES:BX+12h] ; AL = sample flags Test AL, 30h ; Loop?? JZ GetLoopInformation4 Mov ECX, [ES:BX+34h] ; CX = loopbeg Mov EDX, [ES:BX+38h] ; DX = loopend Mov AH, AL Test AL, 20h ; SusLoop? JZ GetLoopInformation2 Test Byte Ptr [SI], 4 JNZ GetLoopInformation1 Mov ECX, [ES:BX+40h] Mov EDX, [ES:BX+44h] ShR AH, 1 Jmp GetLoopInformation2 GetLoopInformation1: Test AL, 10h JZ GetLoopInformation4 GetLoopInformation2: Test AH, 40h JNZ GetLoopInformation3 Mov AH, 8 Jmp GetLoopInformation5 GetLoopInformation3: Mov AH, 24 Jmp GetLoopInformation5 GetLoopInformation4: Xor ECX, ECX Mov EDX, [ES:BX+30h] Mov AH, 0 GetLoopInformation5: Cmp [SI+0Ah], AH JNE GetLoopInformation6 Cmp [SI+40h], ECX JNE GetLoopInformation6 Cmp [SI+44h], EDX JNE GetLoopInformation6 Ret GetLoopInformation6: Mov [SI+0Ah], AH Mov [SI+40h], ECX Mov [SI+44h], EDX Or Word Ptr [SI], 400h ; Loop changed. Ret ;EndP GetLoopInformation ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %include "it_m_eff.inc" ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc PitchSlideDown ; Expects SI to slave ; BX = slide value ;Assume DS:Music %IF USEFPUCODE Neg BX ;EndP PitchSlideDown ; EndP for PitchSlideDown %ELSE Test Byte Ptr [ES:2Ch], 8 JNZ PitchSlideDownLinear ; Go on to amiga slide down. ;EndP PitchSlideDown ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc PitchSlideDownAmiga Or Byte Ptr [SI], 32 ; recalculate pitch! Mov EAX, [SI+10h] MovZX EBX, BX Mul EBX ; EDX:EAX = cmd*InitialFreq Xor CX, CX ; CX = counter. Add EAX, 1712*8363 AdC EDX, 0 JZ PitchSlideDownAmiga1 PitchSlideDownAmiga2: ShR EDX, 1 RCR EAX, 1 Inc CX Test EDX, EDX JNZ PitchSlideDownAmiga2 PitchSlideDownAmiga1: Mov EBX, EAX ; EBX = 1712*8363+Cmd*InitialFreq Mov EAX, 8363*1712 Mul DWord Ptr [SI+10h] JCXZ PitchSlideDownAmiga4 PitchSlideDownAmiga5: ShR EDX, 1 RCR EAX, 1 Loop PitchSlideDownAmiga5 PitchSlideDownAmiga4: Cmp EBX, EDX JBE PitchSlideDownAmiga3 Div EBX Mov [SI+10h], EAX PitchSlideDownAmiga3: Ret ;EndP PitchSlideDownAmiga ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc PitchSlideDownLinear ; Given BX = slide down value = 0->1024 Or Byte Ptr [SI], 32 ; recalculate pitch! Push DI Mov DI, Offset LinearSlideDownTable Cmp BX, 0Fh JA PitchSlideDownLinear1 Mov DI, Offset FineLinearSlideDownTable Add BX, BX Jmp PitchSlideDownLinear2 PitchSlideDownLinear1: ShR BX, 1 And BX, Not 1 PitchSlideDownLinear2: MovZX EAX, Word Ptr [DI+BX] Mul DWord Ptr [SI+10h] SHRD EAX, EDX, 16 Mov [SI+10h], EAX Pop DI Ret ;EndP PitchSlideDownLinear ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %ENDIF ; USEFPUCODE Proc PitchSlideUp ; Expects SI to slave ; BX = slide value Test Byte Ptr [ES:2Ch], 8 JZ PitchSlideUpAmiga ; Go on to linear slide ;EndP PitchSlideUp ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc PitchSlideUpLinear %IF USEFPUCODE Mov [CS:SlideValue], BX FILD Word Ptr [CS:SlideValue] FMul [CS:Const1_On_768] ; Have SlideValue/768.0 FLd ST FRndInt FSub ST(1), ST FXCh F2XM1 FLd1 FAdd FScale FIMul DWord Ptr [SI+10h] FIStP DWord Ptr [SI+10h] FStP ST PitchSlideUpFPUFreqCheck: Or Byte Ptr [SI], 32 ; recalculate pitch! Cmp DWord Ptr [SI+10h], 07FFFFFFFh JAE PitchSlideUpLinear1 Ret PitchSlideUpLinear1: ; Turn off channel Or Word Ptr [SI], 200h And Byte Ptr [DI], Not 4 %ELSE Or Byte Ptr [SI], 32 ; recalculate pitch! Push DI Cmp BX, 0Fh Mov DI, Offset LinearSlideUpTable JA PitchSlideUpLinear3 Mov DI, Offset FineLinearSlideUpTable ShL BX, 2 Jmp PitchSlideUpLinear2 PitchSlideUpLinear3: And BX, Not 3 PitchSlideUpLinear2: Mov EAX, [SI+10h] Mul DWord Ptr [DI+BX] SHRD EAX, EDX, 16 Test EDX, 0FFFF0000h JNZ PitchSlideUpLinear1 Mov [SI+10h], EAX Pop DI Ret PitchSlideUpLinear1: ; Turn off channel Pop DI Or Word Ptr [SI], 200h And Byte Ptr [DI], Not 4 ; And Byte Ptr [SI], Not 1 ; Or Byte Ptr [SI+1], 2 ; Cut! ; And Byte Ptr [DI], Not 4 %ENDIF Ret ;EndP PitchSlideUpLinear ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc PitchSlideUpAmiga %IF USEFPUCODE Mov [CS:SlideValue], BX FILD Word Ptr [CS:SlideValue] FILD DWord Ptr [SI+10h] ; InitFreq, Cmd FMul ST(1), ST ; InitFreq, Cmd.InitFreq FLd [CS:Const_14317456] ; 1712*8363, InitFreq, Cmd.InitFreq FSubR ST(2), ST ; 1712*8363, InitFreq, 1712*8363-Cmd.InitFreq FMul ; 1712*8363*InitFreq, 1712*8363-Cmd.InitFreq FDivRP ST(1), ST ; FinalFreq FIStP DWord Ptr [SI+10h] Jmp PitchSlideUpFPUFreqCheck %ELSE Or Byte Ptr [SI], 32 ; recalculate pitch! Mov EAX, [SI+10h] MovZX EBX, BX Mul EBX ; EDX:EAX = InitialFreq*Cmd Test EDX, EDX JNZ PitchSlideUpAmiga1 Mov ECX, 1712*8363 Mov EDX, ECX Sub ECX, EAX ; ECX = 1712*8363-Cmd*InitialFreq JBE PitchSlideUpAmiga1 Mov EAX, [SI+10h] Mul EDX Cmp ECX, EDX JBE PitchSlideUpAmiga1 Div ECX Mov [SI+10h], EAX Ret PitchSlideUpAmiga1: ; Turn off channel Or Word Ptr [SI], 200h And Byte Ptr [DI], Not 4 ; And Byte Ptr [SI], Not 1 ; Or Byte Ptr [SI+1], 2 ; Cut! ; And Byte Ptr [DI], Not 4 Ret %ENDIF ;EndP PitchSlideUpAmiga ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetWaveForm Far Test Byte Ptr CS:DriverFlags, 4 JZ Music_GetWaveForm1 Call [CS:DriverGetWaveform] DB 85h Music_GetWaveForm1: StC Ret ;EndP Music_GetWaveForm ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_Poll Far Mov AX, CS:PlayMode Mov BX, CS:CurrentPattern Jmp [DriverPoll] ;EndP Music_Poll ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_InitTempo Far PushA Call Music_GetTempo Call [DriverSetTempo] PopA Ret ;EndP Music_InitTempo ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc GetChannels ; Returns min of NumChannels & DriverMaxChannels ; Also uses default channels if num channels ; = 0ffffh Push DS Push CS Pop DS ;Assume DS:Music Mov AX, CmdLineNumChannels Cmp AX, 0FFFFh JNE GetChannels2 Mov AX, DefaultChannels GetChannels2: Cmp AX, DriverMaxChannels JBE GetChannels1 Mov AX, DriverMaxChannels GetChannels1: Cmp AX, MAXSLAVECHANNELS JB GetChannels3 ; MC4 Mov AX, MAXSLAVECHANNELS GetChannels3: ; MC4 Mov NumChannels, AX Pop DS Ret ;EndP GetChannels ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ReinitSoundCard Far Call GetChannels Call [DriverReinitSound] Jmp Music_SoundCardLoadAllSamples ;EndP Music_ReinitSoundCard ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_UnInitSoundCard Far Jmp [DriverUninitSound] ;EndP Music_UnInitSoundCard ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_InitMusic Far PushAD Push DS Push ES Xor AX, AX Mov DS, AX Mov AX, CS ShL EAX, 16 Mov AX, Offset Music_UpdateSampleLocation %IF ENABLEINT3 %ELSE Mov [DS:0Ch], EAX %ENDIF Trace " - Initialising SoundDriver Tables" Call Music_ClearDriverTables Call D_GotoStartingDirectory Push CS Pop DS ;Assume DS:Music Trace " - Loading MIDI configuration" ; Open MIDI Config file. Mov AX, 3D00h Mov DX, Offset MIDIConfigFileName Int 21h JC Music_InitMusic1 Mov BX, AX Mov DS, MIDIDataArea Xor DX, DX Mov AH, 3Fh Mov CX, (128+16+9)*32 Int 21h Mov AH, 3Eh ; Close Int 21h Music_InitMusic1: Trace " - Initialising playback tables" Call Music_Stop Pop ES Pop DS PopAD ;Assume DS:Nothing Ret ;EndP Music_InitMusic ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ReleasePattern Far ; AX = pattern number Push AX Push DS Push SI Push ES LEA SI, [63912+EAX*4] Push SI Mov DS, CS:SongDataArea LodsW Cmp AL, 1 JB Music_ReleasePattern1 JA Music_ReleasePattern2 LodsW Mov ES, AX Mov AH, 49h Int 21h Jmp Music_ReleasePattern1 Music_ReleasePattern2: Cmp AL, 3 JB Music_ReleasePattern3 JA Music_ReleasePattern1 LodsW Dec AX Call E_ReleaseBlockEMS Jmp Music_ReleasePattern1 Music_ReleasePattern3: LodsW Call E_ReleaseEMS Music_ReleasePattern1: Pop SI Mov DWord Ptr [SI], 0 Pop ES Pop SI Pop DS Pop AX Ret ;EndP Music_ReleasePattern ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetPattern Far ; AX = pattern number ; Returns DS:SI points to pattern data. Push AX ; ShL AX, 2 ; Mov SI, 63912 ; Add SI, AX LEA SI, [63912+EAX*4] Mov DS, CS:SongDataArea LodsW Cmp AL, 1 JE Music_GetPattern1 JA Music_GetPattern2 Push CS Pop DS Mov SI, Offset EmptyPattern Pop AX Ret Music_GetPattern1: LodsW Mov DS, AX Xor SI, SI Pop AX Ret Music_GetPattern2: Cmp AL, 3 JB Music_GetPattern3 LodsW Call E_MapAlignedBlockEMS Pop AX Ret Music_GetPattern3: Push CX Push DX MovZX CX, AH Mov DX, [SI] Call E_MapEMSMemory Call E_GetEMSPageFrame Mov DS, AX Xor SI, SI Pop DX Pop CX Pop AX Ret ;EndP Music_GetPattern ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetPatternLocation Far ; AX = pattern number ; Returns AX = handle ; EBX = page/offset or ; seg/offset ; CX = length Call Music_GetPattern ; Returns DS:SI Mov CX, [SI] Add CX, 8 ; CX = size of data including header Proc Music_GetPatternLocationNoCount Far LEA SI, [63912+EAX*4] Mov DS, CS:SongDataArea LodsW Cmp AL, 1 JE Music_GetPatternLocation1 JA Music_GetPatternLocation2 Mov BX, CS Xor AX, AX ShL EBX, 16 Xor DX, DX Mov BX, Offset EmptyPattern Ret Music_GetPatternLocation1: LodsW Mov BX, AX ShL EBX, 16 Xor AX, AX Xor DX, DX Ret Music_GetPatternLocation2: Cmp AL, 3 JB Music_GetPatternLocation3 LodsW ; AX = "Segment" into EMS block ; Want page = (AX >> 10) ; offset = (AX << 4) & 0xFFFF Mov BX, AX ShL AX, 4 ShL EBX, 6 Mov BX, AX And EBX, 03F3FFFh Call E_GetInternalEMSHandle Mov DL, 1 Ret Music_GetPatternLocation3: LodsW Xor EBX, EBX Mov DL, 1 Ret ;EndP Music_GetPatternLocationNoCount ;EndP Music_GetPatternLocation ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_AllocatePattern Far ; DX = length. ; SI = Pattern ; ES:DI points to pattern area Cmp CS:PatternStorage, 1 JB Music_AllocatePatternConventionalOnly JA Music_AllocatePatternEMS2 Music_AllocatePatternEMS: ; Try allocating EMS Xor EAX, EAX Mov AX, DX Call E_AllocateBlockEMS JC Music_AllocatePatternEMS2 Mov ES, CS:SongDataArea LEA DI, [ESI*4+63914] Inc AX StosW Mov Word Ptr [ES:DI-4], 3 Push DS Push SI Call E_MapAlignedBlockEMS Push DS Pop ES Mov DI, SI Pop SI Pop DS Ret Music_AllocatePatternEMS2: MovZX EAX, DX ClC Call E_AllocateEMS Test AX, AX JZ Music_AllocatePatternConventional Push CX Push DX Mov ES, CS:SongDataArea LEA DI, [ESI*4+63914] ; Mov DI, SI ; ShL DI, 2 ; Add DI, 63914 StosW Add DX, 16383 RCR DX, 1 ShR DX, 13 Mov CX, DX Mov DX, AX Call E_MapEMSMemory Mov CH, CL Mov CL, 2 Mov [ES:DI-4], CX Call E_GetEMSPageFrame Mov ES, AX Xor DI, DI Pop DX Pop CX Ret Music_AllocatePatternConventionalOnly: Mov AH, 48h ; How much free? Mov BX, 0FFFFh Int 21h Cmp BX, -1 JE Music_AllocatePatternEMS Cmp BX, 4096 JAE Music_AllocatePatternConventional ShL BX, 4 ; BX = size in bytes of ; conv remaining Cmp DX, BX JA Music_AllocatePatternEMS Music_AllocatePatternConventional: Mov AH, 48h Mov BX, DX Add BX, 15 RCR BX, 1 ShR BX, 3 Int 21h JC Music_AllocatePattern2 Push DS Mov DS, CS:SongDataArea LEA SI, [ESI*4+63912] ; ShL SI, 2 ; Add SI, 63912 Mov Word Ptr [SI], 1 Mov [SI+2], AX Pop DS Mov ES, AX Xor DI, DI Ret Music_AllocatePattern2: Xor AX, AX Mov ES, AX Ret ;EndP Music_AllocatePattern ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_AllocateSample Far ; AX = Sample number, 0 based ; EDX = length ; Returns ES:DI, ES = 0 if not. Push EAX Push BX Push CX Push EDX Push DS Push SI Mov AH, 2 Call Music_ReleaseSample And AX, 0FFh Add EDX, 8 ; Extra 8 bytes allocated.. Mov BX, AX Add BX, BX Mov DS, CS:SongDataArea Mov SI, [64912+BX] Cmp EDX, 1024 JA Music_AllocateSample5 Mov EBX, EDX Add EBX, 15 RCR EBX, 1 SHR EBX, 3 Mov AH, 48h Int 21h JNC Music_AllocateSample4 Music_AllocateSample5: Mov EAX, EDX StC Call E_AllocateEMS Test AX, AX ; AX = handle JZ Music_AllocateSample1 Mov Byte Ptr [DS:SI+48h], 2 Mov [DS:SI+4Ah], AX Add EDX, 16383 RCR EDX, 1 ShR EDX, 13 Mov [DS:SI+49h], DL Xor CH, CH Mov CL, DL Mov DX, AX Call E_MapEMSMemory Call E_GetEMSPageFrame Mov ES, AX Xor DI, DI Or Byte Ptr [SI+12h], 1 Jmp Music_AllocateSample3 Music_AllocateSample1: Cmp EDX, 1048576 JAE Music_AllocateSample2 Mov EBX, EDX Add EBX, 15 RCR EBX, 1 SHR EBX, 3 Mov AH, 48h Int 21h JC Music_AllocateSample2 Music_AllocateSample4: Mov Byte Ptr [SI+48h], 1 Mov [SI+4Ah], AX Or Byte Ptr [SI+12h], 1 Mov ES, AX Xor DI, DI Jmp Music_AllocateSample3 Music_AllocateSample2: And Byte Ptr [SI+12h], 0F0h Xor AX, AX Mov ES, AX Music_AllocateSample3: Pop SI Pop DS Pop EDX Pop CX Pop BX Pop EAX Ret ;EndP Music_AllocateSample ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ReleaseSample Far ; AX = sample number, 0 based ; AH = 1 = called from network ; = 2 = called from allocate PushAD Push DS Push ES Mov DX, AX And AX, 0FFh Mov BX, AX Add BX, BX Mov DS, CS:SongDataArea Mov BX, [BX+64912] ; DS:BX points to sample PushAD Mov SI, BX Call [DriverReleaseSample] PopAD Mov DI, BX Test Byte Ptr [BX+12h], 1 JZ Music_ReleaseSample1 ; Used to be ReleaseSample5. ; Changed for network code Mov AL, [BX+48h] Cmp AL, 1 JB Music_ReleaseSample5 JE Music_ReleaseSample2 Cmp AL, 2 JA Music_ReleaseSample1 Mov AX, [BX+4Ah] Call E_ReleaseEMS Jmp Music_ReleaseSample1 Music_ReleaseSample2: Mov ES, [BX+4Ah] Mov AH, 49h Int 21h Music_ReleaseSample1: Mov DWord Ptr [DI+30h], 0 Mov DWord Ptr [DI+48h], 0 Cmp DH, 1 JA Music_ReleaseSample5 JE Music_ReleaseSample6 %IF NETWORKENABLED Mov AH, DL Mov AL, NETWORK_DELETESAMPLEOBJECT Call Network_AddWordToQueue %ENDIF Music_ReleaseSample6: Push DS Pop ES Xor AX, AX And Byte Ptr [DI+12h], 0FEh Add DI, 14h Mov CX, 3Ch/2 Rep StosW Music_ReleaseSample5: Pop ES Pop DS PopAD Ret ;EndP Music_ReleaseSample ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ClearSampleName Far ; AX = Sample number (0 based) Push CX Push DS Push SI Push ES Push DI Push CS Pop DS Mov SI, Offset SampleHeader Mov ES, CS:SongDataArea Mov DI, AX Add DI, DI Mov DI, [ES:64912+DI] Mov CX, 80 Rep MovsB Pop DI Pop ES Pop SI Pop DS Pop CX Ret ;EndP Music_ClearSampleName ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ClearAllSampleNames Far Push AX Push CX Mov CX, 100 Music_ClearAllSampleNames1: Mov AX, CX Dec AX Call Music_ClearSampleName Loop Music_ClearAllSampleNames1 Pop CX Pop AX Ret ;EndP Music_ClearAllSampleNames ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ReleaseAllSamples Far Push AX Push CX Mov CX, 100 Music_ReleaseAllSamples1: Mov AX, CX Dec AX Call Music_ReleaseSample Loop Music_ReleaseAllSamples1 Pop CX Pop AX Ret ;EndP Music_ReleaseAllSamples ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ReleaseAllPatterns Far Push AX Push CX Mov CX, 200 Music_ReleaseAllPatterns1: Mov AX, CX Dec AX Call Music_ReleasePattern Loop Music_ReleaseAllPatterns1 Pop CX Pop AX Ret ;EndP Music_ReleaseAllPatterns ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ClearInstrument Far ; AX = Instrument number ; (0 based) Push CX Push DS Push SI Push ES Push DI Push CS Pop DS ;Assume DS:Music Mov DI, AX Add DI, DI Mov ES, SongDataArea Mov DI, [ES:DI+64712] ; ES:DI points to inst. Mov SI, Offset InstrumentHeader Mov CX, 554 Rep MovsB Pop DI Pop ES Pop SI Pop DS Pop CX Ret ;EndP Music_ClearInstrument ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ClearAllInstruments Far Mov AX, 99 Music_ClearAllInstruments1: Call Music_ClearInstrument Dec AX JNS Music_ClearAllInstruments1 Ret ;EndP Music_ClearAllInstruments ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_UnInitMusic Far Call Music_UnInitSoundCard Call Music_UnloadDriver Cmp CS:SongDataArea, 0 JE Music_UnInitMusic1 Call Music_ReleaseAllPatterns Call Music_ReleaseAllSamples Music_UnInitMusic1: Mov ES, CS:SongDataArea Mov AH, 49h Int 21h Ret ;EndP Music_UnInitMusic ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetSongSegment Far Mov AX, CS:SongDataArea Ret ;EndP Music_GetSongSegment ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_UnloadDriver Xor AX, AX XChg AX, CS:SoundDriverSegment Test AX, AX JZ Music_UnloadDriver1 Mov ES, AX Mov AH, 49h Int 21h Music_UnloadDriver1: Ret ;EndP Music_UnloadDriver ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc NoFunction2 Push CS Pop DS Mov SI, Offset NoSoundCardMsg Proc NoFunction Far Xor AX, AX StC Ret ;EndP NoFunction ;EndP NoFunction2 ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ClearDriverTables ; Makes all of them point to ; Xor AX, AX, StC, RetF Mov AX, CS Mov ES, AX ShL EAX, 16 Mov AX, Offset NoFunction2 Mov DI, Offset StartDriverFunctions StosD StosD Mov AX, Offset NoFunction %IF OLDDRIVER Mov CX, 61 %ELSE Mov CX, 29 %ENDIF Rep StosD Xor EAX, EAX StosD Mov DriverMaxChannels, 32 Ret ;EndP Music_ClearDriverTables ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_LoadDriver ; Given DS:DX = filename ;Assume DS:Nothing %IF DEF DEBUG PushA Push ES Push DS Mov DI, 0B800h Mov ES, DI Push CS Pop DS ;Assume DS:Music Mov DI, [ScreenOffset] Mov SI, Offset LoadDriverMessage Mov AH, 2 LoadDriverMessage1: LodsB StosW Test AL, AL JNZ LoadDriverMessage1 Pop DS ;Assume DS:Nothing Mov SI, DX LoadDriverMessage2: LodsB StosW Test AL, AL JNZ LoadDriverMessage2 Add [CS:ScreenOffset], 160 Pop ES PopA %ENDIF Mov AX, 3D00h Int 21h ClD JNC Music_LoadDriver2 %IF DEF DEBUG PushA Push DS Push ES Push CS Pop DS ;Assume DS:Music Mov DI, 0B800h Mov ES, DI Mov SI, Offset UnableToReadFileMessage Mov DI, [ScreenOffset] Mov AH, 2 UnableToReadFileLoop: LodsB StosW Test AL, AL JNZ UnableToReadFileLoop Add [ScreenOffset], 160 Pop ES Pop DS PopA ;Assume DS:Nothing %ENDIF Jmp Music_LoadDriverNoClose Music_LoadDriverError: Mov AH, 3Eh Int 21h Music_LoadDriverNoClose: ClD Call Music_ClearDriverTables Push CS Pop DS StC Ret Music_LoadDriver2: Mov BX, AX ; BX = file handle Mov AH, 3Fh ; Read file %IF OLDDRIVER Mov CX, 256 %ELSE Mov CX, 128 %ENDIF Push CS Push CS Pop DS Pop ES ;Assume DS:Music Mov DX, Offset StartDriverFunctions Mov SI, DX Int 21h JC Music_LoadDriverError Cmp AX, CX JNE Music_LoadDriverError %IF OLDDRIVER Mov CX, 28 %ELSE Mov CX, 37 ; Length of ID %ENDIF Mov DI, Offset DriverID RepE CmpsB JNE Music_LoadDriverError ; OK.. ID OK. Now get length, allocate memory ; load driver, and fill in headers. Push BX Mov BX, DriverLength Add BX, 15 Mov AH, 48h ShR BX, 4 Int 21h Pop BX JC Music_LoadDriverError ; Insufficient memory Mov CX, DriverLength Mov SoundDriverSegment, AX Mov DS, AX ;Assume DS:Nothing Mov DI, AX ; DI = segment of driver... Mov AH, 3Fh ; Load driver into memory! Xor DX, DX Int 21h Push CS Pop DS ;Assume DS:Music Mov AH, 3Fh Mov DX, Offset DriverVariableTable %IF OLDDRIVER Mov CX, 64 %ELSE Mov CX, 16 %ENDIF Int 21h Mov AH, 3Fh %IF OLDDRIVER Mov CX, 128 Mov DX, Offset StartDriverFunctions+128 %ELSE Mov CX, 64 Mov DX, Offset StartDriverFunctions+64 %ENDIF Mov SI, DX Int 21h JC Music_LoadDriverError Cmp AX, CX JNE Music_LoadDriverError Mov AH, 3Eh Int 21h ; Setup reqd function table SHRD EAX, EDI, 16 ; High word of EAX contains ; segment... Mov DI, Offset StartDriverFunctions %IF OLDDRIVER Mov CX, 64 %ELSE Mov CX, 32 %ENDIF DriverFunctionLoop1: LodsW StosD Loop DriverFunctionLoop1 ; Setup variable table Mov ES, SoundDriverSegment Xor DI, DI %IF OLDDRIVER Mov CX, 256 %ELSE Mov CX, 16 %ENDIF Mov SI, Offset DriverRequiredVariables Rep MovsB Mov SI, Offset DriverRequiredFunctions %IF OLDDRIVER Mov CX, 128 %ELSE Mov CX, 32 %ENDIF Rep MovsD %IF DEF DEBUG PushA Push DS Push ES Push CS Pop DS ;Assume DS:Music Mov DI, 0B800h Mov ES, DI Mov SI, Offset DetectingMessage Mov DI, [ScreenOffset] Mov AH, 2 DetectingMessageLoop: LodsB StosW Test AL, AL JNZ DetectingMessageLoop Add [ScreenOffset], 160 Pop ES Pop DS PopA ;Assume DS:Nothing %ENDIF ClC Ret ;EndP Music_LoadDriver ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ADSCParams DW 7 Dup (0) ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_AutoDetectSoundCard Far ; Returns DS:SI = string ; AX, BX, CX, DX, DI = parameters Call D_GotoStartingDirectory Xor SI, SI Mov DX, Word Ptr [CS:DriverName] And DX, DX JZ Music_AutoDetectSoundCard1 Trace " - Loading specific soundcard driver" Cmp DX, 0FFFFh JE Music_AutoDetectSoundCard4 Mov DS, Word Ptr [CS:DriverName+2] Call Music_LoadDriver JC Music_AutoDetectSoundCard4 Mov AL, 1 ; Forced Mov BX, TRACKERVERSION Mov ECX, [CS:DriverName] Call [DriverDetectCard] JC Music_AutodetectSoundCard5 Cmp EAX, 'Jeff' JE Music_AutoDetectSoundCard4 Music_AutodetectSoundCard5: Call Music_UnloadDriver Call Music_ClearDriverTables Jmp Music_AutoDetectSoundCard4 Music_AutoDetectSoundCard1: Trace " - Testing soundcard driver" Push SI Push CS Pop DS ;Assume DS:Music Mov Word Ptr [DriverName+2], DS Mov BX, [SI+DriverDetectionOrder] Cmp BX, 0FFFFh JE Music_AutoDetectSoundCard2 Add BX, BX Mov DX, [DriverNameTable+BX] Mov Word Ptr [DriverName], DX Call Music_LoadDriver JC Music_AutoDetectSoundCard3 Xor AX, AX ; Not forced Mov BX, TRACKERVERSION Mov ECX, [CS:DriverName] Call [DriverDetectCard] JC Music_AutoDetectSoundCard6 Cmp EAX, 'Jeff' JE Music_AutoDetectSoundCard2 Music_AutoDetectSoundCard6: Call Music_UnloadDriver Call Music_ClearDriverTables Music_AutoDetectSoundCard3: Pop SI Add SI, 2 Jmp Music_AutoDetectSoundCard1 Music_AutoDetectSoundCard2: Pop AX Music_AutoDetectSoundCard4: Call GetChannels Call [CS:DriverInitSound] Mov [CS:ADSCParams+2], DS Push CS Pop DS ;Assume DS:Music Mov [ADSCParams], SI Mov [ADSCParams+12], DI Mov [ADSCParams+10], DX Mov [ADSCParams+8], CX Mov [ADSCParams+6], BX Mov [ADSCParams+4], AX Call Music_InitStereo Call Music_InitMixTable Ret ;EndP Music_AutoDetectSoundCard ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ShowAutoDetectSoundCard Far Push CS Pop DS ;Assume DS:Music Push DWord Ptr [ADSCParams+10] Push DWord Ptr [ADSCParams+6] Push [ADSCParams+4] LDS SI, DWord Ptr [ADSCParams] Mov AH, 20h Mov DI, (26+28*80)*2 Call S_DrawString Add SP, 10 Ret ;EndP Music_ShowAutoDetectSoundCard ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetInstrumentMode Far Push DS Mov DS, CS:SongDataArea Mov AH, [DS:2Ch] And AH, 4 Pop DS Ret ;EndP Music_GetInstrumentMode ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc UpdateGOTONote ; Get offset & arrayed flag. Push DS ;Assume DS:Nothing Call PE_GetCurrentPattern ; AX = Pattern number ; BX = MaxRow ; DS = PatternDataSegment Cmp AX, CS:CurrentPattern JNE UpdateGOTONote1 Mov DecodeExpectedPattern, AX Mov CS:PatternSegment, DS Pop DS ;Assume DS:Music Mov NumberOfRows, BX Mov AX, ProcessRow Cmp AX, BX JB UpdateGOTONote2 Xor AX, AX Mov ProcessRow, AX Mov CurrentRow, AX UpdateGOTONote2: Mov DecodeExpectedRow, AX LEA AX, [EAX*4+EAX] ; PatternRowSize = *320 ShL AX, 6 ; Mov BX, 320 ; Mul BX Mov PatternOffset, AX Mov PatternArray, 1 Ret UpdateGOTONote1: Pop DS ;Assume DS:Music Mov AX, CurrentPattern Mov DecodeExpectedPattern, AX %IF NETWORKENABLED Call Network_UpdatePatternIfIdle %ENDIF Call Music_GetPattern ;Assume DS:Nothing ; DS:SI points to pattern. LodsW LodsW ; AX = number of rows Mov CX, ProcessRow Cmp AX, CX JA UpdateGotoNote3 Xor CX, CX UpdateGOTONote3: Mov CurrentRow, CX Mov ProcessRow, CX Mov DecodeExpectedRow, CX Mov NumberOfRows, AX Add SI, 4 Inc CX UpdateGOTONote10: Dec CX JZ UpdateGOTONote5 UpdateGOTONote4: ; OK.. now to find the right ; offset & update tables. LodsB Test AL, AL JZ UpdateGOTONote10 Mov DL, AL And AX, 7Fh Dec AX LEA BX, [EAX*4+EAX] ; BX = AX*5 ShL BX, 4 ; BX = AX*80 LEA DI, [HostChannelInformationTable+BX] ; And AL, 7Fh ; Dec AL ; Mov AH, HOSTCHANNELSIZE ; Mul AH ; Mov DI, AX ; Add DI, Offset HostChannelInformationTable ; CS:DI points. Mov DH, [CS:DI+2] Test DL, 80h JZ UpdateGOTONote6 Mov DH, [SI] Inc SI Mov [CS:DI+2], DH UpdateGOTONote6: Test DH, 1 JZ UpdateGOTONote7 LodsB Mov [CS:DI+3], AL UpdateGOTONote7: Test DH, 2 JZ UpdateGOTONote8 LodsB Mov [CS:DI+4], AL UpdateGOTONote8: Test DH, 4 JZ UpdateGOTONote9 LodsB Mov [CS:DI+5], AL UpdateGOTONote9: Test DH, 8 JZ UpdateGOTONote4 LodsW Mov [CS:DI+8], AX Jmp UpdateGOTONote4 UpdateGOTONote5: Push CS Pop DS ;Assume DS:Music Mov PatternOffset, SI Mov PatternArray, 0 Ret ;EndP UpdateGOTONote ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc PreInitCommand Push DS Push SI Push CS Pop DS ;Assume DS:Music Test Byte Ptr [DI+2], 33h JZ PreInitCommandEnd Test Byte Ptr [ES:2Ch], 4 JNZ PreInitCommand1 PreInitCommand2: Mov AX, [DS:DI+3] Mov [DS:DI+0Eh], AX ; Sample/note Jmp PreInitCommandEnd PreInitCommand1: ; Have to xlat. Mov SI, [DS:DI+3] ; Not a note? And SI, 0FFh Cmp SI, 120 JAE PreInitCommand2 Mov BL, [DS:DI+4] And EBX, 0FFh JZ PreInitCommand2 Add SI, SI Mov BX, [ES:64710+EBX+EBX] Mov AX, [ES:BX+3Ch] Cmp AL, 0 JE PreInitCommandNoMIDI Cmp AL, 17 JNE PreInitCommandMIDI1 Mov AL, [DS:DI+20h] And AL, 0Fh Inc AL ; AL = HCN PreInitCommandMIDI1: Mov [DS:DI+0Ch], AX Mov AH, 101 Mov AL, [ES:BX+SI+40h] ; Mov AL, [DS:DI+3] Jmp PreInitCommandMIDIEnd PreInitCommandNoMIDI: Mov AX, [ES:BX+SI+40h] PreInitCommandMIDIEnd: Mov [DS:DI+0Eh], AX Test AH, AH ; No sample? JZ PreInitCommand4 PreInitCommandEnd: Mov BL, [DS:DI+6] And EBX, 31 Call Word Ptr [InitCommandTable+EBX+EBX] ; Init note Or Byte Ptr [DI], 64 MovZX BX, Byte Ptr [DI+20h] ; Check whether chn ; is on Test Byte Ptr [ES:BX+40h], 80h JZ PreInitCommand4 Test Byte Ptr [DI], 32 JNZ PreInitCommand4 Test Byte Ptr [DI], 4 JZ PreInitCommand4 ; Channel was off. Mov SI, [DI+24h] Or Byte Ptr [SI+1], 8 PreInitCommand4: Pop SI Pop DS Ret ;EndP PreInitCommand ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc UpdateNoteData ;Assume DS:Music Mov PatternLooping, 0 Mov AX, CurrentPattern Cmp AX, DecodeExpectedPattern JNE UpdateNoteData1 Mov AX, CurrentRow Inc DecodeExpectedRow Cmp AX, DecodeExpectedRow JE UpdateNoteData2 UpdateNoteData1: Call UpdateGOTONote UpdateNoteData2: Mov CX, 64 ; 64 channels ; Xor AX, AX ; Just to get rid of "jumps" Mov DI, Offset HostChannelInformationTable Cmp PatternArray, 1 JE UpdateNoteArrayed UpdateNoteCompressed: ; First clear all old command&value. ; Mov CX, 64 ; Done above UpdateNoteCompressed1: And Word Ptr [DI], Not (3+32+64+256) Add DI, HOSTCHANNELSIZE Dec CX JNZ UpdateNoteCompressed1 Push DS Mov AX, CurrentPattern %IF NETWORKENABLED ; Call Network_UpdatePatternIfIdle %ENDIF Call Music_GetPattern ; Gets DS Mov SI, CS:PatternOffset ; Mov DS, PatternSegment ;Assume DS:Nothing UpdateNoteCompressed2: LodsB Test AL, AL JZ UpdateNoteCompressed3 ; No more! ; else... go through decoding. Mov DL, AL And AX, 7Fh Dec AX LEA DI, [EAX*4+EAX] ShL DI, 4 ; HOSTCHANNELSIZE Add DI, Offset HostChannelInformationTable Mov DH, [CS:DI+2] ; mask. Test DL, 80h JZ UpdateNoteCompressed4 Mov DH, [SI] Inc SI Mov [CS:DI+2], DH UpdateNoteCompressed4: ; DH = mask Test DH, 1 JZ UpdateNoteCompressed6 LodsB Mov [CS:DI+3], AL UpdateNoteCompressed6: Test DH, 2 JZ UpdateNoteCompressed8 LodsB Mov [CS:DI+4], AL UpdateNoteCompressed8: Test DH, 4 JZ UpdateNoteCompressed10 LodsB Mov [CS:DI+5], AL UpdateNoteCompressed10: Test DH, 8 JZ UpdateNoteCompressed11 LodsW Mov [CS:DI+8], AX Jmp UpdateNoteCompressed13 UpdateNoteCompressed11: Test DH, 80h JZ UpdateNoteCompressed12 Mov AX, [CS:DI+8] Jmp UpdateNoteCompressed13 UpdateNoteCompressed12: Xor AX, AX UpdateNoteCompressed13: Mov [CS:DI+6], AX Call PreInitCommand Jmp UpdateNoteCompressed2 UpdateNoteCompressed3: Pop DS ;Assume DS:Music Mov PatternOffset, SI Ret UpdateNoteArrayed: ;Assume DS:Music Push DS Mov SI, PatternOffset Mov DS, PatternSegment ;Assume DS:Nothing ; Mov CX, 64 ; 64 channels ; Mov DI, Offset HostChannelInformationTable UpdateNoteArrayed1: Xor DL, DL ; DL = mask. And Word Ptr [CS:DI], Not (3+32+64+256) ; Turn off all calling... LodsB ; AL = note data. Cmp AL, NONOTE JE UpdateNoteArrayed2 Mov [CS:DI+3], AL Or DL, 1 UpdateNoteArrayed2: LodsB Test AL, AL JZ UpdateNoteArrayed3 Mov [CS:DI+4], AL Or DL, 2 UpdateNoteArrayed3: LodsB Cmp AL, 0FFh JE UpdateNoteArrayed4 Mov [CS:DI+5], AL Or DL, 4 UpdateNoteArrayed4: LodsW Mov [CS:DI+6], AX Mov [CS:DI+8], AX Test AX, AX JZ UpdateNoteArrayed5 Or DL, 8 UpdateNoteArrayed5: Test DL, DL JZ UpdateNoteArrayed6 Mov [CS:DI+2], DL Push CX Call PreInitCommand Pop CX ;Assume DS:Nothing UpdateNoteArrayed6: Add DI, HOSTCHANNELSIZE Dec CX JNZ UpdateNoteArrayed1 Pop DS ;Assume DS:Music Mov PatternOffset, SI Ret ;EndP UpdateNoteData ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc UpdateVibrato ; DS:SI points to slavechannelstruct. Mov BX, [SI+34h] ; ES:BX points to sample Mov DL, [ES:BX+4Dh] ; Vibrato depth Test DL, DL JZ UpdateVibrato1 Mov CX, [SI+1Ah] Add CL, [ES:BX+4Eh] ; Vibrato rate AdC CH, 0 Cmp CH, DL JBE UpdateVibrato5 Mov CH, DL UpdateVibrato5: Mov [SI+1Ah], CX Mov AH, [ES:BX+4Ch] ; AH = speed Mov BH, [ES:BX+4Fh] ; BH = waveform Test AH, AH JZ UpdateVibrato1 Cmp BH, 3 JE UpdateVibrato2 Mov BL, [SI+19h] Add BL, AH Mov [SI+19h], BL ; Update pointer. Mov AL, [FineSineData+BX] Jmp UpdateVibrato3 UpdateVibrato2: Call Random And AL, 127 Sub AL, 64 UpdateVibrato3: IMul CH SAL AX, 2 MovSX BX, AH %IF E USEFPUCODE JS UpdateVibrato4 %ENDIF JZ UpdateVibrato1 Push DI Mov DI, [SI+38h] Call PitchSlideUpLinear Pop DI %IF E USEFPUCODE Jmp UpdateVibrato1 UpdateVibrato4: Neg BX Call PitchSlideDownLinear %ENDIF UpdateVibrato1: Ret ;EndP UpdateVibrato ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Update Far Push CS Pop DS ;Assume DS:Music %IF USEFPUCODE FNSave FPSave FNInit FLdCW [NewControlWord] %ENDIF Mov CX, MAXSLAVECHANNELS Mov SI, Offset SlaveChannelInformationTable Mov DI, [SI+38h] Mov BX, MIDICOMMAND_TICK Call MIDITranslate Mov ES, SongDataArea Update2: Test Byte Ptr [SI], 1 JZ Update3 ; reset volume Mov BL, [SI+22h] Cmp BL, [SI+21h] JE Update4 Mov [SI+21h], BL Or Byte Ptr [SI], 10h Update4: Mov EAX, [SI+14h] ; Freq Cmp EAX, [SI+10h] JE Update3 Mov [SI+10h], EAX Or Byte Ptr [SI], 20h ; Recalc freq. Update3: Add SI, SLAVECHANNELSIZE Dec CX JNZ Update2 Call UpdateData Test Byte Ptr [ES:2Ch], 4 JZ Update5 Call UpdateInstruments Jmp UpdateEnd Update5: Call UpdateSamples UpdateEnd: Mov CX, NumChannels Mov SI, Offset SlaveChannelInformationTable Mov AX, PlayMode %IF USEFPUCODE FRstor FPSave %ENDIF Ret ;EndP Update ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc UpdateSamples ;Assume DS:Music Mov CX, NumChannels Mov SI, Offset SlaveChannelInformationTable UpdateSamples1: Test Byte Ptr [SI], 1 JZ UpdateSamples2 Mov BX, [SI] ; OK.. if recalc volume is on. ; then recalc volume! :) Push CX Test BL, 16 JZ UpdateSamples3 And BL, Not 16 Mov CL, SoloSample Or BL, 64 ; Recalc final vol Cmp CL, 0FFh JE UpdateSamples6 Cmp [SI+36h], CL JE UpdateSamples6 Or BH, 8 UpdateSamples6: Xor DX, DX Mov AL, [SI+21h] ; AL = vol Mul Byte Ptr [SI+23h] ; Channel volume, AX = 0->64^2 Mov DL, Byte Ptr [SI+24h] ; Sample volume Mul DX ; AX = 0->64*64*128 SHRD AX, DX, 4 ; AX = 0->32768 Mov DL, GlobalVolume Mul DX ; AX = 0->32768*128 SHRD AX, DX, 7 Mov [SI+20h], AH ; Final vol stored. Mov [SI+4Ah], AX UpdateSamples3: Test BL, 2 JZ UpdateSamples4 And BL, Not 2 Or BH, 128 Mov AL, [SI+2Ah] Mov [SI+25h], AL Cmp AL, 100 JE UpdateSamples5 Sub AL, 32 ; Pan = (Pan-32)* Separation/128 + 32 Mov AH, [ES:34h] ShR AH, 1 ; AH = 0->64 (Separation) IMul AH ; AX = -2048->+2048 ; ie. AH = -8->+8 SAR AX, 6 ; AL = -32->+32 Cmp ReverseChannels, 0 JE UpdateSamplePan3 Neg AL UpdateSamplePan3: Add AL, 32 UpdateSamples5: Mov [SI+37h], AL UpdateSamples4: Mov [SI], BX Call UpdateVibrato Pop CX UpdateSamples2: Add SI, SLAVECHANNELSIZE Dec CX JNZ UpdateSamples1 Ret ;EndP UpdateSamples ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc UpdateEnvelope ; Returns Carry if envelope needs ; to be turned off ; Reqs ES:DI points to envelope ; DS:SI points to slave channel envelope structure ; Called only if envelope is ON ; BP != 0 if sustain points released, 0 otherwise Mov DX, [SI+8] ; DX = current pos Cmp DX, [SI+0Ch] ; Expected end pos JAE UpdateEnvelope1 Inc DX Mov EAX, [SI+4] ; Update value Mov [SI+8], DX ; Increase position Add [SI], EAX ClC Ret UpdateEnvelope1: ; Procedure: ; 1) Get current pos' value ; 2) Figure out next pos (inc/loop) ; 3) Figure out delta to next pos ; 4) Terminate if no loop (with carry) ; or place new check in [SI+0Ch] Xor BX, BX Mov BL, [SI+0Ah] ; BX = cur env node LEA AX, [BX+1] LEA BX, [EBX*2+EBX] ; BX = BX*3 Xor DH, DH Mov DL, [ES:DI+BX+6] ShL EDX, 16 Mov [SI], EDX ; Current pos value done. ; AX = next cur env node Mov DX, [ES:DI] Test DL, 6 ; Any loop at all? JZ UpdateEnvelope2 Mov BX, [ES:DI+2] ; Normal Loop Test DL, 4 ; No SusLoop? JZ UpdateEnvelope3 Test BP, BP JNZ UpdateEnvelope4 Mov BX, [ES:DI+4] Jmp UpdateEnvelope3 UpdateEnvelope4: Test DL, 2 JZ UpdateEnvelope2 UpdateEnvelope3: ; Loop Cmp AL, BH JBE UpdateEnvelope2 Xor BH, BH Mov [SI+0Ah], BL ; BL=New node LEA BX, [EBX*2+EBX] Mov AX, [ES:DI+BX+7] Mov [SI+8], AX Mov [SI+0Ch], AX ClC Ret UpdateEnvelope2: ; AX = new node Cmp AL, DH ; DH = number of nodes JB UpdateEnvelope7 StC Ret UpdateEnvelope7: Mov [SI+0Ah], AL ; New node LEA BX, [EAX*2+EAX] Mov DX, [ES:DI+BX+7] ; New node's tick Mov [SI+0Ch], DX Mov AX, [ES:DI+BX+7-3] ; Last node's tick Sub DX, AX Inc AX Mov [SI+8], AX ; For security. Mov AL, [ES:DI+BX+6] ; New node's amplitude Sub AL, [ES:DI+BX+6-3] ; Last node's amplitude Mov BX, DX ; BX = delta(ticks) Xor DX, DX CBW Test AX, AX PushF JNS UpdateEnvelope5 Neg AX UpdateEnvelope5: Sub BX, 1 AdC BX, 1 ; Just to prevent div 0 errors Div BX ShL EAX, 16 ; This clears AX also Div BX ; EAX = value PopF JNS UpdateEnvelope6 Neg EAX UpdateEnvelope6: Mov [SI+4], EAX ; Delta done ClC Ret ;EndP UpdateEnvelope ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ DoMIDICycle DB 0 MIDIPrograms DB 16 Dup (0FFh) ; Do NOT change order! MIDIBanks DW 16 Dup (0FFFFh) MIDIPan DB 16 Dup (0FFh) MIDIPitch DW 16 Dup (2000h) ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc UpdateMIDI ;Assume DS:Music ; Stop cycle Mov CX, MAXSLAVECHANNELS Mov SI, Offset SlaveChannelInformationTable UpdateMIDI1: Test Word Ptr [SI], 200h JZ UpdateMIDI2 Cmp Byte Ptr [SI+36h], 100 JNE UpdateMIDI2 Test Byte Ptr [SI], 1 JZ UpdateMIDI2 Mov Word Ptr [SI], 0 Mov DI, [SI+38h] ; Host channel in DI Mov BX, MIDICOMMAND_STOPNOTE Call MIDITranslate Test Byte Ptr [SI+3Ah], 80h JNZ UpdateMIDI2 Or Byte Ptr [SI+3Ah], 80h And Byte Ptr [DI], Not 4 ; Signify channel off UpdateMIDI2: Add SI, SLAVECHANNELSIZE Dec CX JNZ UpdateMIDI1 ; Play cycle Mov CX, MAXSLAVECHANNELS Mov SI, Offset SlaveChannelInformationTable UpdateMIDI3: Cmp Byte Ptr [SI+36h], 100 ; MIDI Instrument? JNE UpdateMIDI4 Mov DX, [SI] Test DL, 1 JZ UpdateMIDI4 Mov AL, [SI+4Ch] Mov Byte Ptr [SI+4Ch], 1 Mov [SI+2Ch], AL Test DX, 800h ; Muted? JNZ UpdateMIDI4 Mov DI, [SI+38h] ; Host channel in DI And Word Ptr [SI], 0111100010001101b Test DH, 1 JZ UpdateMIDINoPlayNote UpdateMIDIPlayNote: ; Check if there's a bank select. Mov AX, [SI+3Eh] ; MIDI Bank Cmp AX, 0FFFFh JE UpdatemIDIBankSelectDone Mov BL, [SI+3Ch] ; BL = channel And BX, 0FFh Add BX, BX Cmp [MIDIBanks+BX-2], AX JE UpdateMIDIBankSelectDone Mov [MIDIBanks+BX-2], AX ShR BX, 1 Mov [MIDIPrograms+BX-1], 0FFh ; Reset program Mov BX, MIDICOMMAND_BANKSELECT Call MIDITranslate UpdateMIDIBankSelectDone: ; Check for a program specification Cmp Byte Ptr [SI+3Dh], 0 JL UpdateMIDIProgramDone Mov BL, [SI+3Ch] ; BL = channel And BX, 0FFh Mov AL, [SI+3Dh] ; MIDI program Cmp [MIDIPrograms+BX-1], AL JE UpdateMIDIProgramDone Mov [MIDIPrograms+BX-1], AL Mov BX, MIDICOMMAND_PROGRAMSELECT Call MIDITranslate UpdateMIDIProgramDone: ; Check for MIDI pitch wheel.. Test Byte Ptr [ES:2Ch], 64 JZ UpdateMIDINoPitchWheel Mov BL, [SI+3Ch] ; BL = channel And BX, 0FFh Add BX, BX Cmp [MIDIPitch+BX-2], 2000h JE UpdateMIDINoPitchWheel Mov [MIDIPitch+BX-2], 2000h Mov AL, [SI+3Ch] Dec AL Or AL, 0E0h Call MIDISendFilter Xor AL, AL Call MIDISendFilter ; Reset pitch wheel Mov AL, 40h Call MIDISendFilter UpdateMIDINoPitchWheel: Mov EAX, [SI+14h] Mov BX, MIDICOMMAND_PLAYNOTE Mov [SI+1Ch], EAX Call MIDITranslate Jmp UpdateMIDINoChangeVolume UpdateMIDINoPlayNote: ; Change in volume? Test DL, 64 JZ UpdateMIDINoChangeVolume Mov BX, MIDICOMMAND_CHANGEVOLUME Call MIDITranslate UpdateMIDINoChangeVolume: Test DH, 80h ; Pan changed? JZ UpdateMIDINoChangePan Mov BL, [SI+3Ch] ; BL = channel And BX, 0FFh Mov AL, [SI+37h] ; FPP Cmp [MIDIPan+BX-1], AL JE UpdateMIDINoChangePan Mov [MIDIPan+BX-1], AL Mov BX, MIDICOMMAND_CHANGEPAN Call MIDITranslate UpdateMIDINoChangePan: ; Pitch changed? Test DL, 32 JZ UpdateMIDINoPitchChange Mov BX, MIDICOMMAND_CHANGEPITCH Call MIDITranslate UpdateMIDINoPitchChange: UpdateMIDI4: Add SI, SLAVECHANNELSIZE Dec CX JNZ UpdateMIDI3 Ret ;EndP UpdateMIDI ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc UpdateInstruments ;Assume DS:Music ; Things to update: ; 1) Volume envelope ; 2) Fadeout ; 3) FinalVolume ; 4) Vibrato. ; Turn off channel if ; 1) Volume envelope is off & VEV = 0 or ; 2) Fadeout = 0 Mov CX, MAXSLAVECHANNELS Mov SI, Offset SlaveChannelInformationTable Mov [DoMIDICycle], 0 UpdateInstruments1: Test Byte Ptr [SI], 1 JNZ UpdateInstruments16 ; Channel on!! UpdateInstruments2: Add SI, SLAVECHANNELSIZE Dec CX JNZ UpdateInstruments1 Cmp [DoMIDICycle], 0 JE UpdateInstrumentNoMIDICycle Call UpdateMIDI UpdateInstrumentNoMIDICycle: Ret ; UpdateInstruments14: ; Jmp UpdateInstruments5 ; Jump point UpdateInstruments16: Push CX Mov CX, [SI] MovZX EDI, Word Ptr [SI+30h] ; ES:DI = instrument Cmp Byte Ptr [SI+33h], 0FFh ; No instrument? JE UpdateInstruments5 ; Prev Intruments14 Mov BP, CX And BP, 4 ; BP = sustain for envelope calls UpdatePitchEnvelope: Test CH, 40h JZ UpdatePitchEnvelopeApply Push SI Push DI Add SI, 70h Add DI, 1D4h Call UpdateEnvelope Pop DI Pop SI JNC UpdatePitchEnvelopeApply And CH, Not 40h UpdatePitchEnvelopeApply: Test Byte Ptr [ES:DI+1D4h], 80h JZ UpdatePitchEnvelopePitch Cmp Byte Ptr [SI+36h], 100 JE UpdatePanEnvelope UpdatePitchEnvelopeFilter: Mov BX, [SI+71h] SAR BX, 6 ; Range -128 to +128 Add BX, 128 ; Range 0 -> 256 Cmp BH, 1 AdC BL, -1 Mov [SI+3Eh], BL Or CL, 64 ; Recalculate final volume ; Test Byte Ptr [SI+3Ah], 80h ; JNZ UpdatePanEnvelope ; ; Call SetFilterCutoff ; Jmp UpdatePanEnvelope UpdatePitchEnvelopePitch: Mov BX, [SI+71h] SAR BX, 3 JZ UpdatePanEnvelope %IF E USEFPUCODE JS UpdatePitchEnvDown %ENDIF Push DI Mov DI, [SI+38h] Call PitchSlideUpLinear ; req: DS:SI points to table ; DS:DI points to host channel ; BX = magnintude Pop DI %IF E USEFPUCODE Jmp UpdatePostPitchEnvelope UpdatePitchEnvDown: Neg BX Call PitchSlideDownLinear UpdatePostPitchEnvelope: %ENDIF Or CL, 32 ; Recalculate freq UpdatePanEnvelope: Test CH, 20h JZ UpdateVolumeEnvelope Or CL, 2 ; Recalculate pan Push SI Push DI Add SI, 60h Add DI, 182h Call UpdateEnvelope Pop DI Pop SI JNC UpdateVolumeEnvelope And CH, Not 20h UpdateVolumeEnvelope: Test CH, 10h ; Volume envelope on? JZ UpdateInstruments3 Or CL, 16 ; Recalculate volume Push SI Push DI Add SI, 50h Add DI, 130h Call UpdateEnvelope Pop DI Pop SI JC UpdateVolumeEnvelope1 Test CL, 8 ; Note fade on? JNZ UpdateInstruments13 ; Now, check if loop + sustain ; off Test BP, BP JZ UpdateInstruments5 Test Byte Ptr [ES:DI+130h], 2 ; Normal vol env loop? JNZ UpdateInstruments19 Jmp UpdateInstruments5 ; Volume calculation UpdateVolumeEnvelope1: ; Envelope turned off... And CH, Not 10h ; Turn off envelope flag Cmp Byte Ptr [SI+52h], 0 ; Turn off if end of loop is JE UpdateInstruments17 ; reached Jmp UpdateInstruments19 UpdateInstruments3: Test CL, 8 ; Note fade?? JNZ UpdateInstruments13 ; Also apply fade if No vol env ; AND sustain off Test CL, 4 ; Note off issued? JZ UpdateInstruments5 UpdateInstruments19: Or CL, 8 UpdateInstruments13: Mov AX, [ES:DI+14h] ; AX = fadeout. Sub [SI+26h], AX JG UpdateInstruments4 Mov Word Ptr [SI+26h], 0 UpdateInstruments17: ; Turn off channel Test Byte Ptr [SI+3Ah], 80h JNZ UpdateInstruments18 Or Byte Ptr [SI+3Ah], 80h ; Host channel exists Mov BX, [SI+38h] And Byte Ptr [BX], Not 4 UpdateInstruments18: ; Mov Word Ptr [SI], 200h ; Pop CX ; Jmp UpdateInstruments2 Or CH, 2 UpdateInstruments4: Or CL, 16 ; Recalc volume flag. UpdateInstruments5: Test CL, 16 JZ UpdateInstrument10 ; Calculate volume And CL, Not 16 Mov DX, Word Ptr [SoloSample] ; DL = sample, DH = inst Or CL, 64 ; Recalc final volume Mov AL, [SI+21h] ; Note volume.. Mul Byte Ptr [SI+23h] ; Channel volume ; AX = (0->4096) Cmp DL, 0FFh JE UpdateInstrumentNoSampleSolo Cmp [SI+36h], DL JNE UpdateInstrumentSolo UpdateInstrumentNoSampleSolo: Cmp DH, 0FFh JE UpdateInstrumentNoInstrumentSolo Cmp [SI+33h], DH JE UpdateInstrumentNoInstrumentSolo UpdateInstrumentSolo: Or CH, 8 UpdateInstrumentNoInstrumentSolo: Mul Word Ptr [SI+26h] ; Fadeout Vol (0->1024) ; DX:AX = 0->4194304 SHRD AX, DX, 7 ; AX = (0->32768) Mov DL, [SI+24h] ; Sample volume Mul DX ; DX:AX = 0->4194304 SHRD AX, DX, 7 ; AX = 0->32768 Mov DX, Word Ptr [SI+51h] ; VEV, 0->64*256 Mul DX ; DX:AX = 0->536870912 SHRD AX, DX, 14 ; AX = 0->32768 Xor DH, DH Mov DL, GlobalVolume Mul DX ; DX:AX = 0->4194304 SHRD AX, DX, 7 Mov [SI+20h], AH Mov [SI+4Ah], AX UpdateInstrument10: Test CL, 2 ; Change in panning? JZ UpdateInstrument20 And CL, Not 2 Or CH, 128 Mov DL, [SI+2Ah] ; DL = actual pan Mov AL, DL Cmp DL, 100 JE UpdateInstrumentSurroundPan Mov AL, 32 Sub AL, DL CBW Xor AL, AH Sub AL, AH ; AL = |32-ActualPan| Neg AL Add AL, 32 IMul Byte Ptr [SI+62h] ; Pan envelope.. SAR AX, 5 Add AL, DL Mov [SI+25h], AL ; Value to show.. Sub AL, 32 ; Pan = (Pan-32)* Separation/128 + 32 Mov AH, [ES:34h] ShR AH, 1 ; AH = 0->64 (Separation) IMul AH ; AX = -2048->+2048 ; ie. AH = -8->+8 SAR AX, 6 ; AL = -32->+32 Cmp ReverseChannels, 0 JE UpdateInstrumentPan3 Neg AL UpdateInstrumentPan3: Add AL, 32 Jmp UpdateInstrumentPan2 UpdateInstrumentSurroundPan: Mov [SI+25h], AL UpdateInstrumentPan2: Mov [SI+37h], AL UpdateInstrument20: Mov [SI], CX Call UpdateVibrato Cmp Byte Ptr [SI+36h], 100 ; MIDI? JNE UpdateInstrumentsNoMIDI Mov [DoMIDICycle], 1 UpdateInstrumentsNoMIDI: Pop CX Jmp UpdateInstruments2 ;EndP UpdateInstruments ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc UpdateData ;Assume DS:Music Mov CX, 64 Mov AX, PlayMode Cmp AX, 1 JE UpdateData_PlayMode1 JB UpdateData_PlayMode0 Jmp UpdateData_PlayMode2 UpdateData_PlayMode0: ; Step through each channel. ; Check if on/updatemode OK Mov DI, Offset HostChannelInformationTable UpdateData1: Cmp Byte Ptr [DI+21h], 0 JE PlayMode0UpdateVolume1 Dec Byte Ptr [DI+21h] ; Handle counter JNZ UpdateData4 And Word Ptr [DI], Not 303h ; Turn off mode. UpdateData4: Mov AX, [DI] Test AL, 4 ; Channel on? JZ UpdateData2 Test AH, 1 JZ UpdateData2 ; Don't update effect?? PlayMode0UpdateVolume2: Push CX Mov BX, [DI+0Ah] And BX, 7 Add BX, BX Call Word Ptr [VolumeEffectTable+BX] Pop CX Mov AL, [DI] UpdateData2: Test AL, 2 JNZ UpdateData3 ; Update effect regardless.. Test AL, 4 ; Channel on? JZ PlayMode0UpdateVolume1 Test AL, 1 JZ PlayMode0UpdateVolume1 ; Don't update effect?? UpdateData3: ; OK. now handle counter. Push CX Mov BX, [DI+6] And BX, 31 Add BX, BX Call Word Ptr [CommandTable+BX] Pop CX PlayMode0UpdateVolume1: Add DI, HOSTCHANNELSIZE ; Progress to next channel Dec CX JNZ UpdateData1 Ret ; That's all! UpdateData_PlayMode1: ; Pattern stuff.. Dec ProcessTick Dec CurrentTick JZ UpdateData_Pattern1 UpdateData_NoNewRow: ; OK. call update command. Mov DI, Offset HostChannelInformationTable UpdateData_NoNewRow1: Mov AX, [DI] ; AX = host flags. Test AL, 4 JZ UpdateData_NoNewRow5 Test AH, 1 JZ UpdateData_NoNewRow5 UpdateData_NoNewRow4: Push CX Mov BX, [DI+0Ah] And BX, 7 Add BX, BX Call Word Ptr [VolumeEffectTable+BX] Pop CX Mov AL, [DI] ; AX = host flags. UpdateData_NoNewRow5: Test AL, 3 JZ UpdateData_NoNewRow2 Test AL, 2 JNZ UpdateData_NoNewRow3 Test AL, 4 JZ UpdateData_NoNewRow2 UpdateData_NoNewRow3: Push CX Mov BX, [DI+6] And BX, 31 Add BX, BX Call Word Ptr [CommandTable+BX] Pop CX UpdateData_NoNewRow2: Add DI, HOSTCHANNELSIZE Dec CX JNZ UpdateData_NoNewRow1 Ret UpdateData_Pattern1: ; OK... have to update row. Mov AX, CurrentSpeed Mov CurrentTick, AX Mov ProcessTick, AX Dec RowDelay JNZ UpdateEffectData Mov Word Ptr RowDelay, 1 Mov AX, ProcessRow Inc AX ; Progress to new row. Cmp AX, NumberOfRows JB UpdateData_Pattern2 Cmp StopEndOfPlaySection, 0 JNE UpdateDataStopSong ; Wrap row. Xor AX, AX XChg AX, BreakRow UpdateData_Pattern2: Jmp UpdateData_Song1 ; Mov ProcessRow, AX ; Mov CurrentRow, AX ; ; ; Gotta get note data. ; Call UpdateNoteData ; Ret UpdateEffectData: Mov DI, Offset HostChannelInformationTable UpdateEffectData1: Test Byte Ptr [DI], 64 JZ UpdateEffectData2 Mov AL, [DI+2] Test AL, 88h JZ UpdateEffectData2 Push AX Push CX And AL, 88h Mov [DI+2], AL Mov BL, [DI+6] And BX, 31 Add BX, BX Call Word Ptr [InitCommandTable + BX] ; Init note Pop CX Pop AX Mov [DI+2], AL UpdateEffectData2: Add DI, HOSTCHANNELSIZE Dec CX JNZ UpdateEffectData1 Ret UpdateData_PlayMode2: Dec ProcessTick Dec CurrentTick JNZ UpdateData_NoNewRow ; Play song stuff... Mov AX, CurrentSpeed Mov CurrentTick, AX Mov ProcessTick, AX Dec RowDelay JNZ UpdateEffectData Mov Word Ptr RowDelay, 1 Mov AX, ProcessRow Inc AX Cmp AX, NumberOfRows JB UpdateData_Song1 Test OrderLockFlag, 1 JNZ UpdateData_Song5 Mov BX, ProcessOrder ; Get new pattern. Xor DX, DX Inc BX UpdateData_Song2: Cmp BX, 100h JGE UpdateData_Song4 Mov CL, [ES:BX+100h] ; CL = next pattern. Cmp CL, 200 JB UpdateData_Song3 Inc BX Cmp CL, 0FEh JE UpdateData_Song2 Mov StopSong, 1 Cmp StopEndOfPlaySection, 0 JE UpdateData_Song4 UpdateDataStopSong: Call Music_Stop ; Optionally.. loop! Ret UpdateData_Song4: Test DX, DX JNZ UpdateDataStopSong Inc DX Xor BX, BX Jmp UpdateData_Song2 UpdateData_Song3: Mov ProcessOrder, BX Mov CurrentOrder, BX Mov Byte Ptr CurrentPattern, CL UpdateData_Song5: Xor AX, AX XChg AX, BreakRow UpdateData_Song1: Mov ProcessRow, AX Mov CurrentRow, AX Call UpdateNoteData Ret ;EndP UpdateData ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetNumberOfSamples Far ; Returns AX Push CX Push DS Push SI Push ES Push DI Push CS Pop DS ;Assume DS:Music Mov ES, SongDataArea Mov DI, 63912-160 Mov AX, 99 Music_GetNumberOfSamples1: Mov CX, 80 Mov SI, Offset SampleHeader RepE CmpsB JNE Music_GetNumberOfSamples2 Sub DI, 160 Dec AX JNZ Music_GetNumberOfSamples1 Music_GetNumberOfSamples2: Pop DI Pop ES Pop SI Pop DS Pop CX Ret ;EndP Music_GetNumberOfSamples ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetNumberOfInstruments Far ; Returns AX Push CX Push DS Push SI Push ES Push DI Push CS Pop DS ;Assume DS:Music Mov ES, SongDataArea Mov DI, 55912-554*2 Mov AX, 99 Music_GetNumberOfInstruments1: Mov CX, 554 Mov SI, Offset InstrumentHeader RepE CmpsB JNE Music_GetNumberOfInstruments2 Sub DI, 1108 Dec AX JNZ Music_GetNumberOfInstruments1 Music_GetNumberOfInstruments2: Pop DI Pop ES Pop SI Pop DS Pop CX Ret ;EndP Music_GetNumberOfInstruments ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetSampleHeader Far ; AX = sample, 1 based Mov SI, AX Mov DS, CS:SongDataArea Add SI, SI Mov SI, [DS:64910+SI] Ret ;EndP Music_GetSampleHeader ; Returns DS:SI ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetSampleLocation Far ; AX = sample (1based) ; CH = page. ; Returns DS:ESI ; ECX = length ; Carry if no sample. ; Zero set if 8 bit Mov CS:LastSample, AX Push AX Push BX Push DX Mov BX, AX Add BX, BX Mov DS, CS:SongDataArea Mov BX, [64910+BX] Test Byte Ptr [BX+12h], 1 JZ Music_GetSampleLocationEnd Music_GetSampleLocation3: Mov AL, [BX+48h] Test AL, AL JZ Music_GetSampleLocationEnd Cmp AL, 2 JA Music_GetSampleLocationEnd JE Music_GetSampleLocation4 Mov AX, [BX+4Ah] Xor CL, CL ShL CX, 2 Add AX, CX Jmp Music_GetSampleLocation2 Music_GetSampleLocation4: Mov DX, [BX+4Ah] Mov CL, [BX+49h] Call E_MapEMSMemory Call E_GetEMSPageFrame Music_GetSampleLocation2: Xor ESI, ESI Mov ECX, [BX+30h] Test Byte Ptr [BX+12h], 2 ; Zero flag for 8-bit. Mov DS, AX Music_GetSampleLocation5: ClC Jmp Music_GetSampleLocationEnd2 ; Need to preserve zero flag Music_GetSampleLocationEnd: StC Music_GetSampleLocationEnd2: Pop DX Pop BX Pop AX Ret ;EndP Music_GetSampleLocation ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; Accessed via Int 3 Proc Music_UpdateSampleLocation Far ; Reqs ESI. PushAD Mov AX, CS:LastSample Mov ECX, ESI ShR ECX, 8 ShL CH, 2 Call Music_GetSampleLocation PopAD IRet ;EndP Music_UpdateSampleLocation ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_FarUpdateSampleLocation Far PushF PushF ClI Call Far Ptr Music_UpdateSampleLocation PopF Ret ;EndP Music_FarUpdateSampleLocation ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetPlayMode Far Push DS Push CS Pop DS ;Assume DS:Music Mov AX, PlayMode Mov BX, CurrentRow Mov CX, CurrentPattern Mov DX, CurrentOrder Mov SI, NumberOfRows Pop DS Ret ;Assume DS:Nothing ;EndP Music_GetPlayMode ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetPlayMode2 Far Push DS Push CS Pop DS ;Assume DS:Music Mov AX, PlayMode Mov EBX, DWord Ptr CurrentOrder Mov CX, CurrentRow ShL ECX, 16 Mov CX, CurrentTick Pop DS Ret ;EndP Music_GetPlayMode2 ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_PlayPattern Far ; AX = pattern, BX = number of rows ; CX = row to start Push DS Call Music_Stop Push CS Pop DS ;Assume DS:Music Mov MIDIPitchDepthSent, 0 Mov LastMIDIByte, 0FFh Mov CurrentPattern, AX Mov CurrentRow, CX Dec CX Mov NumberOfRows, BX Mov ProcessRow, CX Mov PlayMode, 1 Pop DS Ret ;EndP Music_PlayPattern ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_PlaySong Far ; AX = Order PushA Push DS Call Music_Stop Push CS Pop DS ;Assume DS:Music Mov MIDIPitchDepthSent, 0 Mov LastMIDIByte, 0FFh Mov CurrentOrder, AX Dec AX Mov ProcessOrder, AX Mov ProcessRow, 0FFFEh Mov PlayMode, 2 Call StartClock Mov BX, MIDICOMMAND_START Mov SI, Offset SlaveChannelInformationTable Call MIDITranslate Pop DS PopA Ret ;EndP Music_PlaySong ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_PlayPartSong Far ; AX = order, BX = row. Push AX Push BX Push DS Call Music_Stop Mov CS:NumberOfRows, 200 Mov CS:ProcessOrder, AX Mov CS:CurrentOrder, AX Mov CS:CurrentRow, BX Dec BX Mov CS:ProcessRow, BX Mov BX, AX Mov DS, CS:SongDataArea MovZX AX, Byte Ptr [DS:BX+100h] Mov CS:CurrentPattern, AX Mov CS:PlayMode, 2 Call StartClock Pop DS Pop BX Pop AX Ret ;EndP Music_PlayPartSong ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_KBPlaySong Far Xor AX, AX Cmp CS:PlayMode, 2 JNE Music_PlaySong Ret ;EndP Music_KBPlaySong ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_StopChannels Push CX Push DS Push SI Push DI Push CS Pop DS ;Assume DS:Music Mov CX, 64 Mov SI, Offset HostChannelInformationTable Music_StopChannels1: Mov Word Ptr [SI], 0 Mov Word Ptr [SI+26h], 0 Add SI, HOSTCHANNELSIZE Loop Music_StopChannels1 Mov CX, MAXSLAVECHANNELS Mov SI, Offset SlaveChannelInformationTable Music_StopChannels2: Test Byte Ptr [SI], 1 JZ Music_StopChannelsNoMIDI Cmp Byte Ptr [SI+36h], 100 JNE Music_StopChannelsNoMIDI PushF ClI Mov DI, [SI+38h] Mov BX, MIDICOMMAND_STOPNOTE Call MIDITranslate PopF Music_StopChannelsNoMIDI: Mov Word Ptr [SI], 200h Add SI, SLAVECHANNELSIZE Loop Music_StopChannels2 Pop DI Pop SI Pop DS Pop CX Ret ;EndP Music_StopChannels ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_Stop Far PushA PushF Push DS Push ES CLI Push CS Pop DS ;Assume DS:Music ; Turn off MIDI channels first. Test OrderLockFlag, 1 JZ Music_StopNoOrderLocked Call Music_ToggleOrderUpdate Music_StopNoOrderLocked: Mov CX, MAXSLAVECHANNELS Mov SI, Offset SlaveChannelInformationTable Music_StopMIDI1: Test Byte Ptr [SI], 1 JZ Music_StopNoMIDI Cmp Byte Ptr [SI+36h], 100 JNE Music_StopNoMIDI Mov DI, [SI+38h] Mov BX, MIDICOMMAND_STOPNOTE Call MIDITranslate Music_StopNoMIDI: Add SI, SLAVECHANNELSIZE Loop Music_StopMIDI1 Mov BX, MIDICOMMAND_STOP ; Stop Mov SI, Offset SlaveChannelInformationTable Call MIDITranslate Mov PlayMode, 0 Mov DecodeExpectedPattern, 0FFFEh Mov DecodeExpectedRow, 0FFFEh Mov RowDelay, 1 Mov CurrentRow, 0 Mov CurrentOrder, 0 Mov CurrentTick, 1 Mov BreakRow, 0 Push CX Push DS Push SI Push DI Push CS Pop ES Mov DI, Offset MIDIPrograms Mov CX, 32 Mov AX, 0FFFFh Rep StosW Mov DI, Offset HostChannelInformationTable Mov DS, SongDataArea ;Assume DS:Nothing Mov SI, 40h Mov DX, 040h Xor AX, AX Music_Clear1: Mov CX, 16 Rep StosW Mov AL, DH StosW Xor AX, AX Mov CX, 6 Rep StosW Mov AH, [SI+40h] LodsB And AL, 7Fh StosW Xor AX, AX Mov CX, 16 Rep StosW Inc DH Dec DL JNZ Music_Clear1 ; Now clear SlaveChannel Mov DX, MAXSLAVECHANNELS Music_Clear2: Mov AX, 200h StosW Mov CX, SLAVECHANNELSIZE/2-1 Xor AX, AX Rep StosW Dec DX JNZ Music_Clear2 Push DS Pop ES ; ES = SongDataArea Pop DI Pop SI Pop DS Pop CX ;Assume DS:Music Mov AX, [ES:32h] ; AL = speed, AH = tempo Mov BX, [ES:30h] ; BL = globalvol Xor DX, DX Mov DL, AL Mov GlobalVolume, BL Mov CurrentSpeed, DX Mov ProcessTick, DX Mov Tempo, AH Call Music_InitTempo Call MIDI_ClearTable Pop ES Pop DS PopF PopA Ret ;EndP Music_Stop ;Assume DS:Nothing, ES:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_UpdatePatternOffset Far Mov CS:DecodeExpectedPattern, 0FFFEh Ret ;EndP Music_UpdatePatternOffset ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_PlayNote Far ; DS:SI points to 5-note struct ; AX = channel ; DH = +32 means ignore mute ; settings ; DH = +128 means to use central ; pan and max volume. PushAD Push DS Push ES Mov AH, HOSTCHANNELSIZE Mul AH Mov DI, Offset HostChannelInformationTable Add DI, AX Mov ES, CS:SongDataArea Xor DL, DL ; DL = mask ClI LodsB Cmp AL, NONOTE JE Music_PlayNote1 Or DL, 1 Mov [CS:DI+3], AL Music_PlayNote1: LodsB Test AL, AL JZ Music_PlayNote2 Or DL, 2 Mov [CS:DI+4], AL Music_PlayNote2: LodsB Cmp AL, 0FFh JE Music_PlayNote3 Or DL, 4 Mov [CS:DI+5], AL Music_PlayNote3: LodsW Test AX, AX JZ Music_PlayNote4 Or DL, 8 Music_PlayNote4: Push CS Pop DS ;Assume DS:Music Push DX And DH, 7Fh Mov [DI+6], AX Mov [DI+8], AX Mov [DI+2], DL And Word Ptr [DI], Not (3+32+64+256) Or Byte Ptr [DI], DH ; Now for command update count Mov AX, CurrentSpeed Mov [DI+21h], AL Call PreInitCommand Pop DX Test Byte Ptr [DI], 4 JZ Music_PlayNote5 Test DH, 128 JZ Music_PlayNote5 Mov SI, [DI+24h] Mov Word Ptr [SI+2Ah], 2020h; Pan and pan set. Mov Byte Ptr [SI+23h], 40h ; Full channel volume. Music_PlayNote5: Mov DecodeExpectedRow, 0FFFEh StI Pop ES Pop DS PopAD Ret ;EndP Music_PlayNote ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_PlaySample Far ; AL = Note ; AH = sample number ; CX = channel. PushAD Push DS Push ES Push CS Pop DS ;Assume DS:Music Mov ES, SongDataArea Push AX Mov AX, HOSTCHANNELSIZE Mul CX Add AX, Offset HostChannelInformationTable Mov DI, AX Pop AX ; Mov DI, Offset HostChannelInformationTable ClI Mov Byte Ptr [DI+2], 3 ; Note & Sample Mov [DI+3], AL ; Note... Mov Byte Ptr [DI+4], 0FFh Mov [DI+0Eh], AX Or Word Ptr [DI], 8020h Call InitNoCommand Test Byte Ptr [DI], 4 JZ Music_PlaySample1 Mov SI, [DI+24h] Mov Word Ptr [SI+2Ah], 2020h Mov Byte Ptr [SI+23h], 40h ; Full channel volume. Mov Byte Ptr [SI+3Bh], 0 ; Note cut. Mov Word Ptr [SI+28h], 0 Music_PlaySample1: And Word Ptr [DI], Not 8000h Mov DecodeExpectedRow, 0FFFEh StI Pop ES Pop DS PopAD Ret ;EndP Music_PlaySample ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetHostChannelInformationTable Far Push CS Pop DS ;Assume DS:Music Mov SI, Offset HostChannelInformationTable Ret ;EndP Music_GetHostChannelInformationTable ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetSlaveChannelInformationTable Far Push CS Pop DS ;Assume DS:Music Mov SI, Offset SlaveChannelInformationTable Mov CX, MAXSLAVECHANNELS Ret ;EndP Music_GetSlaveChannelInformationTable ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_NextOrder Far Push DS Push CS Pop DS ;Assume DS:Music Cmp PlayMode, 2 JNE Music_NextOrder1 Mov PlayMode, 0 Call Music_StopChannels Mov ProcessRow, 0FFFEh Mov CurrentTick, 1 Mov RowDelay, 1 Mov PlayMode, 2 Music_NextOrder1: Pop DS Ret ;EndP Music_NextOrder ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_LastOrder Far Push DS Push CS Pop DS ;Assume DS:Music Cmp PlayMode, 2 JNE Music_NextOrder1 Mov AX, ProcessOrder Cmp AX, 0 JLE Music_LastOrder1 ClI Mov PlayMode, 0 Call Music_StopChannels Sub AX, 2 Mov ProcessOrder, AX Mov ProcessRow, 0FFFEh Mov CurrentTick, 1 Mov RowDelay, 1 Mov PlayMode, 2 StI Music_LastOrder1: Pop DS Ret ;EndP Music_LastOrder ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SetGlobalVolume Far Push CX Push DS Push SI Push CS Pop DS ;Assume DS:Music Mov GlobalVolume, AL Call RecalculateAllVolumes Pop SI Pop DS Pop CX Ret ;EndP Music_SetGlobalVolume ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_MuteChannel Far ; AX = channel number Push AX Push CX Push DS Push SI Push DI Push CS Pop DS ;Assume DS:Music Mov CX, NumChannels Mov SI, Offset SlaveChannelInformationTable Music_MuteChannel1: Test Byte Ptr [SI], 1 JZ Music_MuteChannel2 Mov AH, [SI+3Ah] And AH, 07Fh Cmp AH, AL JNE Music_MuteChannel2 Or Word Ptr [SI], 840h Music_MuteChannel2: Add SI, SLAVECHANNELSIZE Loop Music_MuteChannel1 Pop DI Pop SI Pop DS Pop CX Pop AX Ret ;EndP Music_MuteChannel ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_UnmuteChannel Far ; AX = channel number Push AX Push CX Push DS Push SI Push DI Push CS Pop DS ;Assume DS:Music Mov CX, NumChannels Mov Word Ptr [SoloSample], 0FFFFh Mov SI, Offset SlaveChannelInformationTable Music_UnmuteChannel1: Test Byte Ptr [SI], 1 JZ Music_UnmuteChannel2 Mov AH, [SI+3Ah] And AH, 07Fh Cmp AH, AL JNE Music_UnmuteChannel2 Comment ~ Music_UnmuteChannel3: Test DL, DL JS Music_UnmuteChannel5 Cmp [SI+36h], DL JE Music_UnmuteChannel2 Music_UnmuteChannel4: Test DH, DH JS Music_UnmuteChannel5 Cmp [SI+33h], DH JE Music_UnmuteChannel2 Music_UnmuteChannel5: ~ And Byte Ptr [SI+1], Not 8 Or Byte Ptr [SI], 64 Music_UnmuteChannel2: Add SI, SLAVECHANNELSIZE Loop Music_UnmuteChannel1 Pop DI Pop SI Pop DS Pop CX Pop AX Ret ;EndP Music_UnmuteChannel ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ToggleChannel Far ; AX = channel number. Push BX Push DS Mov BX, AX Mov DS, CS:SongDataArea Test Byte Ptr [BX+40h], 80h JZ Music_ToggleChannel1 And Byte Ptr [BX+40h], 7Fh Call Music_UnmuteChannel Mov [CS:MuteChannelTable+BX], 0 Pop DS Pop BX Ret Music_ToggleChannel1: ; Mute channel Xor [CS:MuteChannelTable+BX], 1 Or Byte Ptr [BX+40h], 80h Call Music_MuteChannel Pop DS Pop BX Ret ;EndP Music_ToggleChannel ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_UnmuteAll Far Push BX Push CX Push DX Push DS Push SI Jmp Music_SoloChannel3 Proc Music_SoloChannel Far ; AX = channel Push BX Push CX Push DX Push DS Push SI ; Check & count whether any playing. Mov BX, AX Mov DS, CS:SongDataArea Mov SI, 40h Mov CX, SI Mov DX, CX Music_SoloChannel1: LodsB ShL AL, 1 SbB DX, 0 Loop Music_SoloChannel1 ; DX = num playing. Cmp DX, 1 JNE Music_SoloChannel6 Music_SoloChannel2: ; check whether it's the current Test Byte Ptr [BX+40h], 80h JZ Music_SoloChannel3 Music_SoloChannel6: Mov CX, 64 ; 64 channel to step through ; turn 'em all off. Music_SoloChannel7: Mov SI, CX Dec SI Cmp SI, BX JE Music_SoloChannel9 Test Byte Ptr [SI+40h], 80h JNZ Music_SoloChannel8 Music_SoloChannel10: Mov AX, SI Call Music_ToggleChannel Music_SoloChannel8: Loop Music_SoloChannel7 Jmp Music_SoloChannel11 Music_SoloChannel9: Test Byte Ptr [SI+40h], 80h JZ Music_SoloChannel8 Jmp Music_SoloChannel10 Music_SoloChannel3: ; solo pressed on already soloed ; channel -> turn everything on. Mov CX, 64 Music_SoloChannel4: Mov BX, CX Dec BX Cmp [CS:MuteChannelTable+BX], 1 JNE Music_SoloChannel5 Mov AX, BX Call Music_ToggleChannel Music_SoloChannel5: Loop Music_SoloChannel4 Music_SoloChannel11: Pop SI Pop DS Pop DX Pop CX Pop BX Ret ;EndP Music_SoloChannel ;EndP Music_UnmuteAll ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_InitMuteTable Far Push AX Push CX Push ES Push DI Mov DI, Offset MuteChannelTable Mov CX, 32 Push CS Pop ES Xor AX, AX Rep StosW Mov DWord Ptr [CS:SoloSample], 0FFFFh Pop DI Pop ES Pop CX Pop AX Ret ;EndP Music_InitMuteTable ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_InitStereo Far Push DS Mov DS, CS:SongDataArea Mov AL, [DS:2Ch] And AL, 1 Call [DriverSetStereo] Push CS Pop DS Call RecalculateAllVolumes Pop DS Ret ;EndP Music_InitStereo ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_IncreaseSpeed Far ; Returns AX = speed Mov AX, CS:CurrentSpeed Cmp AX, 1 JE Music_IncreaseSpeed1 Dec AX Mov CS:CurrentSpeed, AX Push DS Mov DS, SongDataArea Mov [DS:32h], AL Pop DS Music_IncreaseSpeed1: Ret ;EndP Music_IncreaseSpeed ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_DecreaseSpeed Far Mov AX, CS:CurrentSpeed Cmp AX, 0FFh JAE Music_DecreaseSpeed1 Inc AX Mov CS:CurrentSpeed, AX Push DS Mov DS, SongDataArea Mov [DS:32h], AL Pop DS Music_DecreaseSpeed1: Ret ;EndP Music_DecreaseSpeed ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SetSoundCard Far ; AL contains sound card num Xor AH, AH Push EBX Mov BX, CS ShL EBX, 16 Mov BX, AX Add BX, BX Mov BX, [CS:DriverSoundCard+BX] Add BX, BX Mov BX, [CS:DriverNameTable+BX] Mov [CS:DriverName], EBX Pop EBX Ret ;EndP Music_SetSoundCard ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SetSoundCardDriver Far Mov Word Ptr [CS:DriverName], SI Mov Word Ptr [CS:DriverName+2], DS Ret ;EndP Music_SetSoundCardDriver ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SetDMA Far Xor AH, AH Mov DMA, AX Ret ;EndP Music_SetDMA ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SetMixSpeed Far ;Assume DS:Nothing Mov CmdLineMixSpeed, CX Ret ;EndP Music_SetMixSpeed ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SetIRQ Far ;Assume DS:Nothing Mov IRQ, CX Ret ;EndP Music_SetIRQ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SetAddress Far Mov BasePort, DX Ret ;EndP Music_SetAddress ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetDisplayVariables Far Mov AX, CS:CurrentSpeed MovZX BX, CS:Tempo MovZX CX, CS:GlobalVolume Ret ;EndP Music_GetDisplayVariables ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_AssignSampleToInstrument Far ; BX = sample num ; returns AX Push CX DX DS SI ES DI Push CS Pop DS ;Assume DS:Music Mov ES, SongDataArea ; Check for sample-number's instrument first. Mov AX, 554 Mul BX Mov DI, AX Add DI, 512 LEA AX, [BX+1] Mov SI, Offset InstrumentHeader Mov CX, 554 RepE CmpsB JE Music_AssignSampleToInstrument4 ; Search Mov CX, 99 Mov DI, 512 ; Points to first inst. Mov AX, 1 Music_AssignSampleToInstrument1: Push CX Mov SI, Offset InstrumentHeader Mov CX, 554 RepE CmpsB JE Music_AssignSampleToInstrument2 Add DI, CX Pop CX Inc AX Loop Music_AssignSampleToInstrument1 StC Music_AssignSampleToInstrumentEnd: Pop DI ES SI DS DX CX Ret Music_AssignSampleToInstrument2: Pop CX ; Clear the stack Music_AssignSampleToInstrument4: %IF NETWORKENABLED Call Network_GetSendQueue JZ Music_AssignSampleNetwork Mov SI, AX Mov AX, 400h StosW Mov AX, SI Dec AX StosB Music_AssignSampleNetwork: Call Network_FinishedSendQueue %ENDIF Push ES Pop DS Sub DI, 554-20h ; Points to name Mov SI, BX Mov SI, [64912+SI+BX] Add SI, 14h Mov CX, 26 Rep MovsB Add DI, 7 ; Now to fill in table. Mov CX, 120 Inc BX Music_AssignSampleToInstrument3: Mov [DI], BL ; Add DI, 2 ScasW Loop Music_AssignSampleToInstrument3 ClC Jmp Music_AssignSampleToInstrumentEnd ;EndP Music_AssignSampleToInstrument ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SetLimit Far Mov CS:CmdLineNumChannels, CX Ret ;EndP Music_SetLimit ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ReverseChannels Far Mov CS:ReverseChannels, 1 Ret ;EndP Music_ReverseChannels ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_IncreaseVolume Far Push CX Push DS Push SI Push CS Pop DS ;Assume DS:Music Mov AL, GlobalVolume And AX, 0FFh Cmp AX, 128 JAE Music_IncreaseVolume1 Inc AX Mov GlobalVolume, AL Call RecalculateAllVolumes Music_IncreaseVolume1: Pop SI Pop DS Pop CX Ret ;EndP Music_IncreaseVolume ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_DecreaseVolume Far Push CX Push DS Push SI Push CS Pop DS ;Assume DS:Music Mov AL, GlobalVolume And AX, 0FFh JZ Music_DecreaseVolume1 Dec AX Mov GlobalVolume, AL Call RecalculateAllVolumes Music_DecreaseVolume1: Pop SI Pop DS Pop CX Ret ;EndP Music_DecreaseVolume ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_RegetLoopInformation Far Push AX Push BX Push CX Push DX Push DS Push SI Push ES Push CS Pop DS ; DS setup ;Assume DS:Music Mov ES, SongDataArea Mov CX, NumChannels Mov SI, Offset SlaveChannelInformationTable Music_RegetLoopInformation1: Test Byte Ptr [SI], 1 JZ Music_RegetLoopInformation2 Push CX ClI Call GetLoopInformation Or Byte Ptr [SI], 40h StI Pop CX Music_RegetLoopInformation2: Add SI, SLAVECHANNELSIZE Loop Music_RegetLoopInformation1 Pop ES Pop SI Pop DS Pop DX Pop CX Pop BX Pop AX Ret ;EndP Music_RegetLoopInformation ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc ResetSoundCardMemory Far Jmp [DriverResetMemory] ;EndP ResetSoundCardMemory ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SoundCardLoadSample Far ; AX = sample number ; (1 based) ; Carry set if insuf mem PushA Call [DriverLoadSample] PushF JC Music_SoundCardLoadSample1 Mov CX, 2 Mov DI, Offset O1_OutOfSoundCardMemoryList Call M_Object1List Music_SoundCardLoadSample1: PopF PopA Ret ;EndP Music_SoundCardLoadSample ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SoundCardLoadAllSamples Far PushAD Push DS Call Music_Stop Call S_SaveScreen Push 30 Push 28 Push 50 Push 30 Push 3 Call S_DrawBox Add SP, 10 Push CS Pop DS Mov DI, (32+29*80)*2 Mov SI, Offset PrepareSamplesMsg Mov AH, 20h Call S_DrawString Call S_UpdateScreen Call ResetSoundCardMemory Mov AX, 1 Music_SoundCardLoadAllSamples1: Call Music_SoundCardLoadSample JNC Music_SoundCardLoadAllSamples2 Inc AX Cmp AX, 100 JBE Music_SoundCardLoadAllSamples1 Music_SoundCardLoadAllSamples3: Call S_RestoreScreen Music_SoundCardLoadAllSamples2: Pop DS PopAD Mov AX, 1 Ret ;EndP Music_SoundCardLoadAllSamples ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetFreeSoundCardMemory Far Call [DriverGetStatus] Ret ;EndP Music_GetFreeSoundCardMemory ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetNumChannels Far Mov AX, CS:NumChannels Ret ;EndP Music_GetNumChannels ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetPitchTable Far ; Returns ES:DI to pitch table Push CS Pop ES Mov DI, Offset PitchTable Ret ;EndP Music_GetPitchTable ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ToggleReverse Far Push CS Pop DS ;Assume DS:Music Xor ReverseChannels, 1 Call ReCalculateAllVolumes Mov SI, Offset ReverseMsg Call SetInfoLine Ret ;EndP Music_ToggleReverse ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_PatternStorage Far Mov CS:PatternStorage, AL Ret ;EndP Music_PatternStorage ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_InitMixTable Far Push AX Push DS Xor AX, AX Mov DS, CS:SongDataArea Mov AL, Byte Ptr [DS:31h] ; AL = 0->128 Call [DriverSetMixVolume] Pop DS Pop AX Ret ;EndP Music_InitMixTable ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetTempo Far Xor BH, BH Mov BL, CS:Tempo Ret ;EndP Music_GetTempo ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetLastChannel Far ; Returns AX Push DS Mov DS, CS:SongDataArea Xor SI, SI Mov CX, 64 Xor AX, AX Xor DX, DX Music_GetLastChannel1: Mov BL, [SI+40h] ShR BL, 7 Xor BL, [CS:MuteChannelTable+SI] JNZ Music_GetLastChannel2 Mov AX, DX Music_GetLastChannel2: Inc DX Inc SI Loop Music_GetLastChannel1 Pop DS Ret ;EndP Music_GetLastChannel ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetDriverScreen Far Jmp [DriverSoundCardScreen] ;EndP Music_GetDriverScreen ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetDriverVariable Far Jmp [DriverGetVariable] ;EndP Music_GetDriverVariable ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SetDriverVariable Far Jmp [DriverSetVariable] ;EndP Music_SetDriverVariable ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SetNextOrder Far Dec AX Mov CS:ProcessOrder, AX Ret ;EndP Music_SetNextOrder ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetDelay Far ClI Xor DX, DX Mov CX, CS:PlayMode Test CX, CX JZ Music_GetDelay2 Mov DX, CS:CurrentSpeed Cmp AX, CS:CurrentRow JNE Music_GetDelay3 Sub DX, CS:ProcessTick JZ Music_GetDelay2 Cmp DX, 0Fh JAE Music_GetDelay4 Jmp Music_GetDelay1 Music_GetDelay3: Dec DX Cmp DX, 0Fh JBE Music_GetDelay1 Music_GetDelay4: Mov DX, 0Fh Music_GetDelay1: ShL DX, 8 Or DX, 'S'-'@'+0D000h Music_GetDelay2: StI Ret ;EndP Music_GetDelay ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ StopSong DB 0 TimerCounter DD 0 TotalTimer DD 0 TotalTimerHigh DD 0 PleaseWaitMsg DB "Please Wait...", 0 Proc InternalTimer Far PushAD Mov EAX, 0C214h Mov DX, 16h ; Ticks = (1193181/(2*0.4))/Tempo Div BX Add EAX, EAX Mov CS:TimerCounter, EAX PopAD Ret ;EndP InternalTimer ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_TimeSong Far ; Time song! Push CS Pop DS ;Assume DS:Music Call S_SaveScreen Mov AL, 1 Call S_SetDirectMode Call S_DrawSmallBox Mov SI, Offset PleaseWaitMsg Mov AH, 20h Mov DI, (33+26*80)*2 Call S_DrawString Call Music_Stop Mov CX, 0FFFFh Music_TimeSong1: In AL, 21h ; Delay mechanism In AL, 0A1h ; Delay mechanism Loop Music_TimeSong1 Mov StopSong, 0 Mov TotalTimer, 0 Mov TotalTimerHigh, 0 ClI In AL, 0A1h Mov AH, AL In AL, 21h Push AX Mov AL, 0FFh Out 0A1h, AL Out 21h, AL Push DWord Ptr [DriverSetTempo] Mov AX, CS ShL EAX, 16 Mov AX, Offset InternalTimer Mov [DriverSetTempo], EAX Push Word Ptr [NumChannels] Mov ES, SongDataArea Push Word Ptr [ES:2Ch] And Byte Ptr [ES:2Ch], Not 4 Xor AX, AX Call Music_PlaySong Music_TimeSong3: ;Assume DS:Nothing Call Update Cmp CS:StopSong, 0 JNE Music_TimeSong4 Mov EAX, CS:TimerCounter Add CS:TotalTimer, EAX AdC CS:TotalTimerHigh, 0 Jmp Music_TimeSong3 Music_TimeSong4: Call Music_Stop Mov ES, CS:SongDataArea Pop Word Ptr [ES:2Ch] Pop Word Ptr [CS:NumChannels] Pop DWord Ptr [CS:DriverSetTempo] Pop AX Out 21h, AL Mov AL, AH Out 0A1h, AL StI Mov AL, 0 Call S_SetDirectMode Call S_RestoreScreen Mov CX, 0FFFFh Mov DI, Offset O1_ShowTime Call M_Object1List Mov AX, 1 Ret ;EndP Music_TimeSong ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ShowTime Far Call S_GetDestination Mov EDX, CS:TotalTimerHigh Mov EAX, CS:TotalTimer SHRD EAX, EDX, 16 Mov DI, (43+27*80)*2 Call D_ShowTime Ret ;EndP Music_ShowTime ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetPatternLength Far Mov AX, CS:NumberOfRows Ret ;EndP Music_GetPatternLength ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_SaveMIDIConfig Far Call D_GotoStartingDirectory Push CS Pop DS ;Assume DS:Music Mov AH, 3Ch Xor CX, CX Mov DX, Offset MIDIConfigFileName Int 21h JC Music_SaveMIDIConfig1 Mov BX, AX Mov AH, 40h Mov DS, CS:MIDIDataArea Xor DX, DX Mov CX, (128+16+9)*32 Int 21h Mov AH, 3Eh Int 21h Music_SaveMIDIConfig1: Xor AX, AX Ret ;EndP Music_SaveMIDIConfig ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_GetMIDIDataArea Far Mov DS, CS:MIDIDataArea Ret ;EndP Music_GetMIDIDataArea ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ToggleOrderUpdate Far Push CS Pop DS ;Assume DS:Music Mov SI, Offset OrderUpdateEnabledMsg Xor OrderLockFlag, 1 JZ Music_ToggleOrderUpdate1 Mov SI, Offset OrderUpdateDisabledMsg Music_ToggleOrderUpdate1: Call SetInfoLine Ret ;EndP Music_ToggleOrderUpdate ;Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ToggleSoloInstrument Far Mov SI, Offset SoloInstrumentMsg Mov DI, Offset SoloInstrument Mov BP, 1 Jmp Music_ToggleSolo ;EndP Music_ToggleSoloInstrument ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ToggleSoloSample Far Mov SI, Offset SoloSampleMsg Mov DI, Offset SoloSample Xor BP, BP ;EndP Music_ToggleSoloSample ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc Music_ToggleSolo Far Push CS Pop DS ;Assume DS:Music Call PE_GetLastInstrument ; Returns BX Mov AX, BX Add BX, BP Cmp [DI], BL Mov Word Ptr [SoloSample], 0FFFFh JE Music_ToggleSolo1 Inc AX Mov Byte Ptr [DI], BL Jmp Music_ToggleSolo2 Music_ToggleSolo1: Mov SI, Offset UnsoloMsg Music_ToggleSolo2: Call SetInfoLine Mov CX, NumChannels Mov SI, Offset SlaveChannelInformationTable Xor BX, BX Mov ES, SongDataArea Music_ToggleSolo3: Or Byte Ptr [SI], 18 Mov BL, [SI+3Ah] ; BX = channel Test Byte Ptr [ES:BX+40h], 80h JNZ Music_ToggleSolo4 And Word Ptr [SI], Not 800h Music_ToggleSolo4: Add SI, SLAVECHANNELSIZE Dec CX JNZ Music_ToggleSolo3 Call RecalculateAllVolumes Mov AX, 1 Ret ;EndP Music_ToggleSolo ;Assume DS:Nothing ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ EndS ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ End