Commit 5d7b892

Nick Faro committed on
WIP correct instrument import
commit 5d7b89204ed830bd00769740a1416ace8f04b922 parent a2d4c98
3 changed files +60−14
Modifieddmfimport.pas +6−6
@@ -43,13 +43,13 @@ begin
43 Temp := DS.ReadByte; 43 Temp := DS.ReadByte;
44 Writeln(temp); 44 Writeln(temp);
45 if Temp <> 24 then 45 if Temp <> 24 then
46 raise EDMFException.Create('DMF file was invalid version!'); 46 raise EDMFException.Create('This DMF file has an unsupported version.');
47 47
48 //SYSTEM SET 48 //SYSTEM SET
49 //1 Byte: System: 49 //1 Byte: System:
50 //SYSTEM_GAMEBOY 0x04 (SYSTEM_TOTAL_CHANNELS 4) 50 //SYSTEM_GAMEBOY 0x04 (SYSTEM_TOTAL_CHANNELS 4)
51 if DS.ReadByte <> $04 then 51 if DS.ReadByte <> $04 then
52 raise EDMFException.Create('DMF file is not a Game Boy module!'); 52 raise EDMFException.Create('This DMF file is not a Game Boy module.');
53 53
54 //VISUAL INFORMATION 54 //VISUAL INFORMATION
55 // 1 Byte: Song Name Chars Count (0-255) 55 // 1 Byte: Song Name Chars Count (0-255)
@@ -83,7 +83,7 @@ begin
83 Temp := DS.ReadDWord; 83 Temp := DS.ReadDWord;
84 Writeln(temp); 84 Writeln(temp);
85 if Temp <> 64 then 85 if Temp <> 64 then
86 raise EDMFException.Create('DMF file needs 64 rows per pattern!'); 86 raise EDMFException.Create('This DMF file has '+IntToStr(Temp)+' rows per pattern, but hUGETracker needs exactly 64.');
87 //1 Byte: TOTAL_ROWS_IN_PATTERN_MATRIX 87 //1 Byte: TOTAL_ROWS_IN_PATTERN_MATRIX
88 Temp := DS.ReadByte; 88 Temp := DS.ReadByte;
89 writeln('rows in pattern matrix ', temp); 89 writeln('rows in pattern matrix ', temp);
@@ -98,7 +98,7 @@ begin
98 //1 Byte: TOTAL_INSTRUMENTS 98 //1 Byte: TOTAL_INSTRUMENTS
99 TotalInstruments := DS.ReadByte; 99 TotalInstruments := DS.ReadByte;
100 if TotalInstruments > 15 then 100 if TotalInstruments > 15 then
101 raise EDMFException.Create('DMF file must have 15 instruments or less!'); 101 raise EDMFException.Create('DMF files must have 15 instruments or less.');
102 102
103 // Read all instruments 103 // Read all instruments
104 writeln('total instruments ', totalinstruments); 104 writeln('total instruments ', totalinstruments);
@@ -115,7 +115,7 @@ begin
115 115
116 // 1 Byte: Instrument Mode (0 = STANDARD INS, 1 = FM INS) 116 // 1 Byte: Instrument Mode (0 = STANDARD INS, 1 = FM INS)
117 if DS.ReadByte <> 0 then 117 if DS.ReadByte <> 0 then
118 raise EDMFException.Create('DMF file contains a non-standard instrument!'); 118 raise EDMFException.Create('This DMF file contains an FM-type instrument, which is unsupported.');
119 119
120 //ARPEGGIO MACRO 120 //ARPEGGIO MACRO
121 //1 Byte: ENVELOPE_SIZE (0 - 127) 121 //1 Byte: ENVELOPE_SIZE (0 - 127)
@@ -191,7 +191,7 @@ begin
191 Temp := DS.readbyte; 191 Temp := DS.readbyte;
192 writeln('fx columns ', temp); 192 writeln('fx columns ', temp);
193 if Temp <> 1 then 193 if Temp <> 1 then
194 raise EDMFException.Create('DMF file contains patterns with more than one effect column!'); 194 raise EDMFException.Create('This DMF file contains patterns with more than one effect column, which is unsupported.');
195 195
196 writeln('iterating '+inttostr(High(Result.OrderMatrix[I]) - Low(Result.OrderMatrix[I]) + 1), ' times'); 196 writeln('iterating '+inttostr(High(Result.OrderMatrix[I]) - Low(Result.OrderMatrix[I]) + 1), ' times');
197 for J := Low(Result.OrderMatrix[I]) to High(Result.OrderMatrix[I]) do begin 197 for J := Low(Result.OrderMatrix[I]) to High(Result.OrderMatrix[I]) do begin
ModifiedhUGEDriver +1−1
@@ -1 +1 @@
1 Subproject commit 224f830fcbb1b57d820d6228af68affedc305a88 1 Subproject commit 5e3b03dde8ab7c144bcdc92331dfa7537db138c8
Modifiedtbmimport.pas +53−7
@@ -5,13 +5,15 @@ unit TBMImport;
5 interface 5 interface
6 6
7 uses 7 uses
8 Classes, SysUtils, song, LazUTF8, HugeDatatypes, Constants, Utils; 8 Classes, SysUtils, song, LazUTF8, HugeDatatypes, Constants, Utils, fgl;
9 9
10 function LoadSongFromTbmStream(Stream: TStream): TSong; 10 function LoadSongFromTbmStream(Stream: TStream): TSong;
11 11
12 implementation 12 implementation
13 13
14 type 14 type
15 ETBMException = class(Exception);
16
15 TTBMHeader = packed record 17 TTBMHeader = packed record
16 Signature: array[0..11] of Char; // ' TRACKERBOY ' 18 Signature: array[0..11] of Char; // ' TRACKERBOY '
17 VersionMajor: DWord; 19 VersionMajor: DWord;
@@ -86,6 +88,8 @@ type
86 function ReadLString: String; 88 function ReadLString: String;
87 end; 89 end;
88 90
91 TTBMInstrumentMap = specialize TFPGMap<Integer, Integer>;
92
89 //https://github.com/stoneface86/libtrackerboy/blob/bf4993d53bc34691ca75819a96d3d00b3b699dea/src/trackerboy/data.nim#L111 93 //https://github.com/stoneface86/libtrackerboy/blob/bf4993d53bc34691ca75819a96d3d00b3b699dea/src/trackerboy/data.nim#L111
90 TTBMEffectType = ( 94 TTBMEffectType = (
91 etNoEffect = 0, // No effect, this effect column is unset. 95 etNoEffect = 0, // No effect, this effect column is unset.
@@ -272,12 +276,15 @@ begin
272 end; 276 end;
273 end; 277 end;
274 278
275 procedure CleanupPattern(Pat: PPattern); 279 procedure CleanupPattern(Pat: PPattern; InstMap: TTBMInstrumentMap);
276 var 280 var
277 I: Integer; 281 I: Integer;
278 CurNote: Integer = NO_NOTE; 282 CurNote: Integer = NO_NOTE;
279 begin 283 begin
280 for I := Low(TPattern) to High(TPattern) do begin 284 for I := Low(TPattern) to High(TPattern) do begin
285 if not InstMap.TryGetData(Pat^[I].Instrument, Pat^[I].Instrument) then
286 Pat^[I].Instrument := 0;
287
281 if Pat^[I].Note <> NO_NOTE then 288 if Pat^[I].Note <> NO_NOTE then
282 CurNote := Pat^[I].Note; 289 CurNote := Pat^[I].Note;
283 290
@@ -311,11 +318,18 @@ var
311 WaveId: Byte; 318 WaveId: Byte;
312 WaveName: String; 319 WaveName: String;
313 FourBitWave: T4bitWave; 320 FourBitWave: T4bitWave;
321
322 SquareMap, WaveMap, NoiseMap: TTBMInstrumentMap;
323 SeenSquare, SeenWave, SeenNoise: Integer;
324 NewInstId: Integer;
314 begin 325 begin
315 InitializeSong(Result); 326 InitializeSong(Result);
316 327
317 Stream.ReadBuffer(Header, SizeOf(TTBMHeader)); 328 Stream.ReadBuffer(Header, SizeOf(TTBMHeader));
318 329
330 if Header.SCount > 1 then
331 raise ETBMException.Create('hUGETracker only supports loading TBM modules with one song.');
332
319 // COMM block 333 // COMM block
320 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader)); 334 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader));
321 Stream.Seek(BlockHeader.Length, soCurrent); // Skip the comment for now 335 Stream.Seek(BlockHeader.Length, soCurrent); // Skip the comment for now
@@ -352,10 +366,17 @@ begin
352 Stream.ReadBuffer(RowFormat, SizeOf(TTBMRowFormat)); 366 Stream.ReadBuffer(RowFormat, SizeOf(TTBMRowFormat));
353 Pat^[RowFormat.RowNo] := ConverTBMRow(RowFormat.RowData, InsType); 367 Pat^[RowFormat.RowNo] := ConverTBMRow(RowFormat.RowData, InsType);
354 end; 368 end;
355 CleanupPattern(Pat);
356 end; 369 end;
357 370
358 // INST block 371 // INST block
372
373 SquareMap := TTBMInstrumentMap.Create;
374 WaveMap := TTBMInstrumentMap.Create;
375 NoiseMap := TTBMInstrumentMap.Create;
376 SeenSquare := 1;
377 SeenWave := 1;
378 SeenNoise := 1;
379
359 for I := 0 to Header.ICount-1 do begin 380 for I := 0 to Header.ICount-1 do begin
360 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader)); 381 Stream.ReadBuffer(BlockHeader, SizeOf(TTBMBlockHeader));
361 382
@@ -363,13 +384,29 @@ begin
363 InstName := Stream.ReadLString; 384 InstName := Stream.ReadLString;
364 385
365 Stream.ReadBuffer(InstFormat, SizeOf(TTBMInstrumentFormat)); 386 Stream.ReadBuffer(InstFormat, SizeOf(TTBMInstrumentFormat));
387
366 case InstFormat.Channel of 388 case InstFormat.Channel of
367 0, 1: InsType := itSquare; 389 0, 1: begin
368 2: InsType := itWave; 390 InsType := itSquare;
369 3: InsType := itNoise; 391 SquareMap.Add(InstId, SeenSquare);
392 NewInstId := SeenSquare;
393 Inc(SeenSquare);
394 end;
395 2: begin
396 InsType := itWave;
397 WaveMap.Add(InstId, SeenWave);
398 NewInstId := SeenWave;
399 Inc(SeenWave);
400 end;
401 3: begin
402 InsType := itNoise;
403 NoiseMap.Add(InstId, SeenNoise);
404 NewInstId := SeenNoise;
405 Inc(SeenNoise);
406 end;
370 end; 407 end;
371 408
372 Ins := @Result.Instruments.All[UnmodInst(InsType, InstId+1)]; 409 Ins := @Result.Instruments.All[UnmodInst(InsType, NewInstId)];
373 Ins^.Name := InstName; 410 Ins^.Name := InstName;
374 411
375 EnvReg.ByteValue := InstFormat.Envelope; 412 EnvReg.ByteValue := InstFormat.Envelope;
@@ -426,6 +463,15 @@ begin
426 Result.Waves[WaveId] := UnconvertWaveform(FourBitWave); 463 Result.Waves[WaveId] := UnconvertWaveform(FourBitWave);
427 end; 464 end;
428 465
466 // Cleanup patterns
467 for I := Low(Result.OrderMatrix[0]) to High(Result.OrderMatrix[0])-1 do
468 CleanupPattern(Result.Patterns.KeyData[Result.OrderMatrix[0, I]], SquareMap);
469 for I := Low(Result.OrderMatrix[1]) to High(Result.OrderMatrix[1])-1 do
470 CleanupPattern(Result.Patterns.KeyData[Result.OrderMatrix[1, I]], SquareMap);
471 for I := Low(Result.OrderMatrix[2]) to High(Result.OrderMatrix[2])-1 do
472 CleanupPattern(Result.Patterns.KeyData[Result.OrderMatrix[2, I]], WaveMap);
473 for I := Low(Result.OrderMatrix[3]) to High(Result.OrderMatrix[3])-1 do
474 CleanupPattern(Result.Patterns.KeyData[Result.OrderMatrix[3, I]], NoiseMap);
429 end; 475 end;
430 476
431 end. 477 end.