@@ -17,7 +17,7 @@ type |
| 17 |
Artist: ShortString; |
17 |
Artist: ShortString; |
| 18 |
Comment: ShortString; |
18 |
Comment: ShortString; |
| 19 |
|
19 |
|
| 20 |
Instruments: TInstrumentBank; |
20 |
Instruments: TInstrumentBankV1; |
| 21 |
Waves: TWaveBankV1; |
21 |
Waves: TWaveBankV1; |
| 22 |
|
22 |
|
| 23 |
TicksPerRow: Integer; |
23 |
TicksPerRow: Integer; |
@@ -33,7 +33,7 @@ type |
| 33 |
Artist: ShortString; |
33 |
Artist: ShortString; |
| 34 |
Comment: ShortString; |
34 |
Comment: ShortString; |
| 35 |
|
35 |
|
| 36 |
Instruments: TInstrumentBank; |
36 |
Instruments: TInstrumentBankV1; |
| 37 |
Waves: TWaveBankV1; |
37 |
Waves: TWaveBankV1; |
| 38 |
|
38 |
|
| 39 |
TicksPerRow: Integer; |
39 |
TicksPerRow: Integer; |
@@ -51,9 +51,26 @@ type |
| 51 |
Artist: ShortString; |
51 |
Artist: ShortString; |
| 52 |
Comment: ShortString; |
52 |
Comment: ShortString; |
| 53 |
|
53 |
|
| 54 |
Instruments: TInstrumentCollection; |
54 |
Instruments: TInstrumentCollectionV1; |
|
|
55 |
Waves: TWaveBankV2; |
| 55 |
|
56 |
|
| 56 |
Waves: TWaveBank; |
57 |
TicksPerRow: Integer; |
|
|
58 |
|
|
|
59 |
Patterns: TPatternMap; |
|
|
60 |
OrderMatrix: TOrderMatrix; |
|
|
61 |
|
|
|
62 |
Routines: TRoutineBank; |
|
|
63 |
end; |
|
|
64 |
|
|
|
65 |
TSongV4 = packed record |
|
|
66 |
Version: Integer; |
|
|
67 |
|
|
|
68 |
Name: ShortString; |
|
|
69 |
Artist: ShortString; |
|
|
70 |
Comment: ShortString; |
|
|
71 |
|
|
|
72 |
Instruments: TInstrumentCollectionV2; |
|
|
73 |
Waves: TWaveBankV2; |
| 57 |
|
74 |
|
| 58 |
TicksPerRow: Integer; |
75 |
TicksPerRow: Integer; |
| 59 |
|
76 |
|
@@ -65,7 +82,7 @@ type |
| 65 |
|
82 |
|
| 66 |
{ TSong } |
83 |
{ TSong } |
| 67 |
|
84 |
|
| 68 |
TSong = TSongV3; |
85 |
TSong = TSongV4; |
| 69 |
|
86 |
|
| 70 |
procedure WriteSongToStream(S: TStream; const ASong: TSong); |
87 |
procedure WriteSongToStream(S: TStream; const ASong: TSong); |
| 71 |
procedure ReadSongFromStream(S: TStream; out ASong: TSong); |
88 |
procedure ReadSongFromStream(S: TStream; out ASong: TSong); |
@@ -76,6 +93,7 @@ procedure DestroySong(var S: TSong); |
| 76 |
function UpgradeSong(S: TSongV1): TSong; overload; |
93 |
function UpgradeSong(S: TSongV1): TSong; overload; |
| 77 |
function UpgradeSong(S: TSongV2): TSong; overload; |
94 |
function UpgradeSong(S: TSongV2): TSong; overload; |
| 78 |
function UpgradeSong(S: TSongV3): TSong; overload; |
95 |
function UpgradeSong(S: TSongV3): TSong; overload; |
|
|
96 |
function UpgradeSong(S: TSongV4): TSong; overload; |
| 79 |
|
97 |
|
| 80 |
implementation |
98 |
implementation |
| 81 |
|
99 |
|
@@ -198,13 +216,54 @@ begin |
| 198 |
ASong.Routines[I] := S.ReadAnsiString; |
216 |
ASong.Routines[I] := S.ReadAnsiString; |
| 199 |
end; |
217 |
end; |
| 200 |
|
218 |
|
|
|
219 |
procedure ReadSongFromStreamV4(S: TStream; out ASong: TSongV4); |
|
|
220 |
var |
|
|
221 |
i, n: Integer; |
|
|
222 |
pat: PPattern; |
|
|
223 |
begin |
|
|
224 |
// Read the fixed elements first |
|
|
225 |
n := SizeOf(TSongV4) |
|
|
226 |
- SizeOf(TPatternMap) |
|
|
227 |
- SizeOf(TOrderMatrix) |
|
|
228 |
- SizeOf(TRoutineBank); |
|
|
229 |
|
|
|
230 |
S.Read(ASong, n); |
|
|
231 |
|
|
|
232 |
// Create the patterns |
|
|
233 |
ASong.Patterns := TPatternMap.Create; |
|
|
234 |
// Read the pattern count |
|
|
235 |
S.Read(n, SizeOf(Integer)); |
|
|
236 |
for i:=0 to n - 1 do begin |
|
|
237 |
// Allocate memory for each pattern ... |
|
|
238 |
New(pat); |
|
|
239 |
// and read the pattern content |
|
|
240 |
S.Read(pat^, SizeOf(TPattern)); |
|
|
241 |
// Add the pattern to the list |
|
|
242 |
ASong.Patterns.Add(i, pat); |
|
|
243 |
end; |
|
|
244 |
|
|
|
245 |
// Read the OrderMatrix |
|
|
246 |
for i := 0 to 3 do |
|
|
247 |
begin |
|
|
248 |
// Read length of each OrderMatrix array |
|
|
249 |
S.Read(n, SizeOf(Integer)); |
|
|
250 |
// Allocate memory for it |
|
|
251 |
SetLength(ASong.OrderMatrix[i], n); |
|
|
252 |
// Read content of OrderMatrix array |
|
|
253 |
S.Read(ASong.OrderMatrix[i, 0], n*SizeOf(Integer)); |
|
|
254 |
end; |
|
|
255 |
|
|
|
256 |
for I := Low(TRoutineBank) to High(TRoutineBank) do |
|
|
257 |
ASong.Routines[I] := S.ReadAnsiString; |
|
|
258 |
end; |
|
|
259 |
|
| 201 |
procedure WriteSongToStream(S: TStream; const ASong: TSong); |
260 |
procedure WriteSongToStream(S: TStream; const ASong: TSong); |
| 202 |
var |
261 |
var |
| 203 |
i, n: Integer; |
262 |
i, n: Integer; |
| 204 |
pPat: PPattern; |
263 |
pPat: PPattern; |
| 205 |
begin |
264 |
begin |
| 206 |
// Write the fixed record elements first |
265 |
// Write the fixed record elements first |
| 207 |
n := SizeOf(TSongV3) |
266 |
n := SizeOf(TSongV4) |
| 208 |
- SizeOf(TPatternMap) |
267 |
- SizeOf(TPatternMap) |
| 209 |
- SizeOf(TOrderMatrix) |
268 |
- SizeOf(TOrderMatrix) |
| 210 |
- SizeOf(TRoutineBank); |
269 |
- SizeOf(TRoutineBank); |
@@ -237,6 +296,7 @@ var |
| 237 |
Version: Integer; |
296 |
Version: Integer; |
| 238 |
SV1: TSongV1; |
297 |
SV1: TSongV1; |
| 239 |
SV2: TSongV2; |
298 |
SV2: TSongV2; |
|
|
299 |
SV3: TSongV3; |
| 240 |
begin |
300 |
begin |
| 241 |
S.Read(Version, SizeOf(Integer)); |
301 |
S.Read(Version, SizeOf(Integer)); |
| 242 |
S.Seek(0, soBeginning); |
302 |
S.Seek(0, soBeginning); |
@@ -249,7 +309,11 @@ begin |
| 249 |
ReadSongFromStreamV2(S, SV2); |
309 |
ReadSongFromStreamV2(S, SV2); |
| 250 |
ASong := UpgradeSong(SV2); |
310 |
ASong := UpgradeSong(SV2); |
| 251 |
end; |
311 |
end; |
| 252 |
3: ReadSongFromStreamV3(S, ASong); |
312 |
3: begin |
|
|
313 |
ReadSongFromStreamV3(S, SV3); |
|
|
314 |
ASong := UpgradeSong(SV3); |
|
|
315 |
end; |
|
|
316 |
4: ReadSongFromStreamV4(S, ASong); |
| 253 |
end; |
317 |
end; |
| 254 |
end; |
318 |
end; |
| 255 |
|
319 |
|
@@ -303,10 +367,11 @@ begin |
| 303 |
InitialVolume := High(TEnvelopeVolume); |
367 |
InitialVolume := High(TEnvelopeVolume); |
| 304 |
VolSweepDirection := Down; |
368 |
VolSweepDirection := Down; |
| 305 |
VolSweepAmount := 0; |
369 |
VolSweepAmount := 0; |
| 306 |
|
370 |
NoiseMacro := Default(TNoiseMacro); |
| 307 |
ShiftClockFreq := 0; |
371 |
// TODO: Come back here |
| 308 |
DividingRatio := 0; |
372 |
//ShiftClockFreq := 0; |
| 309 |
CounterStep := swFifteen; |
373 |
//DividingRatio := 0; |
|
|
374 |
//CounterStep := swFifteen; |
| 310 |
end; |
375 |
end; |
| 311 |
|
376 |
|
| 312 |
for I := Low(S.Waves) to High(S.Waves) do begin |
377 |
for I := Low(S.Waves) to High(S.Waves) do begin |
@@ -402,13 +467,59 @@ var |
| 402 |
SV3: TSongV3; |
467 |
SV3: TSongV3; |
| 403 |
I: Integer; |
468 |
I: Integer; |
| 404 |
begin |
469 |
begin |
| 405 |
InitializeSong(SV3); |
|
|
| 406 |
SV3.Patterns.Free; // We already have one in S, so free the one InitializeSong creates. |
|
|
| 407 |
|
|
|
| 408 |
SV3.Version:=3; |
470 |
SV3.Version:=3; |
| 409 |
SV3.Name:=S.Name; |
471 |
SV3.Name:=S.Name; |
| 410 |
SV3.Artist:=S.Artist; |
472 |
SV3.Artist:=S.Artist; |
| 411 |
SV3.Comment:=S.Comment; |
473 |
SV3.Comment:=S.Comment; |
|
|
474 |
SV3.TicksPerRow:=S.TicksPerRow; |
|
|
475 |
SV3.Patterns:=S.Patterns; |
|
|
476 |
SV3.OrderMatrix:=S.OrderMatrix; |
|
|
477 |
SV3.Routines:=S.Routines; |
|
|
478 |
|
|
|
479 |
// AWFUL!!!! |
|
|
480 |
for I := Low(SV3.Instruments.All) to High(SV3.Instruments.All) do |
|
|
481 |
SV3.Instruments.All[I] := Default(TInstrumentV1); |
|
|
482 |
|
|
|
483 |
for I := Low(SV3.Instruments.Duty) to High(SV3.Instruments.Duty) do begin |
|
|
484 |
with SV3.Instruments.Duty[I] do begin |
|
|
485 |
Type_ := itSquare; |
|
|
486 |
Length := 0; |
|
|
487 |
LengthEnabled := False; |
|
|
488 |
InitialVolume := High(TEnvelopeVolume); |
|
|
489 |
VolSweepDirection := Down; |
|
|
490 |
VolSweepAmount := 0; |
|
|
491 |
|
|
|
492 |
SweepTime := 0; |
|
|
493 |
SweepIncDec := Down; |
|
|
494 |
SweepShift := 0; |
|
|
495 |
|
|
|
496 |
Duty := 2; |
|
|
497 |
|
|
|
498 |
OutputLevel := 1; |
|
|
499 |
end; |
|
|
500 |
end; |
|
|
501 |
|
|
|
502 |
for I := Low(SV3.Instruments.Wave) to High(SV3.Instruments.Wave) do |
|
|
503 |
with SV3.Instruments.Wave[I] do begin |
|
|
504 |
Type_ := itWave; |
|
|
505 |
Length := 0; |
|
|
506 |
LengthEnabled := False; |
|
|
507 |
OutputLevel := 1; |
|
|
508 |
Waveform := I-1; |
|
|
509 |
end; |
|
|
510 |
|
|
|
511 |
for I := Low(SV3.Instruments.Noise) to High(SV3.Instruments.Noise) do |
|
|
512 |
with SV3.Instruments.Noise[I] do begin |
|
|
513 |
Type_ := itNoise; |
|
|
514 |
Length := 0; |
|
|
515 |
LengthEnabled := False; |
|
|
516 |
InitialVolume := High(TEnvelopeVolume); |
|
|
517 |
VolSweepDirection := Down; |
|
|
518 |
VolSweepAmount := 0; |
|
|
519 |
ShiftClockFreq := 0; |
|
|
520 |
DividingRatio := 0; |
|
|
521 |
CounterStep := swFifteen; |
|
|
522 |
end; |
| 412 |
|
523 |
|
| 413 |
for I := Low(S.Instruments) to High(S.Instruments) do begin |
524 |
for I := Low(S.Instruments) to High(S.Instruments) do begin |
| 414 |
case S.Instruments[I].Type_ of |
525 |
case S.Instruments[I].Type_ of |
@@ -419,17 +530,36 @@ begin |
| 419 |
end; |
530 |
end; |
| 420 |
|
531 |
|
| 421 |
for I := Low(TWaveBank) to High(TWaveBank) do |
532 |
for I := Low(TWaveBank) to High(TWaveBank) do |
| 422 |
Move(S.Waves[I], SV3.Waves[I], SizeOf(TWave)); |
533 |
Move(S.Waves[I], SV3.Waves[I], SizeOf(TWaveV2)); |
| 423 |
|
|
|
| 424 |
SV3.TicksPerRow:=S.TicksPerRow; |
|
|
| 425 |
SV3.Patterns:=S.Patterns; |
|
|
| 426 |
SV3.OrderMatrix:=S.OrderMatrix; |
|
|
| 427 |
SV3.Routines:=S.Routines; |
|
|
| 428 |
|
534 |
|
| 429 |
Result := UpgradeSong(SV3); |
535 |
Result := UpgradeSong(SV3); |
| 430 |
end; |
536 |
end; |
| 431 |
|
537 |
|
| 432 |
function UpgradeSong(S: TSongV3): TSong; |
538 |
function UpgradeSong(S: TSongV3): TSong; |
|
|
539 |
var |
|
|
540 |
SV4: TSongV4; |
|
|
541 |
I: Integer; |
|
|
542 |
begin |
|
|
543 |
SV4.Version:=4; |
|
|
544 |
SV4.Name:=S.Name; |
|
|
545 |
SV4.Artist:=S.Artist; |
|
|
546 |
SV4.Comment:=S.Comment; |
|
|
547 |
SV4.TicksPerRow:=S.TicksPerRow; |
|
|
548 |
SV4.Patterns:=S.Patterns; |
|
|
549 |
SV4.OrderMatrix:=S.OrderMatrix; |
|
|
550 |
SV4.Routines:=S.Routines; |
|
|
551 |
SV4.Waves := S.Waves; |
|
|
552 |
|
|
|
553 |
// for now just generate a blank noise macro |
|
|
554 |
for I := Low(S.Instruments.All) to High(S.Instruments.All) do begin |
|
|
555 |
Move(S.Instruments.All[I], SV4.Instruments.All[I], SizeOf(TInstrumentV1)); |
|
|
556 |
SV4.Instruments.All[I].NoiseMacro := Default(TNoiseMacro); |
|
|
557 |
end; |
|
|
558 |
|
|
|
559 |
Result := UpgradeSong(SV4); |
|
|
560 |
end; |
|
|
561 |
|
|
|
562 |
function UpgradeSong(S: TSongV4): TSong; |
| 433 |
begin |
563 |
begin |
| 434 |
Result := S; |
564 |
Result := S; |
| 435 |
end; |
565 |
end; |