Commit 5edd985

Nick Faro committed on
Grooves working
commit 5edd98522b37d396ecc73a2f8236fec3066f069c parent 348c97b
6 changed files +172−30
Modifiedsrc/codegen.pas +26−19
@@ -126,6 +126,14 @@ begin
126 itWave: Result := Instrument <= UsedStuff.HighestWaveInst; 126 itWave: Result := Instrument <= UsedStuff.HighestWaveInst;
127 itNoise: Result := Instrument <= UsedStuff.HighestNoiseInst; 127 itNoise: Result := Instrument <= UsedStuff.HighestNoiseInst;
128 end; 128 end;
129
130 function OrderCount(const Song: TSong): Integer;
131 var
132 OrderMatrix: TOrderMatrix;
133 begin
134 OrderMatrix := Song.OrderMatrix;
135 Result := MaxIntValue([High(OrderMatrix[0]), High(OrderMatrix[1]),
136 High(OrderMatrix[2]), High(OrderMatrix[3])]) * 2;
129 end; 137 end;
130 138
131 procedure RenderSongToGBDKC(Song: TSong; DescriptorName: String; Filename: string; Bank: Integer = -1); 139 procedure RenderSongToGBDKC(Song: TSong; DescriptorName: String; Filename: string; Bank: Integer = -1);
@@ -302,7 +310,6 @@ procedure RenderSongToGBDKC(Song: TSong; DescriptorName: String; Filename: strin
302 var 310 var
303 OrderMatrix: TOrderMatrix; 311 OrderMatrix: TOrderMatrix;
304 OutSL: TStringList; 312 OutSL: TStringList;
305 OrderCnt: integer;
306 I: integer; 313 I: integer;
307 F: Text; 314 F: Text;
308 TypePrefix: String; 315 TypePrefix: String;
@@ -322,13 +329,6 @@ begin
322 OutSL.Add('#include <stddef.h>'); 329 OutSL.Add('#include <stddef.h>');
323 OutSL.Add(''); 330 OutSL.Add('');
324 331
325 OrderMatrix := Song.OrderMatrix;
326 OrderCnt := MaxIntValue([High(OrderMatrix[0]), High(OrderMatrix[1]),
327 High(OrderMatrix[2]), High(OrderMatrix[3])]);
328
329 OutSL.Add(Format('static const unsigned char order_cnt = %d;', [OrderCnt * 2]));
330 OutSL.Add('');
331
332 for I := 0 to Song.Patterns.Count - 1 do 332 for I := 0 to Song.Patterns.Count - 1 do
333 if PatternIsUsed(Song.Patterns.Keys[I], UsedStuff) then 333 if PatternIsUsed(Song.Patterns.Keys[I], UsedStuff) then
334 OutSL.Add(RenderGBDKPattern('P' + IntToStr(Song.Patterns.Keys[I]), 334 OutSL.Add(RenderGBDKPattern('P' + IntToStr(Song.Patterns.Keys[I]),
@@ -362,9 +362,12 @@ begin
362 OutSL.Add(Format('const void __at(%d) __bank_%s;', [Bank, DescriptorName])); 362 OutSL.Add(Format('const void __at(%d) __bank_%s;', [Bank, DescriptorName]));
363 363
364 OutSL.Add(Format( 364 OutSL.Add(Format(
365 'const hUGESong_t %s = {%d, &order_cnt, order1, order2, order3,'+ 365 'const hUGESong_t %s = {%d, %d, %d, %d, %d, order1, order2, order3,'+
366 'order4, duty_instruments, wave_instruments, noise_instruments, NULL, waves};', 366 'order4, duty_instruments, wave_instruments, noise_instruments, NULL, waves};',
367 [DescriptorName, Song.TicksPerRow])); 367 [DescriptorName,
368 Song.TicksPerRow[0], Song.TicksPerRow[1], Song.TicksPerRow[2], Song.TicksPerRow[3],
369 OrderCount(Song)
370 ]));
368 371
369 AssignFile(F, Filename); 372 AssignFile(F, Filename);
370 Rewrite(F); 373 Rewrite(F);
@@ -392,13 +395,9 @@ function RenderOrderTable(OrderMatrix: TOrderMatrix): string;
392 395
393 var 396 var
394 Res: TStringList; 397 Res: TStringList;
395 OrderCnt: integer;
396 begin 398 begin
397 Res := TStringList.Create; 399 Res := TStringList.Create;
398 OrderCnt := MaxIntValue([High(OrderMatrix[0]), High(OrderMatrix[1]),
399 High(OrderMatrix[2]), High(OrderMatrix[3])]);
400 400
401 Res.Add('order_cnt: db ' + IntToStr(OrderCnt * 2));
402 Res.Add('order1: dw ' + ArrayHelper(OrderMatrix[0])); 401 Res.Add('order1: dw ' + ArrayHelper(OrderMatrix[0]));
403 Res.Add('order2: dw ' + ArrayHelper(OrderMatrix[1])); 402 Res.Add('order2: dw ' + ArrayHelper(OrderMatrix[1]));
404 Res.Add('order3: dw ' + ArrayHelper(OrderMatrix[2])); 403 Res.Add('order3: dw ' + ArrayHelper(OrderMatrix[2]));
@@ -583,8 +582,11 @@ begin
583 582
584 // Render song descriptor 583 // Render song descriptor
585 OutSL.Add(DescriptorName+'::'); 584 OutSL.Add(DescriptorName+'::');
586 OutSL.Add('db '+IntToStr(Song.TicksPerRow)); 585 OutSL.Add('db '+IntToStr(Song.TicksPerRow[0])+', '
587 OutSL.Add('dw order_cnt'); 586 +IntToStr(Song.TicksPerRow[1])+', '
587 +IntToStr(Song.TicksPerRow[2])+', '
588 +IntToStr(Song.TicksPerRow[3]));
589 OutSL.Add('dw '+IntToStr(OrderCount(Song)));
588 OutSL.Add('dw order1, order2, order3, order4'); 590 OutSL.Add('dw order1, order2, order3, order4');
589 OutSL.Add('dw duty_instruments, wave_instruments, noise_instruments'); 591 OutSL.Add('dw duty_instruments, wave_instruments, noise_instruments');
590 OutSL.Add('dw routines'); 592 OutSL.Add('dw routines');
@@ -600,7 +602,7 @@ begin
600 OutSL.Add(RenderPattern('P' + IntToStr(Song.Patterns.Keys[I]), Song.Patterns.Data[I]^)); 602 OutSL.Add(RenderPattern('P' + IntToStr(Song.Patterns.Keys[I]), Song.Patterns.Data[I]^));
601 603
602 // Render subpatterns 604 // Render subpatterns
603 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do 605 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do
604 if InstrumentIsUsed(ModInst(I), Song.Instruments.All[I].Type_, UsedStuff) then 606 if InstrumentIsUsed(ModInst(I), Song.Instruments.All[I].Type_, UsedStuff) then
605 with Song.Instruments.All[I] do begin 607 with Song.Instruments.All[I] do begin
606 if SubpatternEnabled then begin 608 if SubpatternEnabled then begin
@@ -778,7 +780,7 @@ begin
778 AssignFile(OutFile, ConcatPaths([CacheDir, 'render', 'subpattern.htt'])); 780 AssignFile(OutFile, ConcatPaths([CacheDir, 'render', 'subpattern.htt']));
779 Rewrite(OutFile); 781 Rewrite(OutFile);
780 782
781 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do 783 for I := Low(Song.Instruments.All) to High(Song.Instruments.All) do
782 if InstrumentIsUsed(ModInst(I), Song.Instruments.All[I].Type_, UsedStuff) then 784 if InstrumentIsUsed(ModInst(I), Song.Instruments.All[I].Type_, UsedStuff) then
783 with Song.Instruments.All[I] do begin 785 with Song.Instruments.All[I] do begin
784 if SubpatternEnabled then begin 786 if SubpatternEnabled then begin
@@ -805,7 +807,12 @@ begin
805 807
806 if Assemble(Filename + '_song.obj', 808 if Assemble(Filename + '_song.obj',
807 ConcatPaths([RuntimeDir, 'hUGEDriver', 'song.asm']), 809 ConcatPaths([RuntimeDir, 'hUGEDriver', 'song.asm']),
808 ['SONG_DESCRIPTOR=song', 'TICKS='+IntToStr(Song.TicksPerRow)]) <> 0 then Die; 810 ['SONG_DESCRIPTOR=song',
811 'ORDER_COUNT='+IntToStr(OrderCount(Song)),
812 'TICKS0='+IntToStr(Song.TicksPerRow[0]),
813 'TICKS1='+IntToStr(Song.TicksPerRow[1]),
814 'TICKS2='+IntToStr(Song.TicksPerRow[2]),
815 'TICKS3='+IntToStr(Song.TicksPerRow[3])]) <> 0 then Die;
809 816
810 if Mode = emGBS then 817 if Mode = emGBS then
811 begin 818 begin
Modifiedsrc/hUGEDriver +1−1
@@ -1 +1 @@
1 Subproject commit 3200c60c5eec5310105aa406a4e1cd1154875a37 1 Subproject commit a3c69884eea9f8a452c48fef7b724941950c2af7
Modifiedsrc/hUGETracker.lpi +3−0
@@ -185,6 +185,9 @@
185 </PublishOptions> 185 </PublishOptions>
186 <RunParams> 186 <RunParams>
187 <FormatVersion Value="2"/> 187 <FormatVersion Value="2"/>
188 <Modes Count="1">
189 <Mode0 Name="default"/>
190 </Modes>
188 </RunParams> 191 </RunParams>
189 <RequiredPackages Count="5"> 192 <RequiredPackages Count="5">
190 <Item1> 193 <Item1>
Modifiedsrc/song.pas +106−5
@@ -105,9 +105,30 @@ type
105 Routines: TRoutineBank; 105 Routines: TRoutineBank;
106 end; 106 end;
107 107
108 TSongV7 = packed record
109 Version: Integer;
110
111 Name: ShortString;
112 Artist: ShortString;
113 Comment: ShortString;
114
115 Instruments: TInstrumentCollection;
116 Waves: TWaveBank;
117
118 TicksPerRow: packed array[0..3] of Integer;
119
120 TimerEnabled: Boolean;
121 TimerDivider: Integer;
122
123 Patterns: TPatternMap;
124 OrderMatrix: TOrderMatrix;
125
126 Routines: TRoutineBank;
127 end;
128
108 { TSong } 129 { TSong }
109 130
110 TSong = TSongV6; 131 TSong = TSongV7;
111 132
112 procedure WriteSongToStream(S: TStream; const ASong: TSong); 133 procedure WriteSongToStream(S: TStream; const ASong: TSong);
113 procedure ReadSongFromStream(S: TStream; out ASong: TSong); 134 procedure ReadSongFromStream(S: TStream; out ASong: TSong);
@@ -119,7 +140,7 @@ function UpgradeSong(S: TSongV1): TSong; overload;
119 function UpgradeSong(S: TSongV2): TSong; overload; 140 function UpgradeSong(S: TSongV2): TSong; overload;
120 function UpgradeSong(S: TSongV3): TSong; overload; 141 function UpgradeSong(S: TSongV3): TSong; overload;
121 function UpgradeSong(S: TSongV4): TSong; overload; 142 function UpgradeSong(S: TSongV4): TSong; overload;
122 //function UpgradeSong(S: TSongV5): TSong; overload; 143 function UpgradeSong(S: TSongV6): TSong; overload;
123 144
124 function OptimizeSong(const S: TSong): TSong; 145 function OptimizeSong(const S: TSong): TSong;
125 146
@@ -373,6 +394,49 @@ begin
373 ASong.Routines[I] := S.ReadAnsiString; 394 ASong.Routines[I] := S.ReadAnsiString;
374 end; 395 end;
375 396
397 procedure ReadSongFromStreamV7(S: TStream; out ASong: TSongV7);
398 var
399 i, n, PatKey: Integer;
400 pat: PPattern;
401 begin
402 // Read the fixed elements first
403 n := SizeOf(TSongV7)
404 - SizeOf(TPatternMap)
405 - SizeOf(TOrderMatrix)
406 - SizeOf(TRoutineBank);
407
408 S.Read(ASong, n);
409
410 // Create the patterns
411 ASong.Patterns := TPatternMap.Create;
412 // Read the pattern count
413 S.Read(n, SizeOf(Integer));
414 for i:=0 to n - 1 do begin
415 // Read pattern key
416 S.Read(PatKey, SizeOf(Integer));
417 // Allocate memory for each pattern ...
418 New(pat);
419 // and read the pattern content
420 S.Read(pat^, SizeOf(TPattern));
421 // Add the pattern to the list
422 ASong.Patterns.Add(PatKey, pat);
423 end;
424
425 // Read the OrderMatrix
426 for i := 0 to 3 do
427 begin
428 // Read length of each OrderMatrix array
429 S.Read(n, SizeOf(Integer));
430 // Allocate memory for it
431 SetLength(ASong.OrderMatrix[i], n);
432 // Read content of OrderMatrix array
433 S.Read(ASong.OrderMatrix[i, 0], n*SizeOf(Integer));
434 end;
435
436 for I := Low(TRoutineBank) to High(TRoutineBank) do
437 ASong.Routines[I] := S.ReadAnsiString;
438 end;
439
376 procedure WriteSongToStream(S: TStream; const ASong: TSong); 440 procedure WriteSongToStream(S: TStream; const ASong: TSong);
377 var 441 var
378 i, n: Integer; 442 i, n: Integer;
@@ -414,6 +478,7 @@ var
414 SV3: TSongV3; 478 SV3: TSongV3;
415 SV4: TSongV4; 479 SV4: TSongV4;
416 SV5: TSongV5; 480 SV5: TSongV5;
481 SV6: TSongV6;
417 begin 482 begin
418 S.Read(Version, SizeOf(Integer)); 483 S.Read(Version, SizeOf(Integer));
419 S.Seek(0, soBeginning); 484 S.Seek(0, soBeginning);
@@ -439,8 +504,12 @@ begin
439 ASong := UpgradeSong(SV5); 504 ASong := UpgradeSong(SV5);
440 end; 505 end;
441 6: begin 506 6: begin
442 ReadSongFromStreamV6(S, ASong); 507 ReadSongFromStreamV6(S, SV6);
508 ASong := UpgradeSong(SV6);
443 end; 509 end;
510 7: begin
511 ReadSongFromStreamV7(S, ASong);
512 end
444 else begin 513 else begin
445 raise ESongVersionException.Create(IntToStr(Version)); 514 raise ESongVersionException.Create(IntToStr(Version));
446 end; 515 end;
@@ -515,7 +584,10 @@ begin
515 for I := Low(TRoutineBank) to High(TRoutineBank) do 584 for I := Low(TRoutineBank) to High(TRoutineBank) do
516 S.Routines[I] := ''; 585 S.Routines[I] := '';
517 586
518 S.TicksPerRow := 7; 587 S.TicksPerRow[0] := 7;
588 S.TicksPerRow[1] := 7;
589 S.TicksPerRow[2] := 7;
590 S.TicksPerRow[3] := 7;
519 S.TimerDivider := 0; 591 S.TimerDivider := 0;
520 S.TimerEnabled := False; 592 S.TimerEnabled := False;
521 S.Patterns := TPatternMap.Create; 593 S.Patterns := TPatternMap.Create;
@@ -809,7 +881,36 @@ begin
809 for I := 0 to S.Patterns.Count-1 do 881 for I := 0 to S.Patterns.Count-1 do
810 SV6.Patterns.Add(S.Patterns.Keys[I], ConvertPattern(S.Patterns.Data[I])); 882 SV6.Patterns.Add(S.Patterns.Keys[I], ConvertPattern(S.Patterns.Data[I]));
811 883
812 Result := SV6; 884 Result := UpgradeSong(SV6);
885 end;
886
887 function UpgradeSong(S: TSongV6): TSong;
888 var
889 SV7: TSongV7;
890 begin
891 SV7.Version := 7;
892
893 SV7.Name := S.Name;
894 SV7.Artist := S.Artist;
895 SV7.Comment := S.Comment;
896
897 SV7.Instruments := S.Instruments;
898 SV7.Waves := S.Waves;
899
900 SV7.TicksPerRow[0] := S.TicksPerRow;
901 SV7.TicksPerRow[1] := S.TicksPerRow;
902 SV7.TicksPerRow[2] := S.TicksPerRow;
903 SV7.TicksPerRow[3] := S.TicksPerRow;
904
905 SV7.TimerEnabled := S.TimerEnabled;
906 SV7.TimerDivider := S.TimerDivider;
907
908 SV7.Patterns := S.Patterns;
909 SV7.OrderMatrix := S.OrderMatrix;
910
911 SV7.Routines := S.Routines;
912
913 Result := SV7;
813 end; 914 end;
814 915
815 function OptimizeSong(const S: TSong): TSong; 916 function OptimizeSong(const S: TSong): TSong;
Modifiedsrc/tbmimport.pas +1−1
@@ -375,7 +375,7 @@ begin
375 // stoneface about it. 375 // stoneface about it.
376 Stream.ReadByte; 376 Stream.ReadByte;
377 377
378 Result.TicksPerRow := SongFormat.RowsPerBeat; 378 Result.TicksPerRow[0] := SongFormat.RowsPerBeat;
379 379
380 for I := Low(Result.OrderMatrix) to High(Result.OrderMatrix) do 380 for I := Low(Result.OrderMatrix) to High(Result.OrderMatrix) do
381 SetLength(Result.OrderMatrix[I], SongFormat.PatternCount+2); // off-by-one error on my part 381 SetLength(Result.OrderMatrix[I], SongFormat.PatternCount+2); // off-by-one error on my part
Modifiedsrc/tracker.pas +35−4
@@ -53,6 +53,9 @@ type
53 Splitter2: TSplitter; 53 Splitter2: TSplitter;
54 TBMOpenDialog: TOpenDialog; 54 TBMOpenDialog: TOpenDialog;
55 FUROpenDialog: TOpenDialog; 55 FUROpenDialog: TOpenDialog;
56 TicksPerRowSpinEdit1: TSpinEdit;
57 TicksPerRowSpinEdit2: TSpinEdit;
58 TicksPerRowSpinEdit3: TSpinEdit;
56 ToolButton11: TToolButton; 59 ToolButton11: TToolButton;
57 LoopSongToolButton: TToolButton; 60 LoopSongToolButton: TToolButton;
58 ToolButton12: TToolButton; 61 ToolButton12: TToolButton;
@@ -313,6 +316,9 @@ type
313 Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 316 Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
314 procedure RevertMenuItemClick(Sender: TObject); 317 procedure RevertMenuItemClick(Sender: TObject);
315 procedure SingleStepActionExecute(Sender: TObject); 318 procedure SingleStepActionExecute(Sender: TObject);
319 procedure TicksPerRowSpinEdit1Change(Sender: TObject);
320 procedure TicksPerRowSpinEdit2Change(Sender: TObject);
321 procedure TicksPerRowSpinEdit3Change(Sender: TObject);
316 procedure TimerDividerSpinEditChange(Sender: TObject); 322 procedure TimerDividerSpinEditChange(Sender: TObject);
317 procedure TimerEnabledCheckBoxChange(Sender: TObject); 323 procedure TimerEnabledCheckBoxChange(Sender: TObject);
318 procedure LoopSongToolButtonClick(Sender: TObject); 324 procedure LoopSongToolButtonClick(Sender: TObject);
@@ -603,7 +609,11 @@ begin
603 ArtistEdit.Text := Song.Artist; 609 ArtistEdit.Text := Song.Artist;
604 CommentMemo.Text := Song.Comment; 610 CommentMemo.Text := Song.Comment;
605 611
606 TicksPerRowSpinEdit.Value := Song.TicksPerRow; 612 TicksPerRowSpinEdit.Value := Song.TicksPerRow[0];
613 TicksPerRowSpinEdit1.Value := Song.TicksPerRow[1];
614 TicksPerRowSpinEdit2.Value := Song.TicksPerRow[2];
615 TicksPerRowSpinEdit3.Value := Song.TicksPerRow[3];
616
607 TimerDividerSpinEdit.Value := Song.TimerDivider; 617 TimerDividerSpinEdit.Value := Song.TimerDivider;
608 TimerEnabledCheckBox.Checked := Song.TimerEnabled; 618 TimerEnabledCheckBox.Checked := Song.TimerEnabled;
609 619
@@ -685,7 +695,7 @@ begin
685 else 695 else
686 TimerHZ := 59.727500569606; // VBlank hz 696 TimerHZ := 59.727500569606; // VBlank hz
687 697
688 BeatHZ := (TimerHZ / Song.TicksPerRow) / 4; // 4 rows comprise one beat 698 BeatHZ := (TimerHZ / Song.TicksPerRow[0]) / 4; // 4 rows comprise one beat
689 TempoBPMLabel.Caption := '~'+FormatFloat('###.##', BeatHZ * 60)+' BPM'; 699 TempoBPMLabel.Caption := '~'+FormatFloat('###.##', BeatHZ * 60)+' BPM';
690 end; 700 end;
691 701
@@ -1563,7 +1573,10 @@ begin
1563 CreateKeymap; 1573 CreateKeymap;
1564 1574
1565 // Initialize ticks per row 1575 // Initialize ticks per row
1566 Song.TicksPerRow := TicksPerRowSpinEdit.Value; 1576 Song.TicksPerRow[0] := TicksPerRowSpinEdit.Value;
1577 Song.TicksPerRow[1] := TicksPerRowSpinEdit1.Value;
1578 Song.TicksPerRow[2] := TicksPerRowSpinEdit2.Value;
1579 Song.TicksPerRow[3] := TicksPerRowSpinEdit3.Value;
1567 1580
1568 // Initialize order table (InitializeSong creates the default order table) 1581 // Initialize order table (InitializeSong creates the default order table)
1569 CopyOrderMatrixToOrderGrid; 1582 CopyOrderMatrixToOrderGrid;
@@ -2722,7 +2735,25 @@ end;
2722 2735
2723 procedure TfrmTracker.TicksPerRowSpinEditChange(Sender: TObject); 2736 procedure TfrmTracker.TicksPerRowSpinEditChange(Sender: TObject);
2724 begin 2737 begin
2725 Song.TicksPerRow := TicksPerRowSpinEdit.Value; 2738 Song.TicksPerRow[0] := TicksPerRowSpinEdit.Value;
2739 UpdateBPMLabel
2740 end;
2741
2742 procedure TfrmTracker.TicksPerRowSpinEdit1Change(Sender: TObject);
2743 begin
2744 Song.TicksPerRow[1] := TicksPerRowSpinEdit1.Value;
2745 UpdateBPMLabel
2746 end;
2747
2748 procedure TfrmTracker.TicksPerRowSpinEdit2Change(Sender: TObject);
2749 begin
2750 Song.TicksPerRow[2] := TicksPerRowSpinEdit2.Value;
2751 UpdateBPMLabel
2752 end;
2753
2754 procedure TfrmTracker.TicksPerRowSpinEdit3Change(Sender: TObject);
2755 begin
2756 Song.TicksPerRow[3] := TicksPerRowSpinEdit3.Value;
2726 UpdateBPMLabel 2757 UpdateBPMLabel
2727 end; 2758 end;
2728 2759