@@ -1,6 +1,6 @@ |
| 1 |
unit Tracker; |
1 |
unit Tracker; |
| 2 |
|
2 |
|
| 3 |
{$mode objfpc} |
3 |
{$mode objfpc}{$H+} |
| 4 |
|
4 |
|
| 5 |
interface |
5 |
interface |
| 6 |
|
6 |
|
@@ -9,7 +9,7 @@ uses |
| 9 |
Menus, Spin, StdCtrls, ActnList, StdActns, SynEdit, math, Instruments, Waves, |
9 |
Menus, Spin, StdCtrls, ActnList, StdActns, SynEdit, math, Instruments, Waves, |
| 10 |
Song, EmulationThread, Utils, Constants, sound, vars, machine, |
10 |
Song, EmulationThread, Utils, Constants, sound, vars, machine, |
| 11 |
about_hugetracker, TrackerGrid, lclintf, lmessages, Buttons, Grids, DBCtrls, |
11 |
about_hugetracker, TrackerGrid, lclintf, lmessages, Buttons, Grids, DBCtrls, |
| 12 |
ECProgressBar, HugeDatatypes, LCLType, Codegen; |
12 |
ECProgressBar, HugeDatatypes, LCLType, Codegen, SymParser; |
| 13 |
|
13 |
|
| 14 |
type |
14 |
type |
| 15 |
{ TfrmTracker } |
15 |
{ TfrmTracker } |
@@ -156,6 +156,8 @@ type |
| 156 |
Shift: TShiftState; X, Y: Integer); |
156 |
Shift: TShiftState; X, Y: Integer); |
| 157 |
procedure HeaderControl1SectionClick(HeaderControl: TCustomHeaderControl; |
157 |
procedure HeaderControl1SectionClick(HeaderControl: TCustomHeaderControl; |
| 158 |
Section: THeaderSection); |
158 |
Section: THeaderSection); |
|
|
159 |
procedure HeaderControl1SectionResize(HeaderControl: TCustomHeaderControl; |
|
|
160 |
Section: THeaderSection); |
| 159 |
procedure HelpLookupManualExecute(Sender: TObject); |
161 |
procedure HelpLookupManualExecute(Sender: TObject); |
| 160 |
procedure ArtistEditChange(Sender: TObject); |
162 |
procedure ArtistEditChange(Sender: TObject); |
| 161 |
procedure CommentMemoChange(Sender: TObject); |
163 |
procedure CommentMemoChange(Sender: TObject); |
@@ -196,6 +198,8 @@ type |
| 196 |
procedure PanicToolButtonClick(Sender: TObject); |
198 |
procedure PanicToolButtonClick(Sender: TObject); |
| 197 |
procedure PasteActionExecute(Sender: TObject); |
199 |
procedure PasteActionExecute(Sender: TObject); |
| 198 |
procedure TicksPerRowSpinEditChange(Sender: TObject); |
200 |
procedure TicksPerRowSpinEditChange(Sender: TObject); |
|
|
201 |
procedure ToolButton2Click(Sender: TObject); |
|
|
202 |
procedure ToolButton4Click(Sender: TObject); |
| 199 |
procedure ToolButton5Click(Sender: TObject); |
203 |
procedure ToolButton5Click(Sender: TObject); |
| 200 |
procedure WaveEditNumberSpinnerChange(Sender: TObject); |
204 |
procedure WaveEditNumberSpinnerChange(Sender: TObject); |
| 201 |
procedure WaveEditPaintBoxMouseDown(Sender: TObject; Button: TMouseButton; |
205 |
procedure WaveEditPaintBoxMouseDown(Sender: TObject; Button: TMouseButton; |
@@ -228,16 +232,19 @@ type |
| 228 |
PreviewingInstrument: Boolean; |
232 |
PreviewingInstrument: Boolean; |
| 229 |
DrawingWave: Boolean; |
233 |
DrawingWave: Boolean; |
| 230 |
|
234 |
|
| 231 |
Patterns: TPatternMap; |
|
|
| 232 |
|
|
|
| 233 |
PatternsNode, InstrumentsNode, WavesNode, RoutinesNode: TTreeNode; |
235 |
PatternsNode, InstrumentsNode, WavesNode, RoutinesNode: TTreeNode; |
| 234 |
|
236 |
|
|
|
237 |
SymbolTable: TSymbolMap; |
|
|
238 |
|
| 235 |
procedure ChangeToSquare; |
239 |
procedure ChangeToSquare; |
| 236 |
procedure ChangeToWave; |
240 |
procedure ChangeToWave; |
| 237 |
procedure ChangeToNoise; |
241 |
procedure ChangeToNoise; |
| 238 |
procedure LoadInstrument(Instr: Integer); |
242 |
procedure LoadInstrument(Instr: Integer); |
| 239 |
procedure LoadWave(Wave: Integer); |
243 |
procedure LoadWave(Wave: Integer); |
| 240 |
procedure ReloadPatterns; |
244 |
procedure ReloadPatterns; |
|
|
245 |
procedure CopyOrderGridToOrderMatrix; |
|
|
246 |
function PeekSymbol(Symbol: String): Integer; |
|
|
247 |
procedure ResetEmulationThread; |
| 241 |
|
248 |
|
| 242 |
procedure UpdateUIAfterLoad; |
249 |
procedure UpdateUIAfterLoad; |
| 243 |
|
250 |
|
@@ -368,9 +375,46 @@ begin |
| 368 |
OrderEditStringGrid.Cells[I+1, OrderEditStringGrid.Row], |
375 |
OrderEditStringGrid.Cells[I+1, OrderEditStringGrid.Row], |
| 369 |
OrderNum |
376 |
OrderNum |
| 370 |
); |
377 |
); |
| 371 |
Pat := Patterns.GetOrCreateNew(OrderNum); |
378 |
Pat := Song.Patterns.GetOrCreateNew(OrderNum); |
| 372 |
TrackerGrid.LoadPattern(I, Pat); |
379 |
TrackerGrid.LoadPattern(I, Pat); |
| 373 |
end; |
380 |
end; |
|
|
381 |
|
|
|
382 |
CopyOrderGridToOrderMatrix; |
|
|
383 |
end; |
|
|
384 |
|
|
|
385 |
procedure TfrmTracker.CopyOrderGridToOrderMatrix; |
|
|
386 |
var |
|
|
387 |
C, R, OrderNum: Integer; |
|
|
388 |
begin |
|
|
389 |
// Copy the data in the grid to the song's order matrix. Not super efficient |
|
|
390 |
// but it's fast enough |
|
|
391 |
with OrderEditStringGrid do begin |
|
|
392 |
for C := 0 to 3 do begin |
|
|
393 |
SetLength(Song.OrderMatrix[C], RowCount); |
|
|
394 |
for R := 0 to RowCount-2 do begin |
|
|
395 |
OrderNum := 0; |
|
|
396 |
TryStrToInt(Cells[C+1, R+1], OrderNum); |
|
|
397 |
Song.OrderMatrix[C, R] := OrderNum; |
|
|
398 |
end; |
|
|
399 |
end; |
|
|
400 |
end; |
|
|
401 |
end; |
|
|
402 |
|
|
|
403 |
function TfrmTracker.PeekSymbol(Symbol: String): Integer; |
|
|
404 |
begin |
|
|
405 |
if SymbolTable = nil then exit; |
|
|
406 |
Result := speekb(SymbolTable.KeyData[Symbol]); |
|
|
407 |
end; |
|
|
408 |
|
|
|
409 |
procedure TfrmTracker.ResetEmulationThread; |
|
|
410 |
begin |
|
|
411 |
SymbolTable := nil; |
|
|
412 |
|
|
|
413 |
EmulationThread.Terminate; |
|
|
414 |
EmulationThread.WaitFor; |
|
|
415 |
EmulationThread.Free; |
|
|
416 |
EmulationThread := TEmulationThread.Create('halt.gb'); |
|
|
417 |
EmulationThread.Start; |
| 374 |
end; |
418 |
end; |
| 375 |
|
419 |
|
| 376 |
procedure TfrmTracker.LoadInstrument(Instr: Integer); |
420 |
procedure TfrmTracker.LoadInstrument(Instr: Integer); |
@@ -603,17 +647,18 @@ begin |
| 603 |
(Section as THeaderSection).Width := TrackerGrid.ColumnWidth; |
647 |
(Section as THeaderSection).Width := TrackerGrid.ColumnWidth; |
| 604 |
|
648 |
|
| 605 |
// Initialize order table |
649 |
// Initialize order table |
| 606 |
Patterns := TPatternMap.Create; |
650 |
Song.Patterns := TPatternMap.Create; |
| 607 |
for I := 0 to 3 do begin |
651 |
for I := 0 to 3 do begin |
| 608 |
OrderEditStringGrid.Cells[I+1, 1] := IntToStr(I); |
652 |
OrderEditStringGrid.Cells[I+1, 1] := IntToStr(I); |
| 609 |
TrackerGrid.LoadPattern(I, Patterns.GetOrCreateNew(I)); |
653 |
TrackerGrid.LoadPattern(I, Song.Patterns.GetOrCreateNew(I)); |
| 610 |
end; |
654 |
end; |
|
|
655 |
CopyOrderGridToOrderMatrix; |
| 611 |
|
656 |
|
| 612 |
// Manually resize the fixed column in the order editor |
657 |
// Manually resize the fixed column in the order editor |
| 613 |
OrderEditStringGrid.ColWidths[0]:=50; |
658 |
OrderEditStringGrid.ColWidths[0]:=50; |
| 614 |
|
659 |
|
| 615 |
// Get the emulator ready to make sound... |
660 |
// Get the emulator ready to make sound... |
| 616 |
EmulationThread := TEmulationThread.Create; |
661 |
EmulationThread := TEmulationThread.Create('halt.gb'); |
| 617 |
EmulationThread.Start; |
662 |
EmulationThread.Start; |
| 618 |
end; |
663 |
end; |
| 619 |
|
664 |
|
@@ -715,6 +760,14 @@ begin |
| 715 |
Section.ImageIndex := (Section.ImageIndex + 1) mod 2; |
760 |
Section.ImageIndex := (Section.ImageIndex + 1) mod 2; |
| 716 |
end; |
761 |
end; |
| 717 |
|
762 |
|
|
|
763 |
procedure TfrmTracker.HeaderControl1SectionResize( |
|
|
764 |
HeaderControl: TCustomHeaderControl; Section: THeaderSection); |
|
|
765 |
begin |
|
|
766 |
// Prevent resizing these |
|
|
767 |
// TODO: Create a subclass of them that doesn't allow resizing maybe? |
|
|
768 |
Section.Width := TrackerGrid.ColumnWidth; |
|
|
769 |
end; |
|
|
770 |
|
| 718 |
procedure TfrmTracker.FileOpen1Accept(Sender: TObject); |
771 |
procedure TfrmTracker.FileOpen1Accept(Sender: TObject); |
| 719 |
{var |
772 |
{var |
| 720 |
F: file of TSong;} |
773 |
F: file of TSong;} |
@@ -805,7 +858,7 @@ procedure TfrmTracker.MenuItem17Click(Sender: TObject); |
| 805 |
var |
858 |
var |
| 806 |
X, Highest: Integer; |
859 |
X, Highest: Integer; |
| 807 |
begin |
860 |
begin |
| 808 |
Highest := Patterns.MaxKey; |
861 |
Highest := Song.Patterns.MaxKey; |
| 809 |
|
862 |
|
| 810 |
with OrderEditStringGrid do |
863 |
with OrderEditStringGrid do |
| 811 |
InsertRowWithValues( |
864 |
InsertRowWithValues( |
@@ -818,7 +871,7 @@ begin |
| 818 |
); |
871 |
); |
| 819 |
|
872 |
|
| 820 |
for X := 0 to 3 do |
873 |
for X := 0 to 3 do |
| 821 |
Patterns.CreateNewPattern(Highest+X); |
874 |
Song.Patterns.CreateNewPattern(Highest+X); |
| 822 |
end; |
875 |
end; |
| 823 |
|
876 |
|
| 824 |
procedure TfrmTracker.MenuItem18Click(Sender: TObject); |
877 |
procedure TfrmTracker.MenuItem18Click(Sender: TObject); |
@@ -880,24 +933,27 @@ procedure TfrmTracker.OrderEditStringGridDblClick(Sender: TObject); |
| 880 |
var |
933 |
var |
| 881 |
Highest: Integer; |
934 |
Highest: Integer; |
| 882 |
begin |
935 |
begin |
| 883 |
Highest := Patterns.MaxKey; |
936 |
Highest := Song.Patterns.MaxKey; |
| 884 |
|
937 |
|
| 885 |
with OrderEditStringGrid do begin |
938 |
with OrderEditStringGrid do begin |
| 886 |
Cells[Col, Row] := IntToStr(Highest); |
939 |
Cells[Col, Row] := IntToStr(Highest); |
| 887 |
TrackerGrid.LoadPattern(Col - 1, Patterns.GetOrCreateNew(Highest)); |
940 |
TrackerGrid.LoadPattern(Col - 1, Song.Patterns.GetOrCreateNew(Highest)); |
| 888 |
end; |
941 |
end; |
| 889 |
end; |
942 |
end; |
| 890 |
|
943 |
|
| 891 |
procedure TfrmTracker.OrderEditStringGridEditingDone(Sender: TObject); |
944 |
procedure TfrmTracker.OrderEditStringGridEditingDone(Sender: TObject); |
| 892 |
var |
945 |
var |
| 893 |
Temp: Integer; |
946 |
Temp: Integer; |
|
|
947 |
R, C: Integer; |
| 894 |
begin |
948 |
begin |
| 895 |
// TODO: Fix this hack! |
949 |
// TODO: Fix this hack! |
| 896 |
// For some reason OnValidateEntry is giving bad pointers |
950 |
// For some reason OnValidateEntry is giving bad pointers |
| 897 |
// for its NewValue and OldValue params. This is the workaround for now. |
951 |
// for its NewValue and OldValue params. This is the workaround for now. |
| 898 |
with OrderEditStringGrid do |
952 |
with OrderEditStringGrid do begin |
| 899 |
if not TryStrToInt(Cells[Col, Row], Temp) then Cells[Col, Row] := ''; |
953 |
if not TryStrToInt(Cells[Col, Row], Temp) then |
| 900 |
|
954 |
Cells[Col, Row] := '' |
|
|
955 |
else; |
|
|
956 |
end; |
| 901 |
ReloadPatterns; |
957 |
ReloadPatterns; |
| 902 |
end; |
958 |
end; |
| 903 |
|
959 |
|
@@ -933,6 +989,27 @@ begin |
| 933 |
Song.TicksPerRow := TicksPerRowSpinEdit.Value; |
989 |
Song.TicksPerRow := TicksPerRowSpinEdit.Value; |
| 934 |
end; |
990 |
end; |
| 935 |
|
991 |
|
|
|
992 |
procedure TfrmTracker.ToolButton2Click(Sender: TObject); |
|
|
993 |
begin |
|
|
994 |
if RenderPreviewROM(Song) then begin |
|
|
995 |
// Load the new symbol table |
|
|
996 |
SymbolTable := ParseSymFile('hUGEDriver/preview.sym'); |
|
|
997 |
|
|
|
998 |
// Start emulation on the rendered preview binary |
|
|
999 |
EmulationThread.Terminate; |
|
|
1000 |
EmulationThread.WaitFor; |
|
|
1001 |
EmulationThread.Free; |
|
|
1002 |
EmulationThread := TEmulationThread.Create('hUGEDriver/preview.gb'); |
|
|
1003 |
EmulationThread.Start; |
|
|
1004 |
end |
|
|
1005 |
else ResetEmulationThread; |
|
|
1006 |
end; |
|
|
1007 |
|
|
|
1008 |
procedure TfrmTracker.ToolButton4Click(Sender: TObject); |
|
|
1009 |
begin |
|
|
1010 |
ResetEmulationThread; |
|
|
1011 |
end; |
|
|
1012 |
|
| 936 |
procedure TfrmTracker.ToolButton5Click(Sender: TObject); |
1013 |
procedure TfrmTracker.ToolButton5Click(Sender: TObject); |
| 937 |
begin |
1014 |
begin |
| 938 |
if SaveDialog1.Execute then begin |
1015 |
if SaveDialog1.Execute then begin |