;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; ; Write module functions ; ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc WriteITSampleBlock PushAD ; BX = file handle. Push DS Mov DS, CS:DiskDataArea Mov DX, [DS:1996] Mov CX, [DS:1998] Mov AX, 4200h Int 21h Mov AX, 80 Mul Word Ptr [DS:24h] Mov CX, AX Mov DX, 2000 Call D_SaveBlock WriteITSampleBlock1: Pop DS PopAD Ret EndP WriteITSampleBlock ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ NUMS3MCHANNELS EQU 16 BitLUT Label Byte DB 1, 2, 3, 3, 4, 4, 4, 4 DB 5, 5, 5, 5, 5, 5, 5, 5 DB 4, 4, 4, 4, 3, 3, 2 BitLUT16 Label Byte DB 1, 10 SHL 3 + 3, 11 SHL 3 + 5, 11 SHL 3 + 3 DB 3 DUP (12 SHL 3 + 5), 12 SHL 3 + 3 DB 7 DUP (13 SHL 3 + 5), 13 SHL 3 + 3 DB 13 SHL 3 + 4, 7 DUP (13 SHL 3 + 5) DB 12 SHL 3 + 4, 3 DUP (12 SHL 3 + 5) DB 11 SHL 3 + 4, 11 SHL 3 + 5, 10 SHL 3 + 4, 2 Proc D_SaveIT Far Call PE_SaveCurrentPattern Call D_UpdateFileName Push CS Pop DS Assume DS:Disk Mov NoSaveError, 0 Mov AH, 3Ch Xor CX, CX ; File type is normal (archive) Mov DX, Offset SaveFileName ; DS:DX points to filename Int 21h JNC D_SaveIT3 Call PE_RestoreCurrentPattern Jmp D_NoSaveMessage D_SaveIT3: Mov BX, AX ; BX = handle Mov ES, DiskDataArea Call Music_GetSongSegment Mov DS, AX Assume DS:Nothing ; DS = MusicData Xor SI, SI Xor DI, DI Mov CX, 192 Rep MovsB ; Get header. ; Now to figure out the ; orders. Mov SI, 511 StD Mov CX, 256 D_SaveIT4: LodsB Cmp AL, 0FFh LoopE D_SaveIT4 ClD Add CX, 2 Mov [ES:20h], CX Dec CX Mov SI, 256 Rep MovsB ; Transfer orders. Mov AL, 0FFh StosB ; Mov AX, 0 ; Test Byte Ptr [DS:2Ch], 4 ; JZ D_SaveIT6 ; Call Music_GetNumberOfInstruments ; ; D_SaveIT6: Mov [ES:22h], AX ; Number of instruments Call Music_GetNumberOfSamples Mov [ES:24h], AX ; Number of samples Call PE_GetMaxPattern Inc AX Mov [ES:26h], AX ; Number of patterns. Xor CX, CX ; CX:DX = 'long' offsets. Mov DX, 0C0h Add DX, [ES:20h] Mov AX, [ES:22h] ShL AX, 2 Add DX, AX Mov AX, [ES:24h] ShL AX, 2 Add DX, AX Mov AX, [ES:26h] ShL AX, 2 Add DX, AX Mov DWord Ptr [ES:36h], 0 Mov Word Ptr [ES:2Eh], 4 ; Row hilight information Push DS Push Pattern Pop DS Assume DS:Pattern Mov AX, Word Ptr [RowHilight1] Pop DS Assume DS:Nothing Mov [ES:1Eh], AX Call GetTimerCounter Sub EAX, EditTimer Cmp TimerData, 0 JE NoTimerData Or Byte Ptr [ES:2Eh], 2 ; Contains timer information Push ES ; Put time into table. Push DI Mov ES, TimerData Mov DI, NumTimerData ShL DI, 3 Add DI, 4 StosD Add DI, 2 Add DX, DI ; Long offset progress. AdC CX, 0 Pop DI Pop ES NoTimerData: ; OK.. check for MIDI config save. Test Byte Ptr [DS:2Ch], 128 JZ D_SaveITNoMIDIConfig1 Add DX, 4896 ; MIDI Config size AdC CX, 0 Or Byte Ptr [ES:2Eh], 8 ; MIDI Config. D_SaveITNOMIDIConfig1: Add EAX, [ES:3Ch] Xor EAX, 'JTHL' RoR EAX, 4 Neg EAX RoL EAX, 7 Xor EAX, 'ITRK' Mov [ES:3Ch], EAX Call Msg_GetMessageLength Cmp AX, 1 JE D_SaveITMsg1 Or Byte Ptr [ES:2Eh], 1 Mov Word Ptr [ES:3Ah], 0 Mov [ES:38h], DX Mov [ES:36h], AX Add DX, AX D_SaveITMsg1: Mov BP, [ES:22h] ; Number of instruments Mov AX, 214h Cmp CS:SaveFormat, 0 JE D_SaveNewFormat Inc AX Cmp CS:SaveFormat, 3 JE D_SaveNewFormat Mov AX, 200h D_SaveOldIT2_1: Test BP, BP JNZ D_SaveNewFormat Mov AX, 100h D_SaveNewFormat: Inc BP Mov Word Ptr [ES:28h], TRACKERVERSION Mov [ES:2Ah], AX And EBP, 0FFFFh D_SaveIT7: Dec BP JZ D_SaveIT8 Mov SI, [DS:EBP+EBP+64710] Test Byte Ptr [SI+1D4h], 80h JZ D_SaveIT216 Mov Word Ptr [ES:2Ah], 216h D_SaveIT216: Mov AX, DX StosW Mov AX, CX StosW Add DX, 554 AdC CX, 0 Jmp D_SaveIT7 D_SaveIT8: Mov BP, [ES:24h] ; Number of samples Inc BP Mov [ES:1996], DX ; Store sample position. Mov [ES:1998], CX D_SaveIT9: Dec BP JZ D_SaveIT10 Mov AX, DX StosW Mov AX, CX StosW Add DX, 80 AdC CX, 0 Jmp D_SaveIT9 D_SaveIT10: Xor BP, BP D_SaveIT11: Cmp BP, [ES:26h] ; Number of patterns JAE D_SaveIT12 Push DS Mov AX, BP Call Music_GetPattern ; DS:SI has pattern Mov AX, DS Cmp AX, Music JE D_SaveIT1 Mov AX, DX StosW Mov AX, CX StosW Add DX, [DS:SI] AdC CX, 0 Add DX, 8 ; pattern header length = 8. AdC CX, 0 Jmp D_SaveIT22 D_SaveIT1: Xor EAX, EAX StosD D_SaveIT22: Pop DS Inc BP Jmp D_SaveIT11 D_SaveIT12: ; CX:DX now point to first sample data. Push CX Push DX Push DS Push DI Push CS Pop DS Mov DI, (4+17*80)*2 Mov SI, Offset HeaderMsg Mov AH, 5 Call S_DrawString Pop CX ; CX = length of header. Push ES Pop DS Xor DX, DX Call D_SaveBlock ; Header. Test Byte Ptr [DS:2Eh], 2 ; Time information? JZ D_SaveITTimeData Push DS Push CS Pop DS Mov CX, 2 Mov DX, Offset NumTimerData Inc [DS:NumTimerData] Call D_SaveBlock Mov CX, [DS:NumTimerData] Dec [DS:NumTimerData] ShL CX, 3 Mov DS, [DS:TimerData] Xor DX, DX Call D_SaveBlock Pop DS D_SaveITTimeData: Test Byte Ptr [DS:2Ch], 128 JZ D_SaveITMIDIConfig Push DS Mov CX, 4896 Xor DX, DX Call Music_GetMIDIDataArea ; Gets DS Call D_SaveBlock Pop DS D_SaveITMIDIConfig: ; Message? Test Byte Ptr [DS:2Eh], 1 JZ D_SaveITMsg2 Mov CX, [DS:36h] Push DS Call Msg_GetMessageOffset Call D_SaveBlock Pop DS D_SaveITMsg2: Push CS Pop DS Mov DI, (4+18*80)*2 Mov SI, Offset InstrumentHeaderMsg Mov AH, 5 Call S_DrawString Pop DS Cmp Word Ptr [ES:22h], 0 JE D_SaveIT13 Mov AX, 554 Mul Word Ptr [ES:22h] Mov DX, 512 Mov CX, AX Call D_SaveBlock ; Instrument headers... D_SaveIT13: Push DS Push CS Pop DS Mov DI, (4+19*80)*2 Mov SI, Offset SampleHeaderMsg Mov AH, 5 Call S_DrawString Pop DS ; DS = song data segment Mov SI, 55912 ; Start of samples in mem. Mov AX, 80 Mul Word Ptr [ES:24h] Mov DI, 2000 Mov CX, AX Rep MovsB Pop DX Pop CX ; CX:DX = sample point. Mov BP, [ES:24h] ; Number of samples. Mov SI, 2000 Inc BP D_SaveIT14: Dec BP JZ D_SaveIT16 Mov AL, [ES:SI+12h] Mov AH, 1 Cmp CS:SaveFormat, 3 JNE D_SaveNoDD Or AH, 4 D_SaveNoDD: Test AL, 1 JZ D_SaveIT15 Or AL, 8 Cmp CS:SaveFormat, 2 JNE D_SaveIT214_1 And AL, Not 8 D_SaveIT214_1: Mov [ES:SI+48h], DX Mov [ES:SI+4Ah], CX Test AL, 2 Mov [ES:SI+12h], AL Mov [ES:SI+2Eh], AH Mov EAX, [ES:SI+30h] JZ D_SaveIT16Bit Add EAX, EAX D_SaveIT16Bit: Add DX, AX PushF ShR EAX, 16 PopF AdC CX, AX ; Advance sample pointer. D_SaveIT15: Add SI, 80 Jmp D_SaveIT14 D_SaveIT16: Call WriteITSampleBlock Xor BP, BP D_SaveIT17: Push DS Push CS Pop DS Mov DI, (4+20*80)*2 Mov SI, Offset PatternMsg Mov AH, 5 Push BP Call S_DrawString Pop AX Call Music_GetPattern Mov DX, DS Cmp DX, Music JE D_SaveIT2 Mov DX, SI Mov CX, [DS:SI] Add CX, 8 Call D_SaveBlock D_SaveIT2: Pop DS Inc BP Cmp BP, [ES:26h] JB D_SaveIT17 ; Setup compression block Push DS Push CS Pop DS Mov SI, Offset BitLUT Mov DI, 10240 Mov CX, 16/2 Rep MovsW ; Setup table. Mov CX, 16 Mov AL, 6 Rep StosB Mov CX, 28 Inc AX Rep StosB Mov CX, 64 Inc AX Rep StosB Mov CX, 8 Inc AX Rep StosB Mov CX, 64 Dec AX Rep StosB Mov CX, 29 Dec AX Rep StosB Mov CX, 16 Dec AX Rep StosB Mov CX, 15 Sub SI, 8 Rep MovsB ; 16 bit Main LUT Mov SI, Offset BitLUT16 Mov CX, 16 Rep MovsB Mov CX, 15 Mov AL, 14 SHL 3 + 5 Rep StosB Mov AL, 14 SHL 3 + 3 StosB Mov CX, 31 Mov AL, 15 SHL 3 + 5 Rep StosB Mov AL, 15 SHL 3 + 3 StosB Mov CX, 63 Mov AL, 16 SHL 3 + 5 Rep StosB Mov AL, 16 SHL 3 + 3 StosB Inc AX ; Mov AL, 16 SHL 3 + 4 StosB Mov CX, 63 Inc AX ; Mov AL, 16 SHL 3 + 5 Rep StosB Mov AL, 15 SHL 3 + 4 StosB Mov CX, 31 Mov AL, 15 SHL 3 + 5 Rep StosB Mov AL, 14 SHL 3 + 4 StosB Mov CX, 15 Mov AL, 14 SHL 3 + 5 Rep StosB Mov CX, 16 Rep MovsB ; 16 bit LUT 1, for 16-bit samples with high byte = 0 Mov SI, Offset BitLUT Mov CX, 16 Rep MovsB Mov CX, 16 Mov AL, 6 Rep StosB ; AL = 6 from before Mov CX, 24 Inc AX Rep StosB Mov CX, 64 Inc AX Rep StosB Mov CX, 128 Inc AX Rep StosB ; 16-Bit LUT 2, for 16-bit samples with high byte = 0xFF Mov CX, 16 Inc AX Rep StosB Mov CX, 128 Dec AX Rep StosB Mov CX, 64 Dec AX Rep StosB Mov CX, 25 Dec AX Rep StosB Mov CX, 16 Dec AX Rep StosB Mov CX, 15 Sub SI, 8 Rep MovsB Mov CX, 256-8 Xor AX, AX Rep StosB Mov CX, 16 Inc AX Rep StosB Mov CX, 256-8+256 Dec AX Rep StosB Pop DS Xor BP, BP ; BP = sample number. Mov DI, 2000+48h D_SaveIT18: Push DS Push DI Xor CX, CX Xor DX, DX Mov AX, 4201h Int 21h Mov [ES:DI], AX Mov [ES:DI+2], DX Mov SI, BP Add SI, SI Mov SI, [64912+SI] ; DS:SI points to sample head. Test Byte Ptr [SI+12h], 1 ; Check if sample is present. JZ D_SaveIT19 Cmp DWord Ptr [SI+30h], 0 ; For bodgy sample crap. JZ D_SaveIT19 D_SaveIT21: Push DS ; DS:DX points to sample... Push SI Push CS Pop DS Mov DI, (4+21*80)*2 Mov SI, Offset SampleMsg Mov AX, BP Inc AX Push AX Mov AH, 5 Call S_DrawString Pop AX Pop SI Pop DS ; Sample encoding to go here.. ; But sample position needs to ; be recoded then... Cmp CS:SaveFormat, 2 JNE D_SaveSampleDataCompressedCall Call D_SaveSampleData Jmp D_SaveIT19 D_SaveSampleDataCompressedCall: Call D_SaveSampleDataCompressed D_SaveIT19: Pop DI Pop DS Add DI, 80 Inc BP Cmp BP, [ES:24h] JB D_SaveIT18 Call WriteITSampleBlock Mov AH, 3Eh ; Close file Int 21h Push CS Pop DS Mov DI, (4+23*80)*2 Mov SI, Offset CompleteMsg Mov AH, 5 Call S_DrawString EndSaveModule: Mov DX, Offset SaveFileName Call D_DeleteIfError Call PE_RestoreCurrentPattern Cmp NoSaveError, 0 JNE SaveModuleError Call PEResetModified SaveModuleError: Mov AX, 1 Ret EndP D_SaveIT Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc D_SaveS3M Far Call PE_SaveCurrentPattern Call D_UpdateFileName Mov BP, 60h ; BP = length of header. ; Call PE_StoreCurrentPattern Push CS Pop DS Assume DS:Disk Mov SaveFormatError, 0 Mov NoSaveError, 0 Mov AH, 3Ch Xor CX, CX ; File type is normal (archive) Mov DX, Offset SaveFileName ; DS:DX points to filename Int 21h JNC D_SaveS3M1 Call PE_RestoreCurrentPattern Jmp D_NoSaveMessage D_SaveS3M1: Mov BX, AX Mov ES, DiskDataArea Call Music_GetSongSegment Mov DS, AX Assume DS:Nothing ; DS = MusicData Mov SI, 4 Xor DI, DI Mov CX, 26/2 Rep MovsW Xor AX, AX StosW Mov AX, 1Ah+16*256 ; St3 module identification. StosW Xor AX, AX StosW ; Now to figure out the ; orders. Mov SI, 511 StD Mov CX, 256 D_SaveS3M2: LodsB Cmp AL, 0FFh LoopE D_SaveS3M2 ClD Inc CX Mov AX, CX Inc AX ; Number of orders. Add BP, AX StosW Call Music_GetNumberOfSamples Add BP, AX Add BP, AX StosW ; Number of samples. Call PE_GetMaxPattern Inc AX Add BP, AX Add BP, AX Cmp AX, 100 JBE D_SaveS3M4 Mov AX, 100 Push Offset D_SaveS3M4 Push SI Push DI Mov SI, Offset TooManyPatternsMsg Mov DI, (4+23*80)*2 Jmp D_SaveS3MFormatError D_SaveS3M4: StosW ; Number of patterns ; Flags... 8 = vol0opt on. Mov AX, [DS:2Ch] And AX, 2 ShL AX, 2 StosW ; Flags stored. Mov AX, 3000h+TRACKERVERSION StosW ; Impulse Tracker Mov AX, 2 StosW ; Standard unsigned samples. Mov EAX, 'MRCS' StosD ; ID done. Mov AH, [DS:2Ch] Test AH, 4 JZ D_SaveS3MNoInsError Push Offset D_SaveS3MNoInsError Push SI Push DI Mov SI, Offset ST3InstrumentErrorMsg Mov DI, (4+29*80)*2 Jmp D_SaveS3MFormatError D_SaveS3MNoInsError: Mov AL, [DS:30h] ShR AL, 1 StosB Mov AX, [DS:32h] ; Tempo and speed StosW Mov AL, [DS:31h] ; Mixing volume Mov AH, [DS:2Ch] ; Grab stereo setting. Cmp AL, 80h JB D_SaveNoMixOverflow Mov AL, 7Fh D_SaveNoMixOverflow: ShL AL, 1 ShR AX, 1 StosB Mov AX, 252*256 StosW Xor AX, AX StosW Call GetTimerCounter Sub EAX, EditTimer Add EAX, [DS:3Ch] Xor EAX, 'JTHL' RoR EAX, 4 Neg EAX RoL EAX, 7 Xor EAX, 'ITRK' StosD Xor AX, AX StosW Mov SI, 256 ; Orders. Mov DI, 60h JCXZ D_SaveS3M3 D_SaveS3M5: LodsB Cmp AL, 0FEh JAE D_SaveS3M6 Cmp AL, 100 JB D_SaveS3M6 Mov AL, 0FFh ; So that pattern numbers >= 100 aren't listed D_SaveS3M6: StosB Loop D_SaveS3M5 D_SaveS3M3: Mov AL, 0FFh StosB ; Do channel settings. Push BX Mov BX, BP Mov SI, 40h Mov DI, SI Sub BX, DI Mov CX, 32 Xor AH, AH D_SaveS3M7: LodsB Test AL, 80h JNZ D_SaveS3M9 Cmp AL, 64 JBE D_SaveS3M8 Mov AL, 32 ; For surround. D_SaveS3M8: ; Convert 0->64 to 0->15 Mov DL, AL ShR DL, 1 Sub DL, 1 AdC DL, 0 ShR DL, 1 Or DL, 32 ; Reqd... Mov AL, AH And AL, 1 ShL AL, 3 Mov DH, AH ShR DH, 1 Or AL, DH Inc AH Jmp D_SaveS3M10 D_SaveS3M9: ; Muted/nonexistant Mov AL, 0FFh Mov DL, 0 D_SaveS3M10: Mov [ES:BX+DI], DL StosB Loop D_SaveS3M7 Pop BX Add BP, 20h ; Check that channel volumes are all 64... Mov CX, 32 Mov SI, 80h D_SaveS3M11: LodsB Cmp AL, 64 JNE D_SaveS3M12 Loop D_SaveS3M11 Jmp D_SaveS3M13 D_SaveS3M12: Push Offset D_SaveS3M13 Push SI Push DI Mov SI, Offset ChannelVolumeErrorMsg Mov DI, (4+24*80)*2 Jmp D_SaveS3MFormatError D_SaveS3M13: Test Byte Ptr [DS:2Ch], 8 JZ D_SaveS3M15 Push Offset D_SaveS3M15 Push SI Push DI Mov SI, Offset LinearSlideMsg Mov DI, (4+25*80)*2 Jmp D_SaveS3MFormatError D_SaveS3M15: Push DS Push CS Pop DS Mov DI, (4+17*80)*2 Mov SI, Offset SampleHeaderMsg Mov AH, 5 Call S_DrawString Pop DS Assume DS:Nothing Push BP ; BP = length of header. Xor AX, AX ; AX = sample number. Xor DX, DX ; DX:BP = file position. ; BX = file handle ;-------------------------------------- D_SaveS3M14: Push AX Add BP, 15 ; Align on next 16-byte boundary. AdC DX, 0 ; Unnecessary.. but who cares. ; Now to store pointer. And BP, Not 15 Push DX Mov DI, AX Add DI, DI Push DI Add DI, 60h Add DI, [ES:20h] ; Move file pointer. Mov AX, 4200h Mov CX, DX Mov DX, BP Int 21h SHRD AX, DX, 4 Mov [ES:DI], AX ; Set up sample block at ES:1024. Pop DI Push BX Mov BX, [DS:64912+DI] ; DS:BX points to sample header. Mov DI, 1024 Mov AL, [BX+12h] Mov DL, AL And AL, 1 StosB Mov SI, BX Add SI, 4 Mov CX, 12 Rep MovsB ; filename Xor AX, AX StosB StosW Mov SI, BX Add SI, 30h Mov CX, 6 Rep MovsW ; Length/Loopbeg/Loopend. Mov AL, [DS:BX+13h] StosW ; Default sample volume. Mov AH, DL Mov CL, DL ShR AH, 4 And AX, 100h ShL CL, 1 And CL, 4 Or AH, CL StosW ; Loop, 16 Bit & no 'pack' MovsW MovsW Mov CX, 6 Xor AX, AX Rep StosW ; Now for sample name. Mov SI, BX Add SI, 14h Mov CX, 25 D_SaveS3M56: LodsB And AL, AL JNZ D_SaveS3M57 Mov AL, 32 D_SaveS3M57: StosB Loop D_SaveS3M56 Xor AX, AX StosB StosW Mov EAX, 'SRCS' StosD ; OK header is done... Test DL, 16+32 JZ D_SaveS3M16 ; No loop on. Test DL, 32 JNZ D_SaveS3M51 Test DL, 64 JZ D_SaveS3M16 D_SaveS3M51: Push Offset D_SaveS3M16 Push SI Push DI Mov SI, Offset LoopMsg Mov DI, (4+27*80)*2 Jmp D_SaveS3MFormatError D_SaveS3M16: Cmp Byte Ptr [DS:BX+11h], 64 JE D_SaveS3M17 Push Offset D_SaveS3M17 Push SI Push DI Mov SI, Offset SampleVolumeMsg Mov DI, (4+26*80)*2 Jmp D_SaveS3MFormatError D_SaveS3M17: Cmp Byte Ptr [DS:BX+4Dh], 0 JE D_SaveS3M18 Push Offset D_SaveS3M18 Push SI Push DI Mov SI, Offset SampleVibratoMsg Mov DI, (4+28*80)*2 Jmp D_SaveS3MFormatError D_SaveS3M18: ; Write block. Pop BX Push DS Push ES Pop DS Mov DX, 1024 Mov CX, 50h Call D_SaveBlock Pop DS Pop DX Add BP, 50h ; Advance file pointer. AdC DX, 0 Pop AX Inc AX Cmp AX, [ES:22h] JB D_SaveS3M14 ; Sample headers done. ;----------------------------------- ; Pattern data. Xor AX, AX ; Start with pattern 0 D_SaveS3M19: Push AX ; Shove message on screen.... Add BP, 15 ; Align on next 16-byte boundary. AdC DX, 0 ; Unnecessary.. but who cares. ; Now to store pointer. And BP, Not 15 Push DX Push AX ; AX for pattern msg... Mov DI, AX Add DI, DI Add DI, 60h Add DI, [ES:20h] Mov CX, [ES:22h] Add CX, CX Add DI, CX ; Move file pointer. Mov AX, 4200h Mov CX, DX Mov DX, BP Int 21h SHRD AX, DX, 4 ; DX:AX = new file pointer location Mov [ES:DI], AX Push CS Pop DS Mov DI, (4+18*80)*2 Mov SI, Offset PatternMsg Mov AH, 5 Call S_DrawString Pop AX ; AX = pattern. Call Music_GetPattern ; DS:SI points to pattern. Mov CX, [SI+2] ; CX = length. Cmp CX, 64 JE D_SaveS3M20 Push Offset D_SaveS3M20 Push SI Push DI Mov SI, Offset PatternLengthMsg Mov DI, (4+30*80)*2 Jmp D_SaveS3MFormatError D_SaveS3M20: Push BX Push CX Mov DI, 20000 Mov CX, 64 D_SaveS3M25: Mov AX, 0FD00h ; Mask & note. StosW Mov AH, 0FFh ; instrument & volume. StosW Xor AH, AH StosW StosW Loop D_SaveS3M25 Mov DI, 30002 Add SI, 8 Pop CX Push CX D_SaveS3M22: ; Pattern translation time. Push CX D_SaveS3M33: LodsB And AL, AL JZ D_SaveS3M23 Mov DL, AL And AX, 7Fh Dec AX Mov CL, 3 ShL AX, CL Mov BX, AX Add BX, 20000 ; ES:BX points to old information. ; Decode row into area. Mov DH, [ES:BX] Test DL, 80h JZ D_SaveS3M24 LodsB ; Mask Mov [ES:BX], AL Mov DH, AL D_SaveS3M24: Test DH, 1 JZ D_SaveS3M26 LodsB Mov [ES:BX+1], AL D_SaveS3M26: Test DH, 2 JZ D_SaveS3M27 LodsB Mov [ES:BX+2], AL D_SaveS3M27: Test DH, 4 JZ D_SaveS3M28 LodsB Cmp AL, 64 JA D_SaveS3MPanError D_SaveS3M28_2: Mov [ES:BX+3], AL ; Volume D_SaveS3M28: Test DH, 8 JZ D_SaveS3M29 LodsW ; Effect+value. Mov [ES:BX+4], AX D_SaveS3M29: And DL, 7Fh Cmp DL, NUMS3MCHANNELS JA D_SaveS3M30 Dec DX Test DH, 33h JZ D_SaveS3M31 Or DL, 32 D_SaveS3M31: Test DH, 44h JZ D_SaveS3M32 Or DL, 64 ; Volume D_SaveS3M32: Test DH, 88h JZ D_SaveS3M34 Or DL, 128 ; Effect. D_SaveS3M34: ; Check if note in range. Mov AX, [ES:BX+1] Mov [ES:BX+6], AX ; BX+6=note, BX+7=ins. Cmp AL, 120 JAE D_SaveS3M55 Test DH, 11h JZ D_SaveS3M55 Test DH, 22h JZ D_SaveS3M55 Push DS Call Music_GetSongSegment Mov DS, AX Test Byte Ptr [DS:2Ch], 4 JZ D_SaveS3M54 Push BX Push DI Mov DI, BX Mov BL, [ES:BX+7] And BX, 0FFh ; BX = ins. JZ D_SaveS3M52 Add BX, BX Mov BX, [BX+64712-2] ; BX points to instrument. Mov AL, [ES:DI+1] And AX, 0FFh Add AX, AX Add BX, AX Mov AX, [BX+40h] Mov [ES:DI+6], AX D_SaveS3M52: Pop DI Pop BX D_SaveS3M54: Pop DS D_SaveS3M55: Mov AL, DL Test DL, 32 ; Do note? JZ D_SaveS3M35 Mov AH, [ES:BX+6] ; AH = note. Cmp AH, 0FDh JAE D_SaveS3M35 Cmp AH, 12 JB D_SaveS3M36 ; Note out of range. Cmp AH, 108 JAE D_SaveS3M36 D_SaveS3M35: StosB ; Store mask. Test DL, 32 JZ D_SaveS3M39 Mov AL, 0FFh Test DH, 11h JZ D_SaveS3M37 Cmp AH, 0FDh JE D_SaveS3M37 Mov AL, 0FEh Cmp AH, 0FEh JAE D_SaveS3M37 Mov AL, AH Xor AH, AH Sub AL, 12 Mov CX, 12*256+4 Div CH ; AL = octave, AH = note. ShL AL, CL Or AL, AH D_SaveS3M37: Mov AH, 0 Test DH, 22h JZ D_SaveS3M50 Mov AH, [ES:BX+7] D_SaveS3M50: StosW D_SaveS3M39: Test DL, 64 JZ D_SaveS3M40 Mov AL, [ES:BX+3] StosB D_SaveS3M40: Test DL, 128 JZ D_SaveS3M41 Mov AX, [ES:BX+4] ; Cmp AL, 'H'-'@' ; JE D_SaveVibDepth1 ; Cmp AL, 'U'-'@' ; JE D_SaveVibDepth2 ; Cmp AX, 'S'-'@'+9100h JE D_SaveS3MSurround Cmp AL, 'V'-'@' JE D_SaveS3M46 Cmp AL, 'X'-'@' JE D_SaveS3M46 Cmp AL, 'C'-'@' JNE D_SaveS3M47 Mov AL, AH Xor AH, AH Mov CX, 10*256+4 Div CH ShL AL, CL Or AH, AL Mov AL, 'C'-'@' Jmp D_SaveS3M47 D_SaveS3MSurround: Mov AX, 'X'-'@'+0A400h Jmp D_SaveS3M47 D_SaveS3M46: ShR AH, 1 D_SaveS3M47: StosW D_SaveS3M41: Jmp D_SaveS3M33 ; D_SaveVibDepth1: ; Command H ; Mov CL, AH ; And AH, 0Fh ; And CL, 0F0h ; Inc AH ; ShR AH, 1 ; Or AH, CL ; ; StosW ; Jmp D_SaveS3M33 ; ;D_SaveVibDepth2: ; Mov CL, AH ; And AH, 0Fh ; AH = depth ; Inc AH ; ShR AH, 1 ; And CL, 0F0h ; Or AH, CL ; ; StosW ; Jmp D_SaveS3M33 D_SaveS3MPanError: Mov AL, 0FFh Mov Byte Ptr [ES:BX+3], AL ; Volume Push Offset D_SaveS3M28_2 Push SI Push DI Mov SI, Offset PanningErrorMsg Mov DI, (4+33*80)*2 Jmp D_SaveS3MFormatError D_SaveS3M30: Push Offset D_SaveS3M33 Push SI Push DI Mov SI, Offset ChannelErrorMsg Mov DI, (4+31*80)*2 Jmp D_SaveS3MFormatError D_SaveS3M36: Push Offset D_SaveS3M33 Push SI Push DI Mov SI, Offset NoteRangeMsg Mov DI, (4+32*80)*2 Jmp D_SaveS3MFormatError D_SaveS3M23: StosB Pop CX Loop D_SaveS3M22 Pop CX Pop BX Sub CX, 64 JNC D_SaveS3M21 Neg CX Xor AL, AL Rep StosB D_SaveS3M21: Mov CX, DI Sub CX, 30000 Mov [ES:30000], CX ; Pattern length. Push ES Pop DS Mov DX, 30000 Call D_SaveBlock Pop DX Add BP, CX AdC DX, 0 Pop AX Inc AX Cmp AX, [ES:24h] JB D_SaveS3M19 ;----------------------------------- ; Now to save samples. Mov DI, 10000 Mov CX, 200 ; ES:10000 contains sample pointers. Xor AX, AX Rep StosW D_SaveS3M42: Inc AX Push AX Xor CX, CX Call Music_GetSampleLocation ; Gets DS:SI, ECX JC D_SaveS3M43 JZ D_SaveS3M8Bit Add ECX, ECX D_SaveS3M8Bit: Push DS Push AX Push CS Pop DS Mov DI, (4+19*80)*2 Mov SI, Offset SampleMsg Mov AH, 5 Call S_DrawString Pop AX Pop DS ; Shove message on screen.... Add BP, 15 ; Align on next 16-byte boundary. AdC DX, 0 And BP, Not 15 Push ECX Push DX Push AX ; AX = sample num Mov DI, AX Dec DI Add DI, DI Add DI, DI Add DI, 10000 Mov AX, BP StosW Mov AX, DX StosW Mov AX, 4200h Mov CX, DX Mov DX, BP Int 21h ; Set file offset. Pop AX Call D_SaveSampleDataConvert Pop DX Pop ECX Add BP, CX PushF ShR ECX, 16 PopF AdC DX, CX D_SaveS3M43: Pop AX Cmp AX, [ES:22h] JB D_SaveS3M42 ;----------------------------------- Push CS Pop DS Assume DS:Disk Mov DI, (4+20*80)*2 Mov SI, Offset HeaderMsg Mov AH, 5 Call S_DrawString Mov AX, 4200h Xor CX, CX Xor DX, DX Int 21h ; Go back to start of file. Push ES Pop DS Xor DX, DX Pop CX ; CX = length of header. (previously BP) Call D_SaveBlock ; To do sample pointers now. Mov SI, 10000 Xor BP, BP D_SaveS3M44: Mov DI, BP Add DI, DI Add DI, 60h ; Length of header Add DI, [DS:20h] ; Past Orders, DS:SI points to parasample Xor CX, CX Mov DX, [DI] SHLD CX, DX, 4 ShL DX, 4 Add DX, 0Dh Mov AX, 4200h Int 21h ; file re-position. LodsW Mov DX, AX LodsW ; AX:DX contains sample pointer. ShRD DX, AX, 4 ShR AX, 4 ; AX:DX contains para pointer. Mov [DS:0], AL Mov [DS:1], DX Mov CX, 3 Xor DX, DX Call D_SaveBlock Inc BP Cmp BP, [DS:22h] JB D_SaveS3M44 Mov AH, 3Eh ; Close file. Int 21h Push CS Pop DS Assume DS:Disk Mov DI, (4+21*80)*2 Mov SI, Offset CompleteMsg Mov AH, 5 Call S_DrawString Cmp SaveFormatError, 0 JE D_SaveS3M_NoKeyWait Call K_ClearKeyboardQueue D_SaveS3MKeyWait: Call K_GetKey Test CH, 1 JZ D_SaveS3MKeyWait D_SaveS3M_NoKeyWait: Jmp EndSaveModule D_SaveS3MFormatError: Push AX Push DS Push CS Pop DS Assume DS:Disk Mov SaveFormatError, 1 Mov AH, 4 Call S_DrawString Pop DS Pop AX Pop DI Pop SI RetN EndP D_SaveS3M Assume DS:Nothing ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc D_SaveFileITModule Far Mov SI, 1 Mov CX, Object1 Mov DX, Offset O1_SaveITList Mov AX, 5 Ret EndP D_SaveFileITModule ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Proc D_SaveFileS3MModule Far Mov SI, 1 Mov CX, Object1 Mov DX, Offset O1_SaveS3MList Mov AX, 5 Ret EndP D_SaveFileS3MModule ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ