home *** CD-ROM | disk | FTP | other *** search
- UNIT Loader669;
-
- INTERFACE
-
- USES Objects, SongUnit;
-
-
-
-
- PROCEDURE Load669FileFormat (VAR Song: TSong; VAR St: TStream; VAR Header: TSongHeader);
-
-
-
-
- IMPLEMENTATION
-
- USES SongElements, SongUtils, Heaps, AsciiZ;
-
-
-
-
- {----------------------------------------------------------------------------}
- { Internal definitions. Format of the files. }
- {____________________________________________________________________________}
-
- TYPE
- T669FileMagic = WORD;
-
- CONST
- Magic669 = $6669;
-
- TYPE
-
- TSizes = ARRAY[1..128] OF BYTE;
-
- T669Header =
- RECORD
- Magic : T669FileMagic;
- Comment : ARRAY[1..3, 1..36] OF CHAR;
- NInstruments: BYTE;
- NPatterns : BYTE;
- RepStart : BYTE;
- Sequence : ARRAY[1..128] OF BYTE;
- Tempos : ARRAY[1..128] OF BYTE;
- Lengths : TSizes;
- END;
-
- T669Instrument =
- RECORD
- Name : ARRAY[1..13] OF CHAR;
- Size : LONGINT;
- RepStart : LONGINT;
- RepLen : LONGINT;
- END;
-
- T669Pattern = ARRAY[1..64, 1..8] OF
- RECORD
- CASE BYTE OF
- 0 : ( w1 : WORD;
- b : BYTE );
- 1 : ( b1,
- b2,
- b3 : BYTE );
- END;
-
-
-
-
- PROCEDURE ProcessPatterns(VAR Song: TSong; VAR St: TStream; VAR Sizes: TSizes; Num: WORD);
- VAR
- Patt : T669Pattern;
- FullTrack : TFullTrack;
- Pattern : PPattern;
- Track : PTrack;
- Note : TFullNote;
- c : BYTE;
- i, j : WORD;
- n, t : WORD;
- Row : WORD;
- Size : WORD;
- NAdj : WORD;
- l : LONGINT;
- BEGIN
- t := 1;
- FOR n := 1 TO Num DO
- BEGIN
- Pattern := Song.GetPattern(n);
- IF Pattern = NIL THEN
- BEGIN
- Song.Status := msOutOfMemory;
- EXIT;
- END;
-
- WITH Pattern^.Patt^ DO
- BEGIN
- NNotes := Sizes[n] + 1;
- NChans := Song.NumChannels;
- Tempo := 0;
- BPM := 0;
- END;
-
- St.Read(Patt, SizeOf(Patt));
-
- IF St.Status <> stOk THEN
- BEGIN
- Song.Status := msFileTooShort;
- EXIT;
- END;
-
- FOR j := 1 TO Song.NumChannels DO
- BEGIN
- FillChar(FullTrack, SizeOf(FullTrack), 0);
-
- FOR i := 1 TO 64 DO
- WITH FullTrack[i-1], Patt[i][j] DO
- BEGIN
- IF b1 < $FE THEN
- BEGIN
- Period := PeriodArray[b1 SHR 2];
- Instrument := ((SWAP(w1) SHR 4) AND 63) + 1;
- END;
-
- IF b1 < $FF THEN
- Volume := ((b2 AND 15) SHL 2) + ((b2 AND 15) SHR 2) + 1;
-
- Parameter := b3 AND 15;
- Command := mcNone;
-
- IF Parameter <> 0 THEN
- CASE b3 SHR 4 OF
- 0 : Command := mcTPortUp;
- 1 : Command := mcTPortDown;
- 2 : Command := mcNPortamento;
- 3 : INC(Period);
- 4 : BEGIN
- Command := mcVibrato;
- Parameter := (Parameter SHL 4) + 1
- END;
- 5 : Command := mcSetTempo;
- END;
- END;
-
- Track := Song.GetTrack(t);
- IF Track = NIL THEN
- BEGIN
- Song.Status := msOutOfMemory;
- EXIT;
- END;
-
- Track^.SetFullTrack(FullTrack);
-
- Pattern^.Patt^.Channels[j] := t;
-
- INC(t);
- END;
-
- END;
- END;
-
-
- PROCEDURE ProcessInstruments(VAR Song: TSong; VAR St: TStream; Num: WORD);
- VAR
- Instrument : TInstrumentRec;
- Instr : PInstrument;
- Instr669 : T669Instrument;
- i, w : WORD;
- Signo : LONGINT;
- NoSigno : LONGINT;
- BEGIN
- FOR i := 1 TO Num DO
- WITH Instrument DO
- BEGIN
- FillChar(Instrument, SizeOf(Instrument), 0);
-
- Instr := Song.GetInstrument(i);
- IF Instr = NIL THEN
- BEGIN
- Song.Status := msOutOfMemory;
- EXIT;
- END;
-
- St.Read(Instr669, SizeOf(Instr669));
-
- Instr^.SetName(StrASCIIZ(Instr669.Name, 13));
-
- Len := Instr669.Size;
-
- IF Len > 0 THEN
- BEGIN
-
- IF Instr669.RepLen <= Len THEN
- BEGIN
- Reps := Instr669.RepStart;
- Repl := Instr669.RepLen;
- END
- ELSE
- BEGIN
- Reps := 0;
- Repl := 0;
- END;
-
- Vol := 64;
-
- IF Repl > Len THEN Repl := Len;
- IF Reps + Repl > Len THEN Repl := Len - Reps;
-
-
- Instr^.Change(@Instrument);
- END
- ELSE
- Instr^.Change(NIL);
- END;
- END;
-
-
-
- PROCEDURE ProcessSamples(VAR Song: TSong; VAR St: TStream; Num: WORD);
- VAR
- Instr : PInstrument;
- i, w : WORD;
- BEGIN
- FOR i := 1 TO Num DO
- BEGIN
- Instr := Song.GetInstrument(i);
-
- IF (Instr^.Instr <> NIL) AND
- (Instr^.Instr^.Len > 0) THEN
- WITH Instr^.Instr^ DO
- BEGIN
- IF Len <= MaxSample THEN
- BEGIN
- FullHeap.HGetMem(POINTER(Data), Len);
- IF Data = NIL THEN BEGIN
- Song.Status := msOutOfMemory;
- EXIT;
- END;
-
- St.Read(Data^, Len);
-
- IF St.Status <> stOk THEN BEGIN
- Song.Status := msFileDamaged;
- EXIT;
- END;
-
- FOR w := 0 TO Len - 1 DO
- INC(Data^[w], 128);
-
- END
- ELSE
- BEGIN
- FullHeap.HGetMem(POINTER(Data), MaxSample);
- FullHeap.HGetMem(POINTER(Xtra), Len-MaxSample);
-
- IF (Data = NIL) OR (Xtra = NIL) THEN BEGIN
- Song.Status := msOutOfMemory;
- EXIT;
- END;
-
- St.Read(Data^, MaxSample);
- St.Read(Xtra^, Len-MaxSample);
-
- IF St.Status <> 0 THEN BEGIN
- Song.Status := msFileDamaged;
- EXIT;
- END;
- END;
- END;
- END;
- END;
-
- PROCEDURE Load669FileFormat(VAR Song: TSong; VAR St: TStream; VAR Header: TSongHeader);
- VAR
- Hdr : T669Header ABSOLUTE Header;
- InitialPos : LONGINT;
- i : WORD;
- BEGIN
- Song.FileFormat := mffComposer669;
-
- InitialPos := St.GetPos;
-
- St.Seek(InitialPos + SizeOf(T669Header));
-
- IF Hdr.Magic <> Magic669 THEN
- BEGIN
- Song.Status := msNotLoaded;
- EXIT;
- END;
-
- Song.Status := msOK;
-
- Song.Name := FullHeap.HNewStr(Song.FileName);
-
- Song.InitialTempo := 4;
- Song.InitialBPM := 80;
- Song.Volume := 255;
- Song.NumChannels := 8;
-
- Song.SequenceLength := 0;
- FOR i := 1 TO 128 DO
- IF Hdr.Sequence[i] < 128 THEN
- Song.SequenceLength := i;
-
- Song.SequenceRepStart := Hdr.RepStart + 1;
- Move(Hdr.Sequence, Song.PatternSequence^, Song.SequenceLength);
- Move(Hdr.Tempos, Song.PatternTempos^, 128);
-
- FOR i := 1 TO Song.SequenceLength DO
- INC(Song.PatternSequence^[i]);
-
-
- { Processing of the instruments }
-
- ProcessInstruments(Song, St, Hdr.NInstruments);
- IF Song.Status > msOk THEN EXIT;
-
-
- { Processing of the patterns (the partiture) }
-
- ProcessPatterns(Song, St, Hdr.Lengths, Hdr.NPatterns);
- IF Song.Status > msOk THEN EXIT;
-
-
- { Processing of the samples }
-
- ProcessSamples(Song, St, Hdr.NInstruments);
- IF Song.Status > msFileTooShort THEN EXIT;
- END;
-
-
-
-
- END.
-