Commit 33b0eb0

Nick committed on
Initial crack at codegen
commit 33b0eb0ae72cec4cb0d7366b7be783ba9addfb53 parent 37e79e4
7 changed files +457−295
Modifiedcodegen.pas +73−19
@@ -1,18 +1,23 @@
1 unit Codegen; 1 unit Codegen;
2 2
3 {$mode objfpc} 3 {$mode objfpc}{$H+}
4 4
5 interface 5 interface
6 6
7 uses 7 uses
8 Classes, SysUtils, math, 8 Classes, SysUtils, math,
9 Waves, Instruments, 9 Waves, Instruments, Song,
10 HugeDatatypes; 10 HugeDatatypes;
11 11
12 function RenderOrderTable(OrderMatrix: TOrderMatrix): String; 12 function RenderOrderTable(OrderMatrix: TOrderMatrix): String;
13 function RenderInstrument(Name: String; Instr: TInstrument): String; 13
14 function RenderInstruments(Instruments: TInstrumentBank): String;
15
14 function RenderPattern(Name: String; Pattern: TPattern): String; 16 function RenderPattern(Name: String; Pattern: TPattern): String;
15 function RenderWaveform(Name: String; Wave: TWave): String; 17
18 function RenderWaveforms(Waves: TWaveBank): String;
19
20 procedure RenderSongToFile(Song: TSong; Filename: String);
16 21
17 //TODO: RenderRoutines 22 //TODO: RenderRoutines
18 23
@@ -27,15 +32,18 @@ var
27 function ArrayHelper(Ints: array of Integer): String; 32 function ArrayHelper(Ints: array of Integer): String;
28 var 33 var
29 I: Integer; 34 I: Integer;
30 Strs: array of string; 35 SL: TStringList;
31 begin 36 begin
37 SL := TStringList.Create;
38 SL.Delimiter := ',';
32 for I := Low(Ints) to High(Ints) do 39 for I := Low(Ints) to High(Ints) do
33 Strs[I] := 'o' + IntToStr(Ints[I]); 40 SL.Add('o' + IntToStr(Ints[I]));
34 Result := TStringHelper.Join(',', Strs); 41 Result := SL.DelimitedText;
42 SL.Free;
35 end; 43 end;
36 begin 44 begin
37 Res := TStringList.Create; 45 Res := TStringList.Create;
38 Res.Delimiter := LineEnding; 46 Res.Delimiter := #10;
39 OrderCnt := maxvalue([High(OrderMatrix[0]), High(OrderMatrix[1]), 47 OrderCnt := maxvalue([High(OrderMatrix[0]), High(OrderMatrix[1]),
40 High(OrderMatrix[2]), High(OrderMatrix[3])]); 48 High(OrderMatrix[2]), High(OrderMatrix[3])]);
41 49
@@ -49,11 +57,29 @@ begin
49 Res.Free; 57 Res.Free;
50 end; 58 end;
51 59
52 function RenderInstrument(Name: String; Instr: TInstrument): String; 60 function RenderInstruments(Instruments: TInstrumentBank): String;
53 var 61 var
54 SL: TStringList; 62 SL, ResultSL: TStringList;
63 AsmInstrument: TAsmInstrument;
64 I, J: Integer;
55 begin 65 begin
66 ResultSL := TStringList.Create;
67 ResultSL.Delimiter := #10;
68
69 for I := Low(Instruments) to High(Instruments) do begin
70 AsmInstrument := InstrumentToBytes(Instruments[I]);
71 SL := TStringList.Create;
72 SL.Delimiter := ',';
73
74 for J := Low(AsmInstrument) to High(AsmInstrument) do
75 SL.Add(IntToStr(AsmInstrument[J]));
56 76
77 ResultSL.Add(Format('%s: db %s', ['inst'+IntToStr(I), SL.DelimitedText]));
78 SL.Free;
79 end;
80
81 Result := ResultSL.DelimitedText;
82 ResultSL.Free;
57 end; 83 end;
58 84
59 function RenderPattern(Name: String; Pattern: TPattern): String; 85 function RenderPattern(Name: String; Pattern: TPattern): String;
@@ -61,17 +87,45 @@ begin
61 87
62 end; 88 end;
63 89
64 function RenderWaveform(Name: String; Wave: TWave): String; 90 function RenderWaveforms(Waves: TWaveBank): String;
65 var 91 var
66 SL: TStringList; 92 SL, ResultSL: TStringList;
67 I: Integer; 93 I, J: Integer;
68 begin 94 begin
69 SL := TStringList.Create; 95 ResultSL := TStringList.Create;
70 SL.Delimiter := ', '; 96 ResultSL.Delimiter := #10;
71 for I := Low(Wave) to High(Wave) do 97
72 SL.Add(IntToStr(Wave[I])); 98 for I := Low(Waves) to High(Waves) do begin
73 Result := Name + SL.DelimitedText; 99 SL := TStringList.Create;
74 SL.Free; 100 SL.Delimiter := ',';
101 for J := Low(Waves[I]) to High(Waves[I]) do
102 SL.Add(IntToStr(Waves[I][J]));
103 Result := Format('wave%d: db %s', [I, SL.DelimitedText]);
104 SL.Free;
105 end;
106
107 Result := ResultSL.DelimitedText;
108 ResultSL.Free;
109 end;
110
111 procedure RenderSongToFile(Song: TSong; Filename: String);
112 var
113 OutFile: Text;
114 begin
115 Assign(OutFile, 'C:/test/wave');
116 Rewrite(OutFile);
117 Write(OutFile, RenderWaveforms(Song.Waves));
118 Close(OutFile);
119
120 {Assign(OutFile, 'C:/test/order');
121 Rewrite(OutFile);
122 Write(RenderOrderTable(Song.Waves));
123 Close(OutFile);}
124
125 Assign(OutFile, 'C:/test/instrument');
126 Rewrite(OutFile);
127 Write(OutFile, RenderInstruments(Song.Instruments));
128 Close(OutFile);
75 end; 129 end;
76 130
77 end. 131 end.
Modifiedhugedatatypes.pas +4−1
@@ -5,9 +5,12 @@ unit HugeDatatypes;
5 interface 5 interface
6 6
7 uses 7 uses
8 Classes, SysUtils, fgl; 8 Classes, SysUtils, fgl, instruments, waves;
9 9
10 type 10 type
11 TInstrumentBank = array[1..15] of TInstrument;
12 TWaveBank = array[0..15] of TWave;
13
11 TEffectParams = packed record 14 TEffectParams = packed record
12 case Boolean of 15 case Boolean of
13 True: (Param1, Param2: Byte); 16 True: (Param1, Param2: Byte);
Modifiedinstruments.pas +277−0
@@ -50,7 +50,284 @@ type
50 DividingRatio: Integer; 50 DividingRatio: Integer;
51 end; 51 end;
52 52
53 TAsmInstrument = array[0..3] of Byte;
54
55 TRegisters = record
56 case Type_: TInstrumentType of
57 Square: (NR10, NR11, NR12, NR13, NR14: Byte);
58 Wave: (NR30, NR31, NR32, NR33, NR34: Byte);
59 Noise: (NR41, NR42, NR43, NR44: Byte);
60 end;
61
62 Bit = Boolean;
63 TwoBits = 0..3;
64 ThreeBits = 0..7;
65 FourBits = 0..17;
66 FiveBits = 0..31;
67 SixBits = 0..63;
68 SevenBits = 0..127;
69 EightBits = Byte;
70
71 TSweepRegister = bitpacked record
72 case Boolean of
73 True: (
74 Shift: ThreeBits;
75 IncDec: Bit;
76 SweepTime: ThreeBits;
77 _: Bit;
78 );
79 False: (ByteValue: Byte);
80 end;
81
82 TSquareLengthRegister = bitpacked record
83 case Boolean of
84 True: (
85 Length: SixBits;
86 Duty: TwoBits;
87 );
88 False: (ByteValue: Byte);
89 end;
90
91 TEnvelopeRegister = bitpacked record
92 case Boolean of
93 True: (
94 SweepNumber: ThreeBits;
95 Direction: Bit;
96 InitialVolume: FourBits;
97 );
98 False: (ByteValue: Byte);
99 end;
100
101 TLowByteRegister = Byte;
102
103 THighByteRegister = bitpacked record
104 case Boolean of
105 True: (
106 FrequencyBits: ThreeBits;
107 _Padding: ThreeBits;
108 UseLength: Bit;
109 Initial: Bit;
110 );
111 False: (ByteValue: Byte);
112 end;
113
114 TCh3SoundOnOffRegister = bitpacked record
115 case Boolean of
116 True: (
117 _Padding: SevenBits;
118 Playback: Bit;
119 );
120 False: (ByteValue: Byte);
121 end;
122
123 TCh3SoundLengthRegister = Byte;
124
125 TCh3OutputLevelRegister = bitpacked record
126 case Boolean of
127 True: (
128 _Padding: FiveBits;
129 OutputLevel: TwoBits;
130 _Padding2: Bit;
131 );
132 False: (ByteValue: Byte);
133 end;
134
135 TCh4SoundLengthRegister = 0..63;
136
137 TPolynomialCounterRegister = bitpacked record
138 case Boolean of
139 True: (
140 DividingRatio: ThreeBits;
141 SevenBitCounter: Bit;
142 ShiftClockFrequency: FourBits;
143 );
144 False: (ByteValue: Byte);
145 end;
146
147 TCh4HighByteRegister = bitpacked record
148 case Boolean of
149 True: (
150 _Padding: SixBits;
151 UseLength: Bit;
152 Initial: Bit;
153 );
154 False: (ByteValue: Byte);
155 end;
156
157 function NoiseInstrumentToRegisters(
158 Initial: Boolean;
159 Instr: TInstrument): TRegisters;
160
161 function SquareInstrumentToRegisters(
162 Frequency: Word;
163 Initial: Boolean;
164 Instr: TInstrument): TRegisters;
165
166 function WaveInstrumentToRegisters(
167 Frequency: Word;
168 Initial: Boolean;
169 Instr: TInstrument): TRegisters;
170
171 function InstrumentToBytes(Instrument: TInstrument): TAsmInstrument;
172
53 implementation 173 implementation
54 174
175 function SquareInstrumentToBytes(Instrument: TInstrument): TAsmInstrument;
176 var
177 Regs: TRegisters;
178 begin
179 Regs := SquareInstrumentToRegisters(0, True, Instrument);
180 Result[0] := Regs.NR10;
181 Result[1] := Regs.NR11;
182 Result[2] := Regs.NR12;
183 Result[3] := Regs.NR14
184 end;
185
186 function WaveInstrumentToBytes(Instrument: TInstrument): TAsmInstrument;
187 var
188 Regs: TRegisters;
189 begin
190 Regs := WaveInstrumentToRegisters(0, True, Instrument);
191 Result[0] :=Regs.NR31;
192 Result[1] :=Regs.NR32;
193 Result[2] :=Instrument.Waveform;
194 Result[3] :=Regs.NR34
195 end;
196
197 function NoiseInstrumentToBytes(Instrument: TInstrument): TAsmInstrument;
198 var
199 Regs: TRegisters;
200 begin
201 Regs := NoiseInstrumentToRegisters(True, Instrument);
202 Result[0] :=Regs.NR41;
203 Result[1] :=Regs.NR42;
204 Result[2] :=Regs.NR43;
205 Result[3] :=Regs.NR44
206 end;
207
208 function InstrumentToBytes(Instrument: TInstrument): TAsmInstrument;
209 begin
210 case Instrument.Type_ of
211 Square: Result := SquareInstrumentToBytes(Instrument);
212 Wave: Result := WaveInstrumentToBytes(Instrument);
213 Noise: Result := NoiseInstrumentToBytes(Instrument);
214 end;
215 end;
216
217 function WaveInstrumentToRegisters(
218 Frequency: Word;
219 Initial: Boolean;
220 Instr: TInstrument): TRegisters;
221 var
222 NR30: TCh3SoundOnOffRegister;
223 NR31: TCh3SoundLengthRegister;
224 NR32: TCh3OutputLevelRegister;
225 NR33: TLowByteRegister;
226 NR34: THighByteRegister;
227 begin
228 NR30 := Default(TCh3SoundOnOffRegister);
229 NR31 := Default(TCh3SoundLengthRegister);
230 NR32 := Default(TCh3OutputLevelRegister);
231 NR33 := Default(TLowByteRegister);
232 NR34 := Default(THighByteRegister);
233
234 NR30.Playback := True;
235
236 NR31 := Instr.Length;
237
238 NR32.OutputLevel := Instr.OutputLevel;
239
240 NR33 := Frequency and $11111111;
241
242 NR34.Initial := Initial;
243 NR34.FrequencyBits := (Frequency and %0000011100000000) shr 8;
244 NR34.UseLength := Instr.LengthEnabled;
245
246 // Copy to wave ram
247
248 Result.Type_ := Wave;
249 Result.NR30 := NR30.ByteValue;
250 Result.NR31 := NR31;
251 Result.NR32 := NR32.ByteValue;
252 Result.NR33 := NR33;
253 Result.NR34 := NR34.ByteValue;
254 end;
255
256 function NoiseInstrumentToRegisters(
257 Initial: Boolean;
258 Instr: TInstrument): TRegisters;
259 var
260 NR41: TCh4SoundLengthRegister;
261 NR42: TEnvelopeRegister;
262 NR43: TPolynomialCounterRegister;
263 NR44: TCh4HighByteRegister;
264 begin
265 NR41 := Default(TCh4SoundLengthRegister);
266 NR42 := Default(TEnvelopeRegister);
267 NR43 := Default(TPolynomialCounterRegister);
268 NR44 := Default(TCh4HighByteRegister);
269
270 NR41 := Instr.Length;
271
272 NR42.InitialVolume := Instr.InitialVolume;
273 NR42.SweepNumber := Instr.VolSweepAmount;
274 NR42.Direction := Instr.VolSweepDirection = Up;
275
276 NR43.DividingRatio:= Instr.DividingRatio;
277 NR43.SevenBitCounter:=Instr.CounterStep = Seven;
278 NR43.ShiftClockFrequency:= Instr.ShiftClockFreq;
279
280 NR44.Initial:= Initial;
281 NR44.UseLength:=Instr.LengthEnabled;
282
283 Result.Type_ := Noise;
284 Result.NR41 := NR41;
285 Result.NR42 := NR42.ByteValue;
286 Result.NR43 := NR43.ByteValue;
287 Result.NR44 := NR44.ByteValue;
288 end;
289
290 function SquareInstrumentToRegisters(
291 Frequency: Word;
292 Initial: Boolean;
293 Instr: TInstrument): TRegisters;
294 var
295 NR10: TSweepRegister;
296 NR11: TSquareLengthRegister;
297 NR12: TEnvelopeRegister;
298 NR13: TLowByteRegister;
299 NR14: THighByteRegister;
300 begin
301 NR10 := Default(TSweepRegister);
302 NR11 := Default(TSquareLengthRegister);
303 NR12 := Default(TEnvelopeRegister);
304 NR13 := Default(TLowByteRegister);
305 NR14 := Default(THighByteRegister);
306
307 NR10.SweepTime := Instr.SweepTime;
308 NR10.Shift := Instr.SweepShift;
309 NR10.IncDec := Instr.SweepIncDec = Down;
310
311 NR11.Duty := Instr.Duty;
312 NR11.Length := Instr.Length;
313
314 NR12.Direction := Instr.VolSweepDirection = Up;
315 NR12.InitialVolume := Instr.InitialVolume;
316 NR12.SweepNumber := Instr.VolSweepAmount;
317
318 NR13 := Frequency and %11111111;
319
320 NR14.FrequencyBits := (Frequency and %0000011100000000) shr 8;
321 NR14.Initial := Initial;
322 NR14.UseLength := Instr.LengthEnabled;
323
324 Result.Type_ := Square;
325 Result.NR10:=NR10.ByteValue;
326 Result.NR11:=NR11.ByteValue;
327 Result.NR12:=NR12.ByteValue;
328 Result.NR13:=NR13;
329 Result.NR14:=NR14.ByteValue;
330 end;
331
55 end. 332 end.
56 333
Modifiedsong.pas +3−4
@@ -4,10 +4,9 @@ unit Song;
4 4
5 interface 5 interface
6 6
7 uses instruments, waves, patterns; 7 uses instruments, waves, patterns, HugeDatatypes;
8 8
9 type 9 type
10
11 { TSong } 10 { TSong }
12 11
13 TSong = record 12 TSong = record
@@ -15,8 +14,8 @@ type
15 Artist: ShortString; 14 Artist: ShortString;
16 Comment: ShortString; 15 Comment: ShortString;
17 16
18 Instruments: array[1..15] of TInstrument; 17 Instruments: TInstrumentBank;
19 Waves: array[0..15] of TWave; 18 Waves: TWaveBank;
20 19
21 Patterns: array of TPattern; 20 Patterns: array of TPattern;
22 OrderMatrix: array of integer; 21 OrderMatrix: array of integer;
Modifiedtracker.lfm +68−25
@@ -1,10 +1,10 @@
1 object frmTracker: TfrmTracker 1 object frmTracker: TfrmTracker
2 Left = 1409 2 Left = 799
3 Height = 1514 3 Height = 1396
4 Top = 390 4 Top = 201
5 Width = 2208 5 Width = 2208
6 Caption = 'hUGETracker' 6 Caption = 'hUGETracker'
7 ClientHeight = 1480 7 ClientHeight = 1362
8 ClientWidth = 2208 8 ClientWidth = 2208
9 DesignTimePPI = 168 9 DesignTimePPI = 168
10 Menu = MainMenu1 10 Menu = MainMenu1
@@ -15,7 +15,7 @@ object frmTracker: TfrmTracker
15 LCLVersion = '2.0.6.0' 15 LCLVersion = '2.0.6.0'
16 object TreeView1: TTreeView 16 object TreeView1: TTreeView
17 Left = 0 17 Left = 0
18 Height = 1084 18 Height = 966
19 Top = 353 19 Top = 353
20 Width = 338 20 Width = 338
21 Align = alLeft 21 Align = alLeft
@@ -33,24 +33,24 @@ object frmTracker: TfrmTracker
33 end 33 end
34 object Splitter1: TSplitter 34 object Splitter1: TSplitter
35 Left = 338 35 Left = 338
36 Height = 1084 36 Height = 966
37 Top = 353 37 Top = 353
38 Width = 9 38 Width = 9
39 end 39 end
40 object Panel1: TPanel 40 object Panel1: TPanel
41 Left = 347 41 Left = 347
42 Height = 1084 42 Height = 966
43 Top = 353 43 Top = 353
44 Width = 1861 44 Width = 1861
45 Align = alClient 45 Align = alClient
46 BevelOuter = bvNone 46 BevelOuter = bvNone
47 ClientHeight = 1084 47 ClientHeight = 966
48 ClientWidth = 1861 48 ClientWidth = 1861
49 ParentFont = False 49 ParentFont = False
50 TabOrder = 2 50 TabOrder = 2
51 object PageControl1: TPageControl 51 object PageControl1: TPageControl
52 Left = 0 52 Left = 0
53 Height = 1084 53 Height = 966
54 Top = 0 54 Top = 0
55 Width = 1861 55 Width = 1861
56 ActivePage = PatternTabSheet 56 ActivePage = PatternTabSheet
@@ -137,16 +137,16 @@ object frmTracker: TfrmTracker
137 end 137 end
138 object PatternTabSheet: TTabSheet 138 object PatternTabSheet: TTabSheet
139 Caption = 'Patterns' 139 Caption = 'Patterns'
140 ClientHeight = 1041 140 ClientHeight = 923
141 ClientWidth = 1853 141 ClientWidth = 1853
142 ParentFont = False 142 ParentFont = False
143 object Panel3: TPanel 143 object Panel3: TPanel
144 Left = 392 144 Left = 392
145 Height = 1041 145 Height = 923
146 Top = 0 146 Top = 0
147 Width = 1461 147 Width = 1461
148 Align = alClient 148 Align = alClient
149 ClientHeight = 1041 149 ClientHeight = 923
150 ClientWidth = 1461 150 ClientWidth = 1461
151 ParentFont = False 151 ParentFont = False
152 TabOrder = 0 152 TabOrder = 0
@@ -194,7 +194,7 @@ object frmTracker: TfrmTracker
194 end 194 end
195 object ScrollBox1: TScrollBox 195 object ScrollBox1: TScrollBox
196 Left = 1 196 Left = 1
197 Height = 987 197 Height = 869
198 Top = 53 198 Top = 53
199 Width = 1459 199 Width = 1459
200 HorzScrollBar.Increment = 1 200 HorzScrollBar.Increment = 1
@@ -213,10 +213,11 @@ object frmTracker: TfrmTracker
213 end 213 end
214 object OrderEditStringGrid: TStringGrid 214 object OrderEditStringGrid: TStringGrid
215 Left = 0 215 Left = 0
216 Height = 1041 216 Height = 923
217 Top = 0 217 Top = 0
218 Width = 392 218 Width = 392
219 Align = alLeft 219 Align = alLeft
220 AutoEdit = False
220 AutoFillColumns = True 221 AutoFillColumns = True
221 Columns = < 222 Columns = <
222 item 223 item
@@ -1723,7 +1724,7 @@ object frmTracker: TfrmTracker
1723 object StatusBar1: TStatusBar 1724 object StatusBar1: TStatusBar
1724 Left = 0 1725 Left = 0
1725 Height = 43 1726 Height = 43
1726 Top = 1437 1727 Top = 1319
1727 Width = 2208 1728 Width = 2208
1728 AutoHint = True 1729 AutoHint = True
1729 Panels = < 1730 Panels = <
@@ -1762,7 +1763,7 @@ object frmTracker: TfrmTracker
1762 ParentShowHint = False 1763 ParentShowHint = False
1763 end 1764 end
1764 object PanicToolButton: TToolButton 1765 object PanicToolButton: TToolButton
1765 Left = 120 1766 Left = 487
1766 Hint = 'Stops all sound output' 1767 Hint = 'Stops all sound output'
1767 Top = 0 1768 Top = 0
1768 AutoSize = True 1769 AutoSize = True
@@ -1773,42 +1774,52 @@ object frmTracker: TfrmTracker
1773 ShowHint = True 1774 ShowHint = True
1774 end 1775 end
1775 object ToolButton2: TToolButton 1776 object ToolButton2: TToolButton
1776 Left = 202 1777 Left = 125
1777 Top = 0 1778 Top = 0
1778 Caption = 'Play' 1779 Caption = 'Play'
1779 ImageIndex = 74 1780 ImageIndex = 74
1780 end 1781 end
1781 object ToolButton3: TToolButton 1782 object ToolButton3: TToolButton
1782 Left = 266 1783 Left = 189
1783 Top = 0 1784 Top = 0
1784 Caption = 'Pause' 1785 Caption = 'Pause'
1785 ImageIndex = 75 1786 ImageIndex = 75
1786 end 1787 end
1787 object ToolButton4: TToolButton 1788 object ToolButton4: TToolButton
1788 Left = 347 1789 Left = 270
1789 Top = 0 1790 Top = 0
1790 Caption = 'Stop' 1791 Caption = 'Stop'
1791 ImageIndex = 73 1792 ImageIndex = 73
1792 end 1793 end
1793 object ToolButton5: TToolButton 1794 object ToolButton5: TToolButton
1794 Left = 421 1795 Left = 343
1795 Top = 0 1796 Top = 0
1796 Caption = 'ToolButton5' 1797 AutoSize = True
1798 Caption = 'Export song'
1799 ImageIndex = 76
1800 OnClick = ToolButton5Click
1797 end 1801 end
1798 object ToolButton8: TToolButton 1802 object ToolButton8: TToolButton
1799 Left = 196 1803 Left = 120
1800 Height = 39 1804 Height = 39
1801 Top = 0 1805 Top = 0
1802 Caption = 'ToolButton8' 1806 Caption = 'ToolButton8'
1803 Style = tbsDivider 1807 Style = tbsDivider
1804 end 1808 end
1805 object ToolButton6: TToolButton 1809 object ToolButton6: TToolButton
1806 Left = 415 1810 Left = 338
1807 Height = 39 1811 Height = 39
1808 Top = 0 1812 Top = 0
1809 Caption = 'ToolButton6' 1813 Caption = 'ToolButton6'
1810 Style = tbsDivider 1814 Style = tbsDivider
1811 end 1815 end
1816 object ToolButton7: TToolButton
1817 Left = 479
1818 Height = 39
1819 Top = 0
1820 Caption = 'ToolButton7'
1821 Style = tbsSeparator
1822 end
1812 end 1823 end
1813 object MainMenu1: TMainMenu 1824 object MainMenu1: TMainMenu
1814 Images = ImageList1 1825 Images = ImageList1
@@ -1979,7 +1990,7 @@ object frmTracker: TfrmTracker
1979 left = 1129 1990 left = 1129
1980 top = 75 1991 top = 75
1981 Bitmap = { 1992 Bitmap = {
1982 4C694C0000001000000010000000000000000000000000000000000000000000 1993 4C694D0000001000000010000000000000000000000000000000000000000000
1983 0000000000000000000000000000000000000000000000000000000000000000 1994 0000000000000000000000000000000000000000000000000000000000000000
1984 0000000000000000000000000000000000000000000000000000000000000000 1995 0000000000000000000000000000000000000000000000000000000000000000
1985 0000000000000000000000000000000000000000000000000000000000000000 1996 0000000000000000000000000000000000000000000000000000000000000000
@@ -4411,7 +4422,39 @@ object frmTracker: TfrmTracker
4411 44F7555555FF4E4E4EFF464646FF4E4E4EFF555555FF444444F7000000C40000 4422 44F7555555FF4E4E4EFF464646FF4E4E4EFF555555FF444444F7000000C40000
4412 00190000000BFFFFFF00FFFFFF00FFFFFF000000001400000030000000680000 4423 00190000000BFFFFFF00FFFFFF00FFFFFF000000001400000030000000680000
4413 00CC000000E8000000E8000000E8000000E8000000E8000000CC000000680000 4424 00CC000000E8000000E8000000E8000000E8000000E8000000CC000000680000
4414 003100000016FFFFFF00FFFFFF00 4425 003100000016FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
4426 FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
4427 FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
4428 FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
4429 FF00FFFFFF00FFFFFF00FFFFFF0000A9FE0000AAFF0000AAFF000286DF000461
4430 BF120462C08B0462C08B0462C08B004080CC004080CC004080CC004080CC0462
4431 C08B0462C08B0462C08B0461BF1200A9FE0000AAFF0000AAFF0000AAFF000357
4432 AB68468ED6C788BBEEFF88BBEEFF4477AAFF4477AAFF4477AAFF4073A6FF88BB
4433 EEFF88BBEEFF468ED6C70357AB6800A9FE9900A9FECC00A9FECC00A9FECC007E
4434 D4CCAADDFFFFAADDFFFFAADDFFFF77AADDFF77AADDFF77AADDFF6699CCFFAADD
4435 FFFFAADDFFFFAADDFFFF045FBA9100A4F9CC51EAFFFF4CE5FFFF4CE5FFFF007A
4436 D0CC9DD0F8FF95C8F3FF95C8F3FF5588BBFF5588BBFF5588BBFF4D80B3FF95C8
4437 F3FF95C8F3FF9FD2F9FF035DB694673501AA9B7A58FF9B7A58FF40D9FFFF0075
4438 CBCC97CAF3FF8FC2EEFF91C4F0FF5588BBFF5487BAFFFFCB43FFFBC33BFFF5B9
4439 31FFF0AF27FF96C9F2FF035BB299663802A2CEAD8BFFA58765FF3BD4FFFF006F
4440 C5CC8EC1ECFF85B8E6FF89BCEAFF4477AAFF4275A8FFF5F5E4FFF5F5E4FFF5F5
4441 E4FFF5F5E4FF89BCE6FF0359AE9D653D0398D5BB99FFB19A78FF35CEFFFF0069
4442 BECC86B9E6FF7DB0E0FF81B4E3FF85B8E7FF6FA2D2FFECECDBFFBABAA9FFCDCD
4443 BCFFECECDBFF7AADD9FF0356A9A26341048FCDBA98FF98B0A5FF2FC8FFFF0062
4444 B8CC7DB0DFFF77AADBFF79ACDDFF7DB0E1FF6194C6FFE2E2D1FFE2E2D1FFE2E2
4445 D1FFE2E2D1FF6C9FCDFF0253A4A70072C7CC32CBFFFF29C2FFFF29C2FFFF005D
4446 B2CC77AADAFF71A4D6FF74A7D9FF77AADBFF699CCEFF598CBEFF5A8DBFFF5A8D
4447 BFFF5A8DBFFF73A6D5FF024F9BB0010101AB0099DDFF31465DFF31465DFF134C
4448 89DD76A9D9FF74A7D8FF78ABDBFF78ABDBFF7AADDEFF7CAFE0FF6487AEFF3D43
4449 59FF3D4359FF698BB1FF014589C30404048B000012ED777777FF777777FF0000
4450 12ED0303036F03030396030303990303039B0202029E02020279000012ED7777
4451 77FF777777FF000012ED010101AA02020200000012CF777777FFBBBBBBFF0000
4452 12CF010106000202020002020200020202000101010001010500000012CF7777
4453 77FFBBBBBBFF000012CF010101000000001E00000B66000012D1000012D10000
4454 0B6600000026000000260000002600000026000000260000002600000B660000
4455 12D1000012D100000B660000001E0000000F000000170000001A0000001A0000
4456 001A0000001A0000001A0000001A0000001A0000001A0000001A0000001A0000
4457 001A0000001A000000170000000F
4415 } 4458 }
4416 end 4459 end
4417 object OpenDialog1: TOpenDialog 4460 object OpenDialog1: TOpenDialog
Modifiedtracker.pas +32−15
@@ -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; 12 ECProgressBar, HugeDatatypes, LCLType, Codegen;
13 13
14 type 14 type
15 { TfrmTracker } 15 { TfrmTracker }
@@ -71,6 +71,7 @@ type
71 ToolButton4: TToolButton; 71 ToolButton4: TToolButton;
72 ToolButton5: TToolButton; 72 ToolButton5: TToolButton;
73 ToolButton6: TToolButton; 73 ToolButton6: TToolButton;
74 ToolButton7: TToolButton;
74 ToolButton8: TToolButton; 75 ToolButton8: TToolButton;
75 WaveEditNumberSpinner: TSpinEdit; 76 WaveEditNumberSpinner: TSpinEdit;
76 WaveEditGroupBox: TGroupBox; 77 WaveEditGroupBox: TGroupBox;
@@ -195,6 +196,7 @@ type
195 procedure PanicToolButtonClick(Sender: TObject); 196 procedure PanicToolButtonClick(Sender: TObject);
196 procedure PasteActionExecute(Sender: TObject); 197 procedure PasteActionExecute(Sender: TObject);
197 procedure TicksPerRowSpinEditChange(Sender: TObject); 198 procedure TicksPerRowSpinEditChange(Sender: TObject);
199 procedure ToolButton5Click(Sender: TObject);
198 procedure WaveEditNumberSpinnerChange(Sender: TObject); 200 procedure WaveEditNumberSpinnerChange(Sender: TObject);
199 procedure WaveEditPaintBoxMouseDown(Sender: TObject; Button: TMouseButton; 201 procedure WaveEditPaintBoxMouseDown(Sender: TObject; Button: TMouseButton;
200 Shift: TShiftState; X, Y: Integer); 202 Shift: TShiftState; X, Y: Integer);
@@ -269,7 +271,7 @@ end;
269 271
270 procedure TfrmTracker.DrawWaveform(PB: TPaintBox; Wave: TWave); 272 procedure TfrmTracker.DrawWaveform(PB: TPaintBox; Wave: TWave);
271 var 273 var
272 Interval, HInterval: Integer; 274 Interval{, HInterval}: Integer;
273 I: Integer; 275 I: Integer;
274 W, H : Integer; 276 W, H : Integer;
275 begin 277 begin
@@ -277,7 +279,7 @@ begin
277 H := PB.Height; 279 H := PB.Height;
278 280
279 Interval := W div 32; 281 Interval := W div 32;
280 HInterval := H div $10; 282 //HInterval := H div $10;
281 With PB.Canvas do begin 283 With PB.Canvas do begin
282 Brush.Color := clBlack; 284 Brush.Color := clBlack;
283 Clear; 285 Clear;
@@ -693,8 +695,9 @@ var
693 Section: TCollectionItem; 695 Section: TCollectionItem;
694 P: TPoint; 696 P: TPoint;
695 begin 697 begin
698 // Hack
699
696 if Button = mbRight then begin 700 if Button = mbRight then begin
697 // Hack
698 P.X := X; 701 P.X := X;
699 P.Y := Y; 702 P.Y := Y;
700 703
@@ -804,10 +807,15 @@ var
804 begin 807 begin
805 Highest := Patterns.MaxKey; 808 Highest := Patterns.MaxKey;
806 809
807 OrderEditStringGrid.InsertRowWithValues( 810 with OrderEditStringGrid do
808 OrderEditStringGrid.Row, 811 InsertRowWithValues(
809 ['',IntToStr(Highest),IntToStr(Highest+1), IntToStr(Highest+2), IntToStr(Highest+3)] 812 Row,
810 ); 813 ['',
814 IntToStr(Highest),
815 IntToStr(Highest+1),
816 IntToStr(Highest+2),
817 IntToStr(Highest+3)]
818 );
811 819
812 for X := 0 to 3 do 820 for X := 0 to 3 do
813 Patterns.CreateNewPattern(Highest+X); 821 Patterns.CreateNewPattern(Highest+X);
@@ -815,10 +823,8 @@ end;
815 823
816 procedure TfrmTracker.MenuItem18Click(Sender: TObject); 824 procedure TfrmTracker.MenuItem18Click(Sender: TObject);
817 begin 825 begin
818 OrderEditStringGrid.InsertRowWithValues( 826 with OrderEditStringGrid do
819 OrderEditStringGrid.Row, 827 InsertRowWithValues(Row, ['', '0', '0', '0', '0']);
820 ['', '0', '0', '0', '0']
821 );
822 end; 828 end;
823 829
824 procedure TfrmTracker.MenuItem19Click(Sender: TObject); 830 procedure TfrmTracker.MenuItem19Click(Sender: TObject);
@@ -872,7 +878,7 @@ end;
872 878
873 procedure TfrmTracker.OrderEditStringGridDblClick(Sender: TObject); 879 procedure TfrmTracker.OrderEditStringGridDblClick(Sender: TObject);
874 var 880 var
875 X, Highest: Integer; 881 Highest: Integer;
876 begin 882 begin
877 Highest := Patterns.MaxKey; 883 Highest := Patterns.MaxKey;
878 884
@@ -886,7 +892,8 @@ procedure TfrmTracker.OrderEditStringGridEditingDone(Sender: TObject);
886 var 892 var
887 Temp: Integer; 893 Temp: Integer;
888 begin 894 begin
889 // TODO: Fix this hack! For some reason OnValidateEntry is giving bad pointers 895 // TODO: Fix this hack!
896 // For some reason OnValidateEntry is giving bad pointers
890 // for its NewValue and OldValue params. This is the workaround for now. 897 // for its NewValue and OldValue params. This is the workaround for now.
891 with OrderEditStringGrid do 898 with OrderEditStringGrid do
892 if not TryStrToInt(Cells[Col, Row], Temp) then Cells[Col, Row] := ''; 899 if not TryStrToInt(Cells[Col, Row], Temp) then Cells[Col, Row] := '';
@@ -897,7 +904,10 @@ end;
897 procedure TfrmTracker.OrderEditStringGridKeyDown(Sender: TObject; 904 procedure TfrmTracker.OrderEditStringGridKeyDown(Sender: TObject;
898 var Key: Word; Shift: TShiftState); 905 var Key: Word; Shift: TShiftState);
899 begin 906 begin
900 if Key = VK_DELETE then OrderEditStringGrid.DeleteRow(OrderEditStringGrid.Row); 907 if Key = VK_DELETE then begin
908 // TODO: Make this stop the editor from showing
909 OrderEditStringGrid.DeleteRow(OrderEditStringGrid.Row);
910 end;
901 end; 911 end;
902 912
903 procedure TfrmTracker.PanicToolButtonClick(Sender: TObject); 913 procedure TfrmTracker.PanicToolButtonClick(Sender: TObject);
@@ -923,6 +933,13 @@ begin
923 Song.TicksPerRow := TicksPerRowSpinEdit.Value; 933 Song.TicksPerRow := TicksPerRowSpinEdit.Value;
924 end; 934 end;
925 935
936 procedure TfrmTracker.ToolButton5Click(Sender: TObject);
937 begin
938 if SaveDialog1.Execute then begin
939 RenderSongToFile(Song, SaveDialog1.FileName);
940 end;
941 end;
942
926 procedure TfrmTracker.WaveEditNumberSpinnerChange(Sender: TObject); 943 procedure TfrmTracker.WaveEditNumberSpinnerChange(Sender: TObject);
927 begin 944 begin
928 LoadWave(WaveEditNumberSpinner.Value); 945 LoadWave(WaveEditNumberSpinner.Value);
Modifiedutils.pas +0−231
@@ -16,122 +16,6 @@ type
16 function MaxKey: Integer; 16 function MaxKey: Integer;
17 end; 17 end;
18 18
19 TRegisters = record
20 case Type_: TInstrumentType of
21 Square: (NR10, NR11, NR12, NR13, NR14: Byte);
22 Wave: (NR30, NR31, NR32, NR33, NR34: Byte);
23 Noise: (NR41, NR42, NR43, NR44: Byte);
24 end;
25
26 Bit = Boolean;
27 TwoBits = 0..3;
28 ThreeBits = 0..7;
29 FourBits = 0..17;
30 FiveBits = 0..31;
31 SixBits = 0..63;
32 SevenBits = 0..127;
33 EightBits = Byte;
34
35 TSweepRegister = bitpacked record
36 case Boolean of
37 True: (
38 Shift: ThreeBits;
39 IncDec: Bit;
40 SweepTime: ThreeBits;
41 _: Bit;
42 );
43 False: (ByteValue: Byte);
44 end;
45
46 TSquareLengthRegister = bitpacked record
47 case Boolean of
48 True: (
49 Length: SixBits;
50 Duty: TwoBits;
51 );
52 False: (ByteValue: Byte);
53 end;
54
55 TEnvelopeRegister = bitpacked record
56 case Boolean of
57 True: (
58 SweepNumber: ThreeBits;
59 Direction: Bit;
60 InitialVolume: FourBits;
61 );
62 False: (ByteValue: Byte);
63 end;
64
65 TLowByteRegister = Byte;
66
67 THighByteRegister = bitpacked record
68 case Boolean of
69 True: (
70 FrequencyBits: ThreeBits;
71 _Padding: ThreeBits;
72 UseLength: Bit;
73 Initial: Bit;
74 );
75 False: (ByteValue: Byte);
76 end;
77
78 TCh3SoundOnOffRegister = bitpacked record
79 case Boolean of
80 True: (
81 _Padding: SevenBits;
82 Playback: Bit;
83 );
84 False: (ByteValue: Byte);
85 end;
86
87 TCh3SoundLengthRegister = Byte;
88
89 TCh3OutputLevelRegister = bitpacked record
90 case Boolean of
91 True: (
92 _Padding: FiveBits;
93 OutputLevel: TwoBits;
94 _Padding2: Bit;
95 );
96 False: (ByteValue: Byte);
97 end;
98
99 TCh4SoundLengthRegister = 0..63;
100
101 TPolynomialCounterRegister = bitpacked record
102 case Boolean of
103 True: (
104 DividingRatio: ThreeBits;
105 SevenBitCounter: Bit;
106 ShiftClockFrequency: FourBits;
107 );
108 False: (ByteValue: Byte);
109 end;
110
111 TCh4HighByteRegister = bitpacked record
112 case Boolean of
113 True: (
114 _Padding: SixBits;
115 UseLength: Bit;
116 Initial: Bit;
117 );
118 False: (ByteValue: Byte);
119 end;
120
121 function NoiseInstrumentToRegisters(
122 Initial: Boolean;
123 Instr: TInstrument): TRegisters;
124
125 function SquareInstrumentToRegisters(
126 Frequency: Word;
127 Initial: Boolean;
128 Instr: TInstrument): TRegisters;
129
130 function WaveInstrumentToRegisters(
131 Frequency: Word;
132 Initial: Boolean;
133 Instr: TInstrument): TRegisters;
134
135 function ConvertWaveform(Waveform: TWave): T4bitWave; 19 function ConvertWaveform(Waveform: TWave): T4bitWave;
136 procedure BlankPattern(Pat: PPattern); 20 procedure BlankPattern(Pat: PPattern);
137 21
@@ -195,120 +79,5 @@ begin
195 end; 79 end;
196 end; 80 end;
197 81
198 function WaveInstrumentToRegisters(
199 Frequency: Word;
200 Initial: Boolean;
201 Instr: TInstrument): TRegisters;
202 var
203 NR30: TCh3SoundOnOffRegister;
204 NR31: TCh3SoundLengthRegister;
205 NR32: TCh3OutputLevelRegister;
206 NR33: TLowByteRegister;
207 NR34: THighByteRegister;
208 begin
209 NR30 := Default(TCh3SoundOnOffRegister);
210 NR31 := Default(TCh3SoundLengthRegister);
211 NR32 := Default(TCh3OutputLevelRegister);
212 NR33 := Default(TLowByteRegister);
213 NR34 := Default(THighByteRegister);
214
215 NR30.Playback := True;
216
217 NR31 := Instr.Length;
218
219 NR32.OutputLevel := Instr.OutputLevel;
220
221 NR33 := Frequency and $11111111;
222
223 NR34.Initial := Initial;
224 NR34.FrequencyBits := (Frequency and %0000011100000000) shr 8;
225 NR34.UseLength := Instr.LengthEnabled;
226
227 // Copy to wave ram
228
229 Result.Type_ := Wave;
230 Result.NR30 := NR30.ByteValue;
231 Result.NR31 := NR31;
232 Result.NR32 := NR32.ByteValue;
233 Result.NR33 := NR33;
234 Result.NR34 := NR34.ByteValue;
235 end;
236
237 function NoiseInstrumentToRegisters(
238 Initial: Boolean;
239 Instr: TInstrument): TRegisters;
240 var
241 NR41: TCh4SoundLengthRegister;
242 NR42: TEnvelopeRegister;
243 NR43: TPolynomialCounterRegister;
244 NR44: TCh4HighByteRegister;
245 begin
246 NR41 := Default(TCh4SoundLengthRegister);
247 NR42 := Default(TEnvelopeRegister);
248 NR43 := Default(TPolynomialCounterRegister);
249 NR44 := Default(TCh4HighByteRegister);
250
251 NR41 := Instr.Length;
252
253 NR42.InitialVolume := Instr.InitialVolume;
254 NR42.SweepNumber := Instr.VolSweepAmount;
255 NR42.Direction := Instr.VolSweepDirection = Up;
256
257 NR43.DividingRatio:= Instr.DividingRatio;
258 NR43.SevenBitCounter:=Instr.CounterStep = Seven;
259 NR43.ShiftClockFrequency:= Instr.ShiftClockFreq;
260
261 NR44.Initial:= True;
262 NR44.UseLength:=Instr.LengthEnabled;
263
264 Result.Type_ := Noise;
265 Result.NR41 := NR41;
266 Result.NR42 := NR42.ByteValue;
267 Result.NR43 := NR43.ByteValue;
268 Result.NR44 := NR44.ByteValue;
269 end;
270
271 function SquareInstrumentToRegisters(
272 Frequency: Word;
273 Initial: Boolean;
274 Instr: TInstrument): TRegisters;
275 var
276 NR10: TSweepRegister;
277 NR11: TSquareLengthRegister;
278 NR12: TEnvelopeRegister;
279 NR13: TLowByteRegister;
280 NR14: THighByteRegister;
281 begin
282 NR10 := Default(TSweepRegister);
283 NR11 := Default(TSquareLengthRegister);
284 NR12 := Default(TEnvelopeRegister);
285 NR13 := Default(TLowByteRegister);
286 NR14 := Default(THighByteRegister);
287
288 NR10.SweepTime := Instr.SweepTime;
289 NR10.Shift := Instr.SweepShift;
290 NR10.IncDec := Instr.SweepIncDec = Down;
291
292 NR11.Duty := Instr.Duty;
293 NR11.Length := Instr.Length;
294
295 NR12.Direction := Instr.VolSweepDirection = Up;
296 NR12.InitialVolume := Instr.InitialVolume;
297 NR12.SweepNumber := Instr.VolSweepAmount;
298
299 NR13 := Frequency and %11111111;
300
301 NR14.FrequencyBits := (Frequency and %0000011100000000) shr 8;
302 NR14.Initial := True;
303 NR14.UseLength := Instr.LengthEnabled;
304
305 Result.Type_ := Square;
306 Result.NR10:=NR10.ByteValue;
307 Result.NR11:=NR11.ByteValue;
308 Result.NR12:=NR12.ByteValue;
309 Result.NR13:=NR13;
310 Result.NR14:=NR14.ByteValue;
311 end;
312
313 end. 82 end.
314 83