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