Commit ac4ea0a

Nick committed on
More work on playback, work on trackergrid
commit ac4ea0a66256b4594bf389b04145b34678caf9a8 parent ea66f3e
8 changed files +160−60
ModifiedCpu/z80cpu.pas +2−1
@@ -3185,7 +3185,8 @@ end;
3185 3185
3186 function PFX_FD: byte; 3186 function PFX_FD: byte;
3187 begin 3187 begin
3188 Writeln('[DEBUG] 0xFD Called, A = ', af.h); 3188 // Writeln('[DEBUG] 0xFD Called, A = ', af.h);
3189 if @FDCallback <> nil then FDCallback;
3189 Result := 0; 3190 Result := 0;
3190 end; 3191 end;
3191 3192
ModifiedGlobal/vars.pas +5−0
@@ -7,12 +7,17 @@ unit vars;
7 7
8 interface 8 interface
9 9
10 type
11 TFDCallback = procedure of object;
12
10 const 13 const
11 thr_f: integer = 1; 14 thr_f: integer = 1;
12 cart: pointer = nil; // Cartridge 15 cart: pointer = nil; // Cartridge
13 isddraw: boolean = True; // DirectDraw; 16 isddraw: boolean = True; // DirectDraw;
14 17
15 var 18 var
19 FDCallback: TFDCallback;
20
16 bdrop, dirname, dirload: string; 21 bdrop, dirname, dirload: string;
17 romname, speicher: string[128]; 22 romname, speicher: string[128];
18 buffer: array[0..1023] of char; 23 buffer: array[0..1023] of char;
Modifiedclipboardutils.pas +59−16
@@ -7,43 +7,86 @@ interface
7 uses 7 uses
8 Classes, SysUtils, Constants, Clipbrd, HugeDatatypes; 8 Classes, SysUtils, Constants, Clipbrd, HugeDatatypes;
9 9
10 type 10 {type
11 TModplugClipboardCell = packed record 11 TModplugClipboardCell = packed record
12 Pipe: Char;
13 Note: array[0..2] of Char; 12 Note: array[0..2] of Char;
14 Instrument: array[0..1] of Char; 13 Instrument: array[0..1] of Char;
15 Volume: array[0..2] of Char; 14 Volume: array[0..2] of Char;
16 EffectCode: Char; 15 EffectCode: Char;
17 EffectParams: array[0..1] of Char; 16 EffectParams: array[0..1] of Char;
18 end; 17 end;}
19 18
20 function ModplugToHuge(MPCell: TModplugClipboardCell): TCell; 19 // function ModplugToHuge(MPCell: TModplugClipboardCell): TCell;
20 function GetPastedCells: TSelection;
21 21
22 implementation 22 implementation
23 23
24 function ModplugToHuge(MPCell: TModplugClipboardCell): TCell; 24 {function ModplugToHuge(MPCell: TModplugClipboardCell): TCell;
25 begin 25 begin
26 Writeln(String(MPCell.Pipe));
27 Writeln(String(MPCell.Note));
28 Result.Note := NoteToCodeMap.KeyData[String(MPCell.Note)]; 26 Result.Note := NoteToCodeMap.KeyData[String(MPCell.Note)];
29 Result.Instrument := StrToInt(String(MPCell.Instrument)); 27 Result.Instrument := StrToInt(String(MPCell.Instrument));
30 Result.EffectCode := StrToInt(String('0x'+MPCell.EffectCode)); 28 Result.EffectCode := StrToInt(String('0x'+MPCell.EffectCode));
31 Result.EffectParams.Value := StrToInt(String('0x'+MPCell.EffectParams)); 29 Result.EffectParams.Value := StrToInt(String('0x'+MPCell.EffectParams));
30 end;}
31
32 function ParseCell(Cell: String): TCell;
33 var
34 Note, Instr, EffectCode, EffectParam1, EffectParam2: String;
35 Temp: Integer;
36 begin
37 Note := Cell.Substring(0, 3);
38 Instr := Cell.Substring(3, 2);
39 EffectCode := Cell.Substring(8, 1);
40 EffectParam1 := Cell.Substring(9, 1);
41 EffectParam2 := Cell.Substring(10, 1);
42
43 if not NoteToCodeMap.TryGetData(Note, Result.Note) then
44 Result.Note := NO_NOTE;
45
46 if not TryStrToInt(Instr, Result.Instrument) then
47 Result.Instrument := 0;
48
49 if not TryStrToInt('x'+EffectCode, Result.EffectCode) then
50 Result.EffectCode := 0;
51
52 if TryStrToInt('x'+EffectParam1, Temp) then
53 Result.EffectParams.Param1 := Temp
54 else
55 Result.EffectParams.Param1 := 0;
56
57 if TryStrToInt('x'+EffectParam2, Temp) then
58 Result.EffectParams.Param2 := Temp
59 else
60 Result.EffectParams.Param2 := 0;
32 end; 61 end;
33 62
34 function GetPastedCells: TSelection; 63 function GetPastedCells: TSelection;
35 var 64 var
36 C: TCell; 65 SL: TStringList;
37 X: TModplugClipboardCell; 66 StringCells: TStringArray;
38 ClipboardDynamicBytes: TBytes; 67 Row, Cell, S: String;
39 ClipboardBytes: array[0..sizeof(X)] of Byte absolute X; 68 I, J: Integer;
40 I: Integer;
41 begin 69 begin
42 ClipboardDynamicBytes := TEncoding.UTF8.GetBytes(Clipboard.AsText); 70 SL := TStringList.Create;
43 for I := 0 to sizeof(X) do 71 try
44 ClipboardBytes[I] := ClipboardDynamicBytes[I]; 72 SL.Text := Clipboard.AsText;
45 73
46 C := ModplugToHuge(X); 74 // First line is the header, last is a blank line
75 SL.Delete(0);
76 SetLength(Result, SL.Count);
77
78 I := 0;
79 for Row in SL do begin
80 StringCells := Row.Split('|');
81
82 SetLength(Result[I], Length(StringCells)-1);
83 for J := 0 to High(StringCells)-1 do
84 Result[I, J] := ParseCell(StringCells[J+1]);
85 Inc(I);
86 end;
87 finally
88 SL.Free;
89 end;
47 end; 90 end;
48 91
49 end. 92 end.
Modifiedconstants.pas +2−0
@@ -14,6 +14,8 @@ type
14 TNoteToFreqMap = specialize TFPGMap<Integer, Integer>; 14 TNoteToFreqMap = specialize TFPGMap<Integer, Integer>;
15 15
16 const 16 const
17 SYM_ROW = 'row';
18
17 // Sound controller registers 19 // Sound controller registers
18 NR10 = $FF10; 20 NR10 = $FF10;
19 NR11 = $FF11; 21 NR11 = $FF11;
Modifiedsymparser.pas +1−1
@@ -33,7 +33,7 @@ begin
33 33
34 for S in SL do begin 34 for S in SL do begin
35 SA := S.Split(' '); 35 SA := S.Split(' ');
36 Result.Add(SA[1], StrToInt('x'+LeftStr(SA[0], 3))); 36 Result.Add(SA[1], StrToInt('x'+SA[0].Substring(3)));
37 end; 37 end;
38 finally 38 finally
39 SL.Free; 39 SL.Free;
Modifiedtracker.lfm +7−13
@@ -1,7 +1,7 @@
1 object frmTracker: TfrmTracker 1 object frmTracker: TfrmTracker
2 Left = 806 2 Left = 791
3 Height = 1396 3 Height = 1396
4 Top = 188 4 Top = 460
5 Width = 2212 5 Width = 2212
6 Caption = 'hUGETracker' 6 Caption = 'hUGETracker'
7 ClientHeight = 1362 7 ClientHeight = 1362
@@ -1764,7 +1764,7 @@ object frmTracker: TfrmTracker
1764 ParentShowHint = False 1764 ParentShowHint = False
1765 end 1765 end
1766 object PanicToolButton: TToolButton 1766 object PanicToolButton: TToolButton
1767 Left = 487 1767 Left = 406
1768 Hint = 'Stops all sound output' 1768 Hint = 'Stops all sound output'
1769 Top = 0 1769 Top = 0
1770 AutoSize = True 1770 AutoSize = True
@@ -1781,21 +1781,15 @@ object frmTracker: TfrmTracker
1781 ImageIndex = 74 1781 ImageIndex = 74
1782 OnClick = ToolButton2Click 1782 OnClick = ToolButton2Click
1783 end 1783 end
1784 object ToolButton3: TToolButton
1785 Left = 189
1786 Top = 0
1787 Caption = 'Pause'
1788 ImageIndex = 75
1789 end
1790 object ToolButton4: TToolButton 1784 object ToolButton4: TToolButton
1791 Left = 270 1785 Left = 189
1792 Top = 0 1786 Top = 0
1793 Caption = 'Stop' 1787 Caption = 'Stop'
1794 ImageIndex = 73 1788 ImageIndex = 73
1795 OnClick = ToolButton4Click 1789 OnClick = ToolButton4Click
1796 end 1790 end
1797 object ToolButton5: TToolButton 1791 object ToolButton5: TToolButton
1798 Left = 343 1792 Left = 262
1799 Top = 0 1793 Top = 0
1800 AutoSize = True 1794 AutoSize = True
1801 Caption = 'Export song' 1795 Caption = 'Export song'
@@ -1810,14 +1804,14 @@ object frmTracker: TfrmTracker
1810 Style = tbsDivider 1804 Style = tbsDivider
1811 end 1805 end
1812 object ToolButton6: TToolButton 1806 object ToolButton6: TToolButton
1813 Left = 338 1807 Left = 257
1814 Height = 39 1808 Height = 39
1815 Top = 0 1809 Top = 0
1816 Caption = 'ToolButton6' 1810 Caption = 'ToolButton6'
1817 Style = tbsDivider 1811 Style = tbsDivider
1818 end 1812 end
1819 object ToolButton7: TToolButton 1813 object ToolButton7: TToolButton
1820 Left = 479 1814 Left = 398
1821 Height = 39 1815 Height = 39
1822 Top = 0 1816 Top = 0
1823 Caption = 'ToolButton7' 1817 Caption = 'ToolButton7'
Modifiedtracker.pas +31−11
@@ -67,7 +67,6 @@ type
67 ToolButton1: TToolButton; 67 ToolButton1: TToolButton;
68 PanicToolButton: TToolButton; 68 PanicToolButton: TToolButton;
69 ToolButton2: TToolButton; 69 ToolButton2: TToolButton;
70 ToolButton3: TToolButton;
71 ToolButton4: TToolButton; 70 ToolButton4: TToolButton;
72 ToolButton5: TToolButton; 71 ToolButton5: TToolButton;
73 ToolButton6: TToolButton; 72 ToolButton6: TToolButton;
@@ -231,6 +230,7 @@ type
231 230
232 PreviewingInstrument: Boolean; 231 PreviewingInstrument: Boolean;
233 DrawingWave: Boolean; 232 DrawingWave: Boolean;
233 Playing: Boolean;
234 234
235 PatternsNode, InstrumentsNode, WavesNode, RoutinesNode: TTreeNode; 235 PatternsNode, InstrumentsNode, WavesNode, RoutinesNode: TTreeNode;
236 236
@@ -245,6 +245,7 @@ type
245 procedure CopyOrderGridToOrderMatrix; 245 procedure CopyOrderGridToOrderMatrix;
246 function PeekSymbol(Symbol: String): Integer; 246 function PeekSymbol(Symbol: String): Integer;
247 procedure ResetEmulationThread; 247 procedure ResetEmulationThread;
248 procedure OnFD;
248 249
249 procedure UpdateUIAfterLoad; 250 procedure UpdateUIAfterLoad;
250 251
@@ -408,8 +409,13 @@ end;
408 409
409 procedure TfrmTracker.ResetEmulationThread; 410 procedure TfrmTracker.ResetEmulationThread;
410 begin 411 begin
412 Playing := False;
413
411 SymbolTable := nil; 414 SymbolTable := nil;
412 415
416 TrackerGrid.HighlightedRow := -1;
417 ToolButton2.ImageIndex := 74;
418
413 EmulationThread.Terminate; 419 EmulationThread.Terminate;
414 EmulationThread.WaitFor; 420 EmulationThread.WaitFor;
415 EmulationThread.Free; 421 EmulationThread.Free;
@@ -417,6 +423,11 @@ begin
417 EmulationThread.Start; 423 EmulationThread.Start;
418 end; 424 end;
419 425
426 procedure TfrmTracker.OnFD;
427 begin
428 TrackerGrid.HighlightedRow:=PeekSymbol(SYM_ROW);
429 end;
430
420 procedure TfrmTracker.LoadInstrument(Instr: Integer); 431 procedure TfrmTracker.LoadInstrument(Instr: Integer);
421 var 432 var
422 CI: ^TInstrument; 433 CI: ^TInstrument;
@@ -608,6 +619,8 @@ var
608 begin 619 begin
609 ReturnNilIfGrowHeapFails := False; 620 ReturnNilIfGrowHeapFails := False;
610 621
622 FDCallback := @Self.OnFD;
623
611 for I := Low(Song.Instruments) to High(Song.Instruments) do 624 for I := Low(Song.Instruments) to High(Song.Instruments) do
612 with Song.Instruments[I] do begin 625 with Song.Instruments[I] do begin
613 Type_ := Square; 626 Type_ := Square;
@@ -991,22 +1004,29 @@ end;
991 1004
992 procedure TfrmTracker.ToolButton2Click(Sender: TObject); 1005 procedure TfrmTracker.ToolButton2Click(Sender: TObject);
993 begin 1006 begin
994 if RenderPreviewROM(Song) then begin 1007 if not Playing then begin
995 // Load the new symbol table 1008 if RenderPreviewROM(Song) then begin
996 SymbolTable := ParseSymFile('hUGEDriver/preview.sym'); 1009 Playing := True;
997 1010 ToolButton2.ImageIndex := 75;
998 // Start emulation on the rendered preview binary 1011
999 EmulationThread.Terminate; 1012 // Load the new symbol table
1000 EmulationThread.WaitFor; 1013 SymbolTable := ParseSymFile('hUGEDriver/preview.sym');
1001 EmulationThread.Free; 1014
1002 EmulationThread := TEmulationThread.Create('hUGEDriver/preview.gb'); 1015 // Start emulation on the rendered preview binary
1003 EmulationThread.Start; 1016 EmulationThread.Terminate;
1017 EmulationThread.WaitFor;
1018 EmulationThread.Free;
1019 EmulationThread := TEmulationThread.Create('hUGEDriver/preview.gb');
1020 EmulationThread.Start;
1021 end
1022 else ResetEmulationThread;
1004 end 1023 end
1005 else ResetEmulationThread; 1024 else ResetEmulationThread;
1006 end; 1025 end;
1007 1026
1008 procedure TfrmTracker.ToolButton4Click(Sender: TObject); 1027 procedure TfrmTracker.ToolButton4Click(Sender: TObject);
1009 begin 1028 begin
1029 TrackerGrid.HighlightedRow := -1;
1010 ResetEmulationThread; 1030 ResetEmulationThread;
1011 end; 1031 end;
1012 1032
Modifiedtrackergrid.pas +53−18
@@ -6,7 +6,7 @@ interface
6 6
7 uses 7 uses
8 Classes, SysUtils, Controls, Graphics, Constants, LCLType, math, 8 Classes, SysUtils, Controls, Graphics, Constants, LCLType, math,
9 LCLIntf, LMessages, HugeDatatypes; 9 LCLIntf, LMessages, HugeDatatypes, ClipboardUtils;
10 10
11 // TODO: Maybe read these from a config file 11 // TODO: Maybe read these from a config file
12 const 12 const
@@ -20,6 +20,9 @@ const
20 clFxPan = clInstrument; 20 clFxPan = clInstrument;
21 clFxSong = TColor($00007F); 21 clFxSong = TColor($00007F);
22 22
23 clHighlighted = TColor($7A99A9);
24 clSelected = TColor($9EB4C0);
25
23 NUM_COLUMNS = 4; 26 NUM_COLUMNS = 4;
24 NUM_ROWS = 64; 27 NUM_ROWS = 64;
25 28
@@ -75,9 +78,13 @@ type
75 78
76 DigitInputting: Boolean; 79 DigitInputting: Boolean;
77 80
81 FHighlightedRow: Integer;
82
78 procedure RenderRow(Row: Integer); 83 procedure RenderRow(Row: Integer);
79 procedure RenderCell(const Cell: TCell); 84 procedure RenderCell(const Cell: TCell);
80 85
86 procedure SetHighlightedRow(Row: Integer);
87
81 function GetEffectColor(EffectCode: Integer): TColor; 88 function GetEffectColor(EffectCode: Integer): TColor;
82 function SelectionsToRect(S1, S2: TSelectionPos): TRect; 89 function SelectionsToRect(S1, S2: TSelectionPos): TRect;
83 function SelectionToRect(Selection: TSelectionPos): TRect; 90 function SelectionToRect(Selection: TSelectionPos): TRect;
@@ -87,6 +94,7 @@ type
87 public 94 public
88 Cursor, Other: TSelectionPos; 95 Cursor, Other: TSelectionPos;
89 ColumnWidth, RowHeight: Integer; 96 ColumnWidth, RowHeight: Integer;
97 property HighlightedRow: Integer read FHighlightedRow write SetHighlightedRow;
90 98
91 procedure LoadPattern(Idx: Integer; Pat: PPattern); 99 procedure LoadPattern(Idx: Integer; Pat: PPattern);
92 end; 100 end;
@@ -132,19 +140,16 @@ begin
132 Clear; 140 Clear;
133 141
134 for I := 0 to High(TPattern) do begin 142 for I := 0 to High(TPattern) do begin
135 if (I mod 4) = 0 then begin 143 if (I mod 4) = 0 then
136 Brush.Color := RGBToColor(216, 209, 195); 144 Brush.Color := RGBToColor(216, 209, 195);
137 FillRect(0, I*RowHeight, Width, (I+1)*RowHeight); 145 if (I mod 16) = 0 then
138 end;
139 if (I mod 16) = 0 then begin
140 Brush.Color := RGBToColor(206, 197, 181); 146 Brush.Color := RGBToColor(206, 197, 181);
141 FillRect(0, I*RowHeight, Width, (I+1)*RowHeight); 147 if I = Cursor.Y then
142 end; 148 Brush.Color := clSelected;
143 if I = Cursor.Y then begin 149 if I = FHighlightedRow then
144 Brush.Color := RGBToColor(169, 153, 122); 150 Brush.Color := clHighlighted;
145 FillRect(0, I*RowHeight, Width, (I+1)*RowHeight);
146 end;
147 151
152 FillRect(0, I*RowHeight, Width, (I+1)*RowHeight);
148 MoveTo(0, I*RowHeight); 153 MoveTo(0, I*RowHeight);
149 RenderRow(I); 154 RenderRow(I);
150 end; 155 end;
@@ -240,13 +245,14 @@ begin
240 DigitInputting := False; 245 DigitInputting := False;
241 end; 246 end;
242 else begin 247 else begin
243 case Cursor.SelectedPart of 248 if not (ssCtrl in Shift) then
244 cpNote: InputNote(Key); 249 case Cursor.SelectedPart of
245 cpInstrument: InputInstrument(Key); 250 cpNote: InputNote(Key);
246 cpVolume: InputVolume(Key); 251 cpInstrument: InputInstrument(Key);
247 cpEffectCode: InputEffectCode(Key); 252 cpVolume: InputVolume(Key);
248 cpEffectParams: InputEffectParams(Key); 253 cpEffectCode: InputEffectCode(Key);
249 end; 254 cpEffectParams: InputEffectParams(Key);
255 end;
250 end; 256 end;
251 end; 257 end;
252 258
@@ -260,15 +266,38 @@ begin
260 end; 266 end;
261 267
262 procedure TTrackerGrid.DoPaste(var Msg: TLMessage); 268 procedure TTrackerGrid.DoPaste(var Msg: TLMessage);
269 var
270 Paste: TSelection;
271 X, Y: Integer;
263 begin 272 begin
273 try
274 Paste := GetPastedCells;
275 for Y := 0 to High(Paste) do begin
276 if Cursor.Y+Y > High(TPattern) then Break;
277 for X := 0 to High(Paste[Y]) do begin
278 if Cursor.X+X > High(Patterns) then Break;
279 Patterns[Cursor.X + X]^[Cursor.Y + Y] := Paste[Y, X];
280 end;
281 end;
282 Other.X := Cursor.X + X;
283 Other.Y := Cursor.Y + Y;
284 Other.SelectedPart := High(TCellPart);
285 except
286 on E: Exception do
287 WriteLn(StdErr, 'Clipboard did not contain valid note data!');
288 end;
289
290 Invalidate;
264 end; 291 end;
265 292
266 procedure TTrackerGrid.DoCopy(var Msg: TLMessage); 293 procedure TTrackerGrid.DoCopy(var Msg: TLMessage);
267 begin 294 begin
295
268 end; 296 end;
269 297
270 procedure TTrackerGrid.DoCut(var Msg: TLMessage); 298 procedure TTrackerGrid.DoCut(var Msg: TLMessage);
271 begin 299 begin
300
272 end; 301 end;
273 302
274 procedure TTrackerGrid.RenderSelectedArea; 303 procedure TTrackerGrid.RenderSelectedArea;
@@ -419,6 +448,12 @@ begin
419 end; 448 end;
420 end; 449 end;
421 450
451 procedure TTrackerGrid.SetHighlightedRow(Row: Integer);
452 begin
453 FHighlightedRow := Row;
454 if FHighlightedRow >= 0 then Invalidate;
455 end;
456
422 function TTrackerGrid.GetEffectColor(EffectCode: Integer): TColor; 457 function TTrackerGrid.GetEffectColor(EffectCode: Integer): TColor;
423 begin 458 begin
424 Result := clBlack; 459 Result := clBlack;