@@ -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 |
|