Commit 738e4e5

Nick Faro committed on
Only emit used stuff in codegen
Co-authored-by: Adrian Siekierka <[email protected]>
commit 738e4e5d30185d5e49c491bfe6aad42013df8014 parent e4dc2b8
2 changed files +103−81
Modifiedsrc/codegen.pas +103−24
@@ -28,6 +28,82 @@ procedure RenderSongToRGBDSAsm(Song: TSong; DescriptorName: String; Filename: st
28 28
29 implementation 29 implementation
30 30
31 uses AvgLvlTree;
32
33 type
34 TUsedStuff = record
35 HighestDutyInst, HighestWaveInst, HighestNoiseInst: Integer;
36 HighestWaveform: Integer;
37 UsedPatterns: TAvgLvlTree;
38 end;
39
40 function CompareIntPointers(Data1, Data2: Pointer): integer;
41 begin
42 Result := Integer(Data1^) - Integer(Data2^);
43 end;
44
45 function FindUsedStuff(const Song: TSong): TUsedStuff;
46 var
47 I, J: Integer;
48 Pat: PPattern;
49 Cell: TCell;
50 Highest: ^Integer;
51 Waveform: Integer;
52 begin
53 Result.UsedPatterns := TAvgLvlTree.Create(@CompareIntPointers);
54 Result.HighestDutyInst := -1;
55 Result.HighestWaveInst := -1;
56 Result.HighestNoiseInst := -1;
57 Result.HighestWaveform := -1;
58
59 for I := Low(Song.OrderMatrix) to High(Song.OrderMatrix) do begin
60 case I of
61 0, 1: Highest := @Result.HighestDutyInst;
62 2: Highest := @Result.HighestWaveInst;
63 3: Highest := @Result.HighestNoiseInst;
64 end;
65
66 for J := Low(Song.OrderMatrix[I]) to High(Song.OrderMatrix[I])-1 do begin
67 if Result.UsedPatterns.Find(@Song.OrderMatrix[I, J]) <> nil then Continue;
68
69 Result.UsedPatterns.Add(@Song.OrderMatrix[I, J]);
70
71 Pat := Song.Patterns.KeyData[Song.OrderMatrix[I, J]];
72 for Cell in Pat^ do begin
73 if Cell.Instrument = 0 then Continue;
74
75 if Cell.Instrument > Highest^ then
76 Highest^ := Cell.Instrument;
77
78 if (I = 2) then begin // Wave channel
79 Waveform := Song.Instruments.Wave[Cell.Instrument].Waveform;
80 if Waveform > Result.HighestWaveform then
81 Result.HighestWaveform := Waveform;
82 end;
83 end;
84 end;
85 end;
86 end;
87
88 procedure FreeUsedStuff(const UsedStuff: TUsedStuff);
89 begin
90 UsedStuff.UsedPatterns.Free;
91 end;
92
93 function PatternIsUsed(Pattern: Integer; const UsedStuff: TUsedStuff): Boolean;
94 begin
95 Result := UsedStuff.UsedPatterns.Find(@Pattern) <> nil;
96 end;
97
98 function InstrumentIsUsed(Instrument: Integer; Type_: TInstrumentType; const UsedStuff: TUsedStuff): Boolean;
99 begin
100 case Type_ of
101 itSquare: Result := Instrument <= UsedStuff.HighestDutyInst;
102 itWave: Result := Instrument <= UsedStuff.HighestWaveInst;
103 itNoise: Result := Instrument <= UsedStuff.HighestNoiseInst;
104 end;
105 end;
106
31 procedure RenderSongToGBDKC(Song: TSong; DescriptorName: String; Filename: string; Bank: Integer = -1); 107 procedure RenderSongToGBDKC(Song: TSong; DescriptorName: String; Filename: string; Bank: Integer = -1);
32 function RenderGBDKCell(Cell: TCell): string; 108 function RenderGBDKCell(Cell: TCell): string;
33 var 109 var
@@ -197,12 +273,12 @@ var
197 OutSL: TStringList; 273 OutSL: TStringList;
198 OrderCnt: integer; 274 OrderCnt: integer;
199 I: integer; 275 I: integer;
200 MaxInstrIdx: integer;
201 F: Text; 276 F: Text;
202 TypePrefix: String; 277 TypePrefix: String;
278 UsedStuff: TUsedStuff;
203 begin 279 begin
204 Song := OptimizeSong(Song); 280 Song := OptimizeSong(Song);
205 MaxInstrIdx := MaxInstrumentIndex(Song); 281 UsedStuff := FindUsedStuff(Song);
206 282
207 OutSL := TStringList.Create; 283 OutSL := TStringList.Create;
208 284
@@ -223,13 +299,13 @@ begin
223 OutSL.Add(''); 299 OutSL.Add('');
224 300
225 for I := 0 to Song.Patterns.Count - 1 do 301 for I := 0 to Song.Patterns.Count - 1 do
226 if PatternIsUsed(Song.Patterns.Keys[I], Song) then 302 if PatternIsUsed(Song.Patterns.Keys[I], UsedStuff) then
227 OutSL.Add(RenderGBDKPattern('P' + IntToStr(Song.Patterns.Keys[I]), 303 OutSL.Add(RenderGBDKPattern('P' + IntToStr(Song.Patterns.Keys[I]),
228 Song.Patterns.Data[I]^)); 304 Song.Patterns.Data[I]^));
229 OutSL.Add(''); 305 OutSL.Add('');
230 306
231 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do 307 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do
232 if InstrumentIsUsed(I, Song) then 308 if InstrumentIsUsed(ModInst(I), Song.Instruments.All[I].Type_, UsedStuff) then
233 with Song.Instruments.All[I] do begin 309 with Song.Instruments.All[I] do begin
234 if SubpatternEnabled then begin 310 if SubpatternEnabled then begin
235 WriteStr(TypePrefix, Type_); 311 WriteStr(TypePrefix, Type_);
@@ -243,12 +319,12 @@ begin
243 OutSL.Add(RenderGBDKOrder(4, Song.OrderMatrix[3])); 319 OutSL.Add(RenderGBDKOrder(4, Song.OrderMatrix[3]));
244 OutSL.Add(''); 320 OutSL.Add('');
245 321
246 OutSL.Add(RenderGBDKInstrumentBank('duty_instruments', Song.Instruments.Duty, MaxInstrIdx)); 322 OutSL.Add(RenderGBDKInstrumentBank('duty_instruments', Song.Instruments.Duty, UsedStuff.HighestDutyInst));
247 OutSL.Add(RenderGBDKInstrumentBank('wave_instruments', Song.Instruments.Wave, MaxInstrIdx)); 323 OutSL.Add(RenderGBDKInstrumentBank('wave_instruments', Song.Instruments.Wave, UsedStuff.HighestWaveInst));
248 OutSL.Add(RenderGBDKInstrumentBank('noise_instruments', Song.Instruments.Noise, MaxInstrIdx)); 324 OutSL.Add(RenderGBDKInstrumentBank('noise_instruments', Song.Instruments.Noise, UsedStuff.HighestNoiseInst));
249 OutSL.Add(''); 325 OutSL.Add('');
250 326
251 OutSL.Add(RenderGBDKWaves(Song.Waves, MaxWaveIndex(Song))); 327 OutSL.Add(RenderGBDKWaves(Song.Waves, UsedStuff.HighestWaveform));
252 OutSL.Add(''); 328 OutSL.Add('');
253 329
254 if Bank <> -1 then 330 if Bank <> -1 then
@@ -265,6 +341,7 @@ begin
265 CloseFile(F); 341 CloseFile(F);
266 342
267 OutSL.Free; 343 OutSL.Free;
344 FreeUsedStuff(UsedStuff);
268 end; 345 end;
269 346
270 function RenderOrderTable(OrderMatrix: TOrderMatrix): string; 347 function RenderOrderTable(OrderMatrix: TOrderMatrix): string;
@@ -460,11 +537,11 @@ var
460 OutSL: TStringList; 537 OutSL: TStringList;
461 F: Text; 538 F: Text;
462 I: Integer; 539 I: Integer;
463 MaxInstrIdx: Integer;
464 TypePrefix: String; 540 TypePrefix: String;
541 UsedStuff: TUsedStuff;
465 begin 542 begin
466 Song := OptimizeSong(Song); 543 Song := OptimizeSong(Song);
467 MaxInstrIdx := MaxInstrumentIndex(Song); 544 UsedStuff := FindUsedStuff(Song);
468 545
469 OutSL := TStringList.Create; 546 OutSL := TStringList.Create;
470 547
@@ -488,12 +565,12 @@ begin
488 565
489 // Render patterns 566 // Render patterns
490 for I := 0 to Song.Patterns.Count - 1 do 567 for I := 0 to Song.Patterns.Count - 1 do
491 if PatternIsUsed(Song.Patterns.Keys[I], Song) then 568 if PatternIsUsed(Song.Patterns.Keys[I], UsedStuff) then
492 OutSL.Add(RenderPattern('P' + IntToStr(Song.Patterns.Keys[I]), Song.Patterns.Data[I]^)); 569 OutSL.Add(RenderPattern('P' + IntToStr(Song.Patterns.Keys[I]), Song.Patterns.Data[I]^));
493 570
494 // Render subpatterns 571 // Render subpatterns
495 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do 572 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do
496 if InstrumentIsUsed(I, Song) then 573 if InstrumentIsUsed(ModInst(I), Song.Instruments.All[I].Type_, UsedStuff) then
497 with Song.Instruments.All[I] do begin 574 with Song.Instruments.All[I] do begin
498 if SubpatternEnabled then begin 575 if SubpatternEnabled then begin
499 WriteStr(TypePrefix, Type_); 576 WriteStr(TypePrefix, Type_);
@@ -503,15 +580,15 @@ begin
503 580
504 // Render instruments 581 // Render instruments
505 OutSL.Add('duty_instruments:'); 582 OutSL.Add('duty_instruments:');
506 OutSL.Add(RenderInstruments(Song.Instruments.Duty, MaxInstrIdx)); 583 OutSL.Add(RenderInstruments(Song.Instruments.Duty, UsedStuff.HighestDutyInst));
507 OutSL.Add(''); 584 OutSL.Add('');
508 585
509 OutSL.Add('wave_instruments:'); 586 OutSL.Add('wave_instruments:');
510 OutSL.Add(RenderInstruments(Song.Instruments.Wave, MaxInstrIdx)); 587 OutSL.Add(RenderInstruments(Song.Instruments.Wave, UsedStuff.HighestWaveInst));
511 OutSL.Add(''); 588 OutSL.Add('');
512 589
513 OutSL.Add('noise_instruments:'); 590 OutSL.Add('noise_instruments:');
514 OutSL.Add(RenderInstruments(Song.Instruments.Noise, MaxInstrIdx)); 591 OutSL.Add(RenderInstruments(Song.Instruments.Noise, UsedStuff.HighestNoiseInst));
515 OutSL.Add(''); 592 OutSL.Add('');
516 593
517 // Render routines 594 // Render routines
@@ -526,7 +603,7 @@ begin
526 603
527 // Render waves 604 // Render waves
528 OutSL.Add('waves:'); 605 OutSL.Add('waves:');
529 OutSL.Add(RenderWaveforms(Song.Waves, MaxWaveIndex(Song))); 606 OutSL.Add(RenderWaveforms(Song.Waves, UsedStuff.HighestWaveform));
530 607
531 AssignFile(F, Filename); 608 AssignFile(F, Filename);
532 Rewrite(F); 609 Rewrite(F);
@@ -534,6 +611,7 @@ begin
534 CloseFile(F); 611 CloseFile(F);
535 612
536 OutSL.Free; 613 OutSL.Free;
614 FreeUsedStuff(UsedStuff);
537 end; 615 end;
538 616
539 procedure RectifyGBSFile(GBSFile: string); 617 procedure RectifyGBSFile(GBSFile: string);
@@ -560,11 +638,11 @@ procedure AssembleSong(Song: TSong; Filename: string; Mode: TExportMode);
560 var 638 var
561 OutFile: Text; 639 OutFile: Text;
562 I: integer; 640 I: integer;
563 MaxInstrIdx: integer;
564 TypePrefix: String; 641 TypePrefix: String;
565 Proc: TProcess; 642 Proc: TProcess;
566 FilePath: string; 643 FilePath: string;
567 RenameSucceeded: Boolean; 644 RenameSucceeded: Boolean;
645 UsedStuff: TUsedStuff;
568 646
569 procedure Die; 647 procedure Die;
570 var 648 var
@@ -638,7 +716,7 @@ var
638 end; 716 end;
639 begin 717 begin
640 Song := OptimizeSong(Song); 718 Song := OptimizeSong(Song);
641 MaxInstrIdx := MaxInstrumentIndex(Song); 719 UsedStuff := FindUsedStuff(Song);
642 720
643 if not DirectoryExists(ConcatPaths([CacheDir, 'render'])) then 721 if not DirectoryExists(ConcatPaths([CacheDir, 'render'])) then
644 CreateDir(ConcatPaths([CacheDir, 'render'])); 722 CreateDir(ConcatPaths([CacheDir, 'render']));
@@ -646,11 +724,11 @@ begin
646 FilePath := Filename; 724 FilePath := Filename;
647 Filename := ConcatPaths([CacheDir, 'render', ExtractFileNameWithoutExt(ExtractFileNameOnly(Filename))]); 725 Filename := ConcatPaths([CacheDir, 'render', ExtractFileNameWithoutExt(ExtractFileNameOnly(Filename))]);
648 726
649 WriteHTT(ConcatPaths([CacheDir, 'render', 'wave.htt']), RenderWaveforms(Song.Waves, MaxWaveIndex(Song))); 727 WriteHTT(ConcatPaths([CacheDir, 'render', 'wave.htt']), RenderWaveforms(Song.Waves, UsedStuff.HighestWaveform));
650 WriteHTT(ConcatPaths([CacheDir, 'render', 'order.htt']), RenderOrderTable(Song.OrderMatrix)); 728 WriteHTT(ConcatPaths([CacheDir, 'render', 'order.htt']), RenderOrderTable(Song.OrderMatrix));
651 WriteHTT(ConcatPaths([CacheDir, 'render', 'duty_instrument.htt']), RenderInstruments(Song.Instruments.Duty, MaxInstrIdx)); 729 WriteHTT(ConcatPaths([CacheDir, 'render', 'duty_instrument.htt']), RenderInstruments(Song.Instruments.Duty, UsedStuff.HighestDutyInst));
652 WriteHTT(ConcatPaths([CacheDir, 'render', 'wave_instrument.htt']), RenderInstruments(Song.Instruments.Wave, MaxInstrIdx)); 730 WriteHTT(ConcatPaths([CacheDir, 'render', 'wave_instrument.htt']), RenderInstruments(Song.Instruments.Wave, UsedStuff.HighestWaveInst));
653 WriteHTT(ConcatPaths([CacheDir, 'render', 'noise_instrument.htt']), RenderInstruments(Song.Instruments.Noise, MaxInstrIdx)); 731 WriteHTT(ConcatPaths([CacheDir, 'render', 'noise_instrument.htt']), RenderInstruments(Song.Instruments.Noise, UsedStuff.HighestNoiseInst));
654 for I := Low(TRoutineBank) to High(TRoutineBank) do 732 for I := Low(TRoutineBank) to High(TRoutineBank) do
655 WriteHTT(ConcatPaths([CacheDir, 'render', 'routine'+IntToStr(I)+'.htt']), Song.Routines[I]); 733 WriteHTT(ConcatPaths([CacheDir, 'render', 'routine'+IntToStr(I)+'.htt']), Song.Routines[I]);
656 734
@@ -658,7 +736,7 @@ begin
658 Rewrite(OutFile); 736 Rewrite(OutFile);
659 737
660 for I := 0 to Song.Patterns.Count - 1 do 738 for I := 0 to Song.Patterns.Count - 1 do
661 if PatternIsUsed(Song.Patterns.Keys[I], Song) then 739 if PatternIsUsed(Song.Patterns.Keys[I], UsedStuff) then
662 Write(OutFile, RenderPattern('P' + IntToStr(Song.Patterns.Keys[I]), 740 Write(OutFile, RenderPattern('P' + IntToStr(Song.Patterns.Keys[I]),
663 Song.Patterns.Data[I]^)); 741 Song.Patterns.Data[I]^));
664 742
@@ -668,7 +746,7 @@ begin
668 Rewrite(OutFile); 746 Rewrite(OutFile);
669 747
670 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do 748 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do
671 if InstrumentIsUsed(I, Song) then 749 if InstrumentIsUsed(ModInst(I), Song.Instruments.All[I].Type_, UsedStuff) then
672 with Song.Instruments.All[I] do begin 750 with Song.Instruments.All[I] do begin
673 if SubpatternEnabled then begin 751 if SubpatternEnabled then begin
674 WriteStr(TypePrefix, Type_); 752 WriteStr(TypePrefix, Type_);
@@ -770,6 +848,7 @@ begin
770 end; 848 end;
771 finally 849 finally
772 Proc.Free; 850 Proc.Free;
851 FreeUsedStuff(UsedStuff);
773 end; 852 end;
774 end; 853 end;
775 854
Modifiedsrc/song.pas +0−57
@@ -122,11 +122,6 @@ function UpgradeSong(S: TSongV4): TSong; overload;
122 //function UpgradeSong(S: TSongV5): TSong; overload; 122 //function UpgradeSong(S: TSongV5): TSong; overload;
123 123
124 function OptimizeSong(const S: TSong): TSong; 124 function OptimizeSong(const S: TSong): TSong;
125 function PatternIsUsed(Idx: Integer; const Song: TSong): Boolean;
126 function MaxInstrumentIndex(const Song: TSong): Integer;
127 function InstrumentIsUsed(Idx: Integer; const Song: TSong): Boolean;
128 function MaxWaveIndex(const Song: TSong): Integer;
129 function WaveIsUsed(Idx: Integer; const Song: TSong): Boolean;
130 125
131 implementation 126 implementation
132 127
@@ -845,57 +840,5 @@ begin
845 end; 840 end;
846 end; 841 end;
847 842
848 function PatternIsUsed(Idx: Integer; const Song: TSong): Boolean;
849 var
850 I, J: Integer;
851 begin
852 for I := Low(Song.OrderMatrix) to High(Song.OrderMatrix) do
853 for J := Low(Song.OrderMatrix[I]) to High(Song.OrderMatrix[I])-1 do
854 if Song.OrderMatrix[I, J] = Idx then Exit(True);
855
856 Result := False;
857 end;
858
859 function MaxInstrumentIndex(const Song: TSong): Integer;
860 var
861 I, J, K: Integer;
862 begin
863 K := -1;
864
865 for I := 0 to Song.Patterns.Count - 1 do
866 if PatternIsUsed(Song.Patterns.Keys[I], Song) then
867 for J := Low(Song.Patterns.Data[I]^) to High(Song.Patterns.Data[I]^) do
868 if K < Song.Patterns.Data[I]^[J].Instrument then
869 K := Song.Patterns.Data[I]^[J].Instrument;
870
871 Result := K;
872 end;
873
874 function InstrumentIsUsed(Idx: Integer; const Song: TSong): Boolean;
875 begin
876 if Idx > 15 then
877 Idx := ((Idx - 1) mod 15) + 1;
878 Result := Idx <= MaxInstrumentIndex(Song);
879 end;
880
881 function MaxWaveIndex(const Song: TSong): Integer;
882 var
883 I, K, MaxInstrIdx: Integer;
884 begin
885 K := -1;
886 MaxInstrIdx := MaxInstrumentIndex(Song);
887
888 for I := Low(Song.Instruments.Wave) to MaxInstrIdx do
889 if K < Song.Instruments.Wave[I].Waveform then
890 K := Song.Instruments.Wave[I].Waveform;
891
892 Result := K;
893 end;
894
895 function WaveIsUsed(Idx: Integer; const Song: TSong): Boolean;
896 begin
897 Result := Idx <= MaxWaveIndex(Song);
898 end;
899
900 end. 843 end.
901 844