Commit 3b48f12

Nick Faro committed on
Add subpatterns to GBDK, use 6 byte instrs
commit 3b48f122e45aa8e6ad06960d4c89303f0be229fb parent 39bceb5
2 changed files +99−38
Modifiedcodegen.pas +98−37
@@ -52,17 +52,49 @@ procedure RenderSongToGBDKC(Song: TSong; DescriptorName: String; Filename: strin
52 SL.Free; 52 SL.Free;
53 end; 53 end;
54 54
55 function RenderGBDKSubpatternCell(Cell: TCell; Last: Boolean): string;
56 var
57 SL: TStringList;
58 begin
59 SL := TStringList.Create;
60 SL.Delimiter := ',';
61
62 if Cell.Note = NO_NOTE then
63 SL.Add('___')
64 else
65 SL.Add(IntToStr(Cell.Note));
66
67 if Last and (Cell.Volume = 0) then
68 SL.Add(IntToStr(1)) // Automatically insert jump back to row 1 if last cell
69 else
70 SL.Add(IntToStr(EnsureRange(Cell.Volume, 0, 32)));
71
72 SL.Add('0x' + EffectCodeToStr(Cell.EffectCode, Cell.EffectParams));
73
74 Result := SL.DelimitedText;
75 SL.Free;
76 end;
77
55 function RenderGBDKPattern(Name: string; Pat: TPattern): string; 78 function RenderGBDKPattern(Name: string; Pat: TPattern): string;
56 var 79 var
57 Cell: TCell; 80 Cell: TCell;
58 begin 81 begin
59
60 Result := 'static const unsigned char ' + Name + '[] = {' + LineEnding; 82 Result := 'static const unsigned char ' + Name + '[] = {' + LineEnding;
61 for Cell in Pat do 83 for Cell in Pat do
62 Result += ' DN(' + RenderGBDKCell(Cell) + '),' + LineEnding; 84 Result += ' DN(' + RenderGBDKCell(Cell) + '),' + LineEnding;
63 Result += '};'; 85 Result += '};';
64 end; 86 end;
65 87
88 function RenderGBDKSubpattern(Name: string; Pat: TPattern): string;
89 var
90 I: Integer;
91 begin
92 Result := 'static const unsigned char ' + Name + '[] = {' + LineEnding;
93 for I := 0 to 31 do
94 Result += ' DN(' + RenderGBDKSubpatternCell(Pat[I], I = 31) + '),' + LineEnding;
95 Result += '};';
96 end;
97
66 function RenderGBDKOrder(Number: integer; Order: array of integer): string; 98 function RenderGBDKOrder(Number: integer; Order: array of integer): string;
67 var 99 var
68 SL: TStringList; 100 SL: TStringList;
@@ -81,12 +113,13 @@ procedure RenderSongToGBDKC(Song: TSong; DescriptorName: String; Filename: strin
81 SL.Free; 113 SL.Free;
82 end; 114 end;
83 115
84 function RenderGBDKInstrument(Instrument: TInstrument): string; 116 function RenderGBDKInstrument(Instrument: TInstrument; Num: Integer): string;
85 var 117 var
86 SL: TStringList; 118 SL: TStringList;
87 AsmInstrument: TAsmInstrument; 119 AsmInstrument: TAsmInstrument;
88 J: integer; 120 J: integer;
89 HighMask: byte; 121 HighMask: byte;
122 TypePrefix: String;
90 begin 123 begin
91 AsmInstrument := InstrumentToBytes(Instrument); 124 AsmInstrument := InstrumentToBytes(Instrument);
92 SL := TStringList.Create; 125 SL := TStringList.Create;
@@ -103,24 +136,39 @@ procedure RenderSongToGBDKC(Song: TSong; DescriptorName: String; Filename: strin
103 if Instrument.CounterStep = swSeven then 136 if Instrument.CounterStep = swSeven then
104 HighMask := HighMask or %10000000; 137 HighMask := HighMask or %10000000;
105 SL.Add(IntToStr(HighMask)); 138 SL.Add(IntToStr(HighMask));
106
107 for J := Low(TNoiseMacro) to High(TNoiseMacro) do
108 SL.Add(IntToStr(Byte(0)));
109 end 139 end
110 else 140 else
111 for J := Low(AsmInstrument) to High(AsmInstrument) do 141 for J := Low(AsmInstrument) to High(AsmInstrument) do
112 SL.Add(IntToStr(AsmInstrument[J])); 142 SL.Add(IntToStr(AsmInstrument[J]));
113 143
114 Result := SL.DelimitedText; 144 WriteStr(TypePrefix, Instrument.Type_);
145
146 if Instrument.SubpatternEnabled then
147 SL.Insert(SL.Count-1, Format('%sSP%d', [TypePrefix, Num]))
148 else
149 SL.Insert(SL.Count-1, '0');
150
151 if Instrument.Type_ = itNoise then begin
152 SL.Add('0');
153 SL.Add('0');
154 end;
155
156 Result := '{'+SL.DelimitedText+'}';
115 end; 157 end;
116 158
117 function RenderGBDKInstrumentBank(Name: string; Bank: TInstrumentBank): string; 159 function RenderGBDKInstrumentBank(Name: string; Bank: TInstrumentBank): string;
118 var 160 var
119 I: integer; 161 I: integer;
162 InstrType: String;
120 begin 163 begin
121 Result := 'static const unsigned char ' + Name + '[] = {'+LineEnding; 164 case Bank[1].Type_ of
165 itSquare: InstrType := 'hUGEDutyInstr_t';
166 itWave: InstrType := 'hUGEWaveInstr_t';
167 itNoise: InstrType := 'hUGENoiseInstr_t';
168 end;
169 Result := 'static const ' + InstrType + ' ' + Name + '[] = {'+LineEnding;
122 for I := Low(Bank) to High(Bank) do begin 170 for I := Low(Bank) to High(Bank) do begin
123 Result += RenderGBDKInstrument(Bank[I]) + ','+LineEnding; 171 Result += ' '+RenderGBDKInstrument(Bank[I], I) + ','+LineEnding;
124 end; 172 end;
125 Result += '};'; 173 Result += '};';
126 end; 174 end;
@@ -150,6 +198,7 @@ var
150 OrderCnt: integer; 198 OrderCnt: integer;
151 I: integer; 199 I: integer;
152 F: Text; 200 F: Text;
201 TypePrefix: String;
153 begin 202 begin
154 Song := OptimizeSong(Song); 203 Song := OptimizeSong(Song);
155 204
@@ -171,14 +220,20 @@ begin
171 OutSL.Add(Format('static const unsigned char order_cnt = %d;', [OrderCnt * 2])); 220 OutSL.Add(Format('static const unsigned char order_cnt = %d;', [OrderCnt * 2]));
172 OutSL.Add(''); 221 OutSL.Add('');
173 222
174 // TODO: Are keys and data defined to be aligned? Seems like they are but
175 // should probably find out if that's just an implementation detail...
176 for I := 0 to Song.Patterns.Count - 1 do 223 for I := 0 to Song.Patterns.Count - 1 do
177 if PatternIsUsed(Song.Patterns.Keys[I], Song) then 224 if PatternIsUsed(Song.Patterns.Keys[I], Song) then
178 OutSL.Add(RenderGBDKPattern('P' + IntToStr(Song.Patterns.Keys[I]), 225 OutSL.Add(RenderGBDKPattern('P' + IntToStr(Song.Patterns.Keys[I]),
179 Song.Patterns.Data[I]^)); 226 Song.Patterns.Data[I]^));
180 OutSL.Add(''); 227 OutSL.Add('');
181 228
229 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do
230 with Song.Instruments.All[I] do begin
231 if SubpatternEnabled then begin
232 WriteStr(TypePrefix, Type_);
233 OutSL.Add(RenderGBDKSubpattern(TypePrefix+'SP' + IntToStr(ModInst(I)), Subpattern));
234 end;
235 end;
236
182 OutSL.Add(RenderGBDKOrder(1, Song.OrderMatrix[0])); 237 OutSL.Add(RenderGBDKOrder(1, Song.OrderMatrix[0]));
183 OutSL.Add(RenderGBDKOrder(2, Song.OrderMatrix[1])); 238 OutSL.Add(RenderGBDKOrder(2, Song.OrderMatrix[1]));
184 OutSL.Add(RenderGBDKOrder(3, Song.OrderMatrix[2])); 239 OutSL.Add(RenderGBDKOrder(3, Song.OrderMatrix[2]));
@@ -279,7 +334,10 @@ begin
279 ResultSL.Insert(ResultSL.Count-1, Format('dw %sSP%d', [TypePrefix, I])) 334 ResultSL.Insert(ResultSL.Count-1, Format('dw %sSP%d', [TypePrefix, I]))
280 else 335 else
281 ResultSL.Insert(ResultSL.Count-1, 'dw 0'); 336 ResultSL.Insert(ResultSL.Count-1, 'dw 0');
282 ResultSL.Add('ds '+IfThen(Instruments[I].Type_ = itNoise, '4', '2')); 337
338 if Instruments[I].Type_ = itNoise then
339 ResultSL.Add('ds 2');
340
283 ResultSL.Add(''); 341 ResultSL.Add('');
284 end; 342 end;
285 343
@@ -312,22 +370,7 @@ begin
312 SL.Free; 370 SL.Free;
313 end; 371 end;
314 372
315 function RenderPattern(Name: string; Pattern: TPattern): string; 373 function RenderSubpatternCell(Cell: TCell; Last: Boolean): string;
316 var
317 SL: TStringList;
318 I: integer;
319 begin
320 SL := TStringList.Create;
321 SL.Add(Name + ':');
322
323 for I := Low(TPattern) to High(TPattern) do
324 SL.Add(RenderCell(Pattern[I]));
325
326 Result := SL.Text;
327 SL.Free;
328 end;
329
330 function RenderTableCell(Cell: TCell; Last: Boolean): string;
331 var 374 var
332 SL: TStringList; 375 SL: TStringList;
333 begin 376 begin
@@ -352,7 +395,22 @@ begin
352 SL.Free; 395 SL.Free;
353 end; 396 end;
354 397
355 function RenderTablePattern(Name: string; Pattern: TPattern): string; 398 function RenderPattern(Name: string; Pattern: TPattern): string;
399 var
400 SL: TStringList;
401 I: integer;
402 begin
403 SL := TStringList.Create;
404 SL.Add(Name + ':');
405
406 for I := Low(TPattern) to High(TPattern) do
407 SL.Add(RenderCell(Pattern[I]));
408
409 Result := SL.Text;
410 SL.Free;
411 end;
412
413 function RenderSubpattern(Name: string; Pattern: TPattern): string;
356 var 414 var
357 SL: TStringList; 415 SL: TStringList;
358 I: integer; 416 I: integer;
@@ -361,7 +419,7 @@ begin
361 SL.Add(Name + ':'); 419 SL.Add(Name + ':');
362 420
363 for I := 0 to 31 do 421 for I := 0 to 31 do
364 SL.Add(RenderTableCell(Pattern[I], I = 31)); // TODO: hardcoded value 422 SL.Add(RenderSubpatternCell(Pattern[I], I = 31)); // TODO: hardcoded value
365 423
366 Result := SL.Text; 424 Result := SL.Text;
367 SL.Free; 425 SL.Free;
@@ -399,6 +457,7 @@ var
399 OutSL: TStringList; 457 OutSL: TStringList;
400 F: Text; 458 F: Text;
401 I: Integer; 459 I: Integer;
460 TypePrefix: String;
402 begin 461 begin
403 OutSL := TStringList.Create; 462 OutSL := TStringList.Create;
404 463
@@ -421,13 +480,19 @@ begin
421 OutSL.Add(RenderOrderTable(Song.OrderMatrix)); 480 OutSL.Add(RenderOrderTable(Song.OrderMatrix));
422 481
423 // Render patterns 482 // Render patterns
424
425 // TODO: Are keys and data defined to be aligned? Seems like they are but
426 // should probably find out if that's just an implementation detail...
427 for I := 0 to Song.Patterns.Count - 1 do 483 for I := 0 to Song.Patterns.Count - 1 do
428 if PatternIsUsed(Song.Patterns.Keys[I], Song) then 484 if PatternIsUsed(Song.Patterns.Keys[I], Song) then
429 OutSL.Add(RenderPattern('P' + IntToStr(Song.Patterns.Keys[I]), Song.Patterns.Data[I]^)); 485 OutSL.Add(RenderPattern('P' + IntToStr(Song.Patterns.Keys[I]), Song.Patterns.Data[I]^));
430 486
487 // Render subpatterns
488 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do
489 with Song.Instruments.All[I] do begin
490 if SubpatternEnabled then begin
491 WriteStr(TypePrefix, Type_);
492 OutSL.Add(RenderSubpattern(TypePrefix+'SP' + IntToStr(ModInst(I)), Subpattern));
493 end;
494 end;
495
431 // Render instruments 496 // Render instruments
432 OutSL.Add('duty_instruments:'); 497 OutSL.Add('duty_instruments:');
433 OutSL.Add(RenderInstruments(Song.Instruments.Duty)); 498 OutSL.Add(RenderInstruments(Song.Instruments.Duty));
@@ -582,8 +647,6 @@ begin
582 AssignFile(OutFile, 'render/pattern.htt'); 647 AssignFile(OutFile, 'render/pattern.htt');
583 Rewrite(OutFile); 648 Rewrite(OutFile);
584 649
585 // TODO: Are keys and data defined to be aligned? Seems like they are but
586 // should probably find out if that's just an implementation detail...
587 for I := 0 to Song.Patterns.Count - 1 do 650 for I := 0 to Song.Patterns.Count - 1 do
588 if PatternIsUsed(Song.Patterns.Keys[I], Song) then 651 if PatternIsUsed(Song.Patterns.Keys[I], Song) then
589 Write(OutFile, RenderPattern('P' + IntToStr(Song.Patterns.Keys[I]), 652 Write(OutFile, RenderPattern('P' + IntToStr(Song.Patterns.Keys[I]),
@@ -594,13 +657,11 @@ begin
594 AssignFile(OutFile, 'render/subpattern.htt'); 657 AssignFile(OutFile, 'render/subpattern.htt');
595 Rewrite(OutFile); 658 Rewrite(OutFile);
596 659
597 // TODO: Are keys and data defined to be aligned? Seems like they are but
598 // should probably find out if that's just an implementation detail...
599 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do 660 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do
600 with Song.Instruments.All[I] do begin 661 with Song.Instruments.All[I] do begin
601 if SubpatternEnabled then begin 662 if SubpatternEnabled then begin
602 WriteStr(TypePrefix, Type_); 663 WriteStr(TypePrefix, Type_);
603 Write(OutFile, RenderTablePattern(TypePrefix+'SP' + IntToStr(ModInst(I)), Subpattern)); 664 Write(OutFile, RenderSubpattern(TypePrefix+'SP' + IntToStr(ModInst(I)), Subpattern));
604 end; 665 end;
605 end; 666 end;
606 667
ModifiedhUGEDriver +1−1
@@ -1 +1 @@
1 Subproject commit 3facfeb04211126c53edbc37841957bd3e8cf91e 1 Subproject commit d0de67619b80fbca580f585d000006caefe7f2c0