Commit 7f11c0b

Nick committed on
WIP more instruments
commit 7f11c0b8941c4112dca99e84bb3100b0227af63c parent e18eed6
8 changed files +255−172
Modifiedcodegen.pas +15−3
@@ -57,6 +57,7 @@ var
57 SL, ResultSL: TStringList; 57 SL, ResultSL: TStringList;
58 AsmInstrument: TAsmInstrument; 58 AsmInstrument: TAsmInstrument;
59 I, J: Integer; 59 I, J: Integer;
60 TypePrefix: String;
60 begin 61 begin
61 ResultSL := TStringList.Create; 62 ResultSL := TStringList.Create;
62 63
@@ -69,7 +70,8 @@ begin
69 for J := Low(AsmInstrument) to High(AsmInstrument) do 70 for J := Low(AsmInstrument) to High(AsmInstrument) do
70 SL.Add(IntToStr(AsmInstrument[J])); 71 SL.Add(IntToStr(AsmInstrument[J]));
71 72
72 ResultSL.Add(Format('%s: db %s', ['inst'+IntToStr(I), SL.DelimitedText])); 73 WriteStr(TypePrefix, Instruments[I].Type_);
74 ResultSL.Add(Format('%s%s: db %s', [TypePrefix, 'inst'+IntToStr(I), SL.DelimitedText]));
73 SL.Free; 75 SL.Free;
74 end; 76 end;
75 77
@@ -207,9 +209,19 @@ begin
207 Write(OutFile, RenderOrderTable(Song.OrderMatrix)); 209 Write(OutFile, RenderOrderTable(Song.OrderMatrix));
208 CloseFile(OutFile); 210 CloseFile(OutFile);
209 211
210 AssignFile(OutFile, './hUGEDriver/instrument.htt'); 212 AssignFile(OutFile, './hUGEDriver/duty_instrument.htt');
211 Rewrite(OutFile); 213 Rewrite(OutFile);
212 Write(OutFile, RenderInstruments(Song.Instruments)); 214 Write(OutFile, RenderInstruments(Song.Instruments.Duty));
215 CloseFile(OutFile);
216
217 AssignFile(OutFile, './hUGEDriver/wave_instrument.htt');
218 Rewrite(OutFile);
219 Write(OutFile, RenderInstruments(Song.Instruments.Wave));
220 CloseFile(OutFile);
221
222 AssignFile(OutFile, './hUGEDriver/noise_instrument.htt');
223 Rewrite(OutFile);
224 Write(OutFile, RenderInstruments(Song.Instruments.Noise));
213 CloseFile(OutFile); 225 CloseFile(OutFile);
214 226
215 WriteRoutinesToFile(Song.Routines); 227 WriteRoutinesToFile(Song.Routines);
Modifiedhugedatatypes.pas +62−2
@@ -15,7 +15,7 @@ type
15 TInstrumentBank = packed array[1..15] of TInstrument; 15 TInstrumentBank = packed array[1..15] of TInstrument;
16 TInstrumentCollection = packed record 16 TInstrumentCollection = packed record
17 case Boolean of 17 case Boolean of
18 False: (DutyInstruments, WaveInstruments, NoiseInstruments: TInstrumentBank); 18 False: (Duty, Wave, Noise: TInstrumentBank);
19 True: (All: packed array[1..45] of TInstrument); 19 True: (All: packed array[1..45] of TInstrument);
20 end; 20 end;
21 21
@@ -39,7 +39,17 @@ type
39 TPattern = packed array[0..63] of TCell; 39 TPattern = packed array[0..63] of TCell;
40 PPattern = ^TPattern; 40 PPattern = ^TPattern;
41 41
42 TPatternMap = specialize TFPGMap<Integer, PPattern>; 42 //TPatternMap = specialize TFPGMap<Integer, PPattern>;
43 TPatternMap = class(specialize TFPGMap<Integer, PPattern>)
44 function GetOrCreateNew(Key: Integer): PPattern;
45 function CreateNewPattern(Key: Integer): PPattern;
46 function MaxKey: Integer;
47
48 procedure DeletePattern(Key: Integer);
49
50 destructor Destroy; override;
51 end;
52
43 TOrderMatrix = packed array[0..3] of array of Integer; 53 TOrderMatrix = packed array[0..3] of array of Integer;
44 54
45 TCellPart = ( 55 TCellPart = (
@@ -74,6 +84,8 @@ procedure DecSelectionPos(var SP: TSelectionPos);
74 84
75 implementation 85 implementation
76 86
87 uses Utils;
88
77 operator>(L, R: TSelectionPos): Boolean; 89 operator>(L, R: TSelectionPos): Boolean;
78 begin 90 begin
79 if L.X > R.X then 91 if L.X > R.X then
@@ -127,5 +139,53 @@ begin
127 else Dec(SP.SelectedPart); 139 else Dec(SP.SelectedPart);
128 end; 140 end;
129 141
142 { TPatternMap }
143
144 function TPatternMap.GetOrCreateNew(Key: Integer): PPattern;
145 begin
146 if Self.IndexOf(Key) <> -1 then
147 Result := Self.KeyData[Key]
148 else begin
149 New(Result);
150 BlankPattern(Result);
151 Self.Add(Key, Result);
152 end;
153 end;
154
155 function TPatternMap.CreateNewPattern(Key: Integer): PPattern;
156 begin
157 if IndexOf(Key) <> -1 then Exit(KeyData[Key]);
158
159 New(Result);
160 BlankPattern(Result);
161 Self.Add(Key, Result);
162 end;
163
164 function TPatternMap.MaxKey: Integer;
165 var
166 X: Integer;
167 begin
168 Result := 0;
169 for X := 0 to Self.Count-1 do
170 if Self.Keys[X] > Result then Result := Self.Keys[X];
171 Inc(Result);
172 end;
173
174 procedure TPatternMap.DeletePattern(Key: Integer);
175 begin
176 Dispose(KeyData[Key]);
177 Self.Remove(Key);
178 end;
179
180 destructor TPatternMap.Destroy;
181 var
182 I: Integer;
183 begin
184 for I := 0 to Self.Count-1 do
185 Dispose(Self.Data[I]);
186
187 inherited;
188 end;
189
130 end. 190 end.
131 191
Modifiedinstruments.pas +2−2
@@ -11,7 +11,7 @@ type
11 TInstrumentType = (itSquare, itWave, itNoise); 11 TInstrumentType = (itSquare, itWave, itNoise);
12 TDutyType = 0..3; 12 TDutyType = 0..3;
13 TSweepType = (Up, Down); 13 TSweepType = (Up, Down);
14 TStepWidth = (Fifteen, Seven); 14 TStepWidth = (swFifteen, swSeven);
15 TEnvelopeVolume = 0..15; 15 TEnvelopeVolume = 0..15;
16 TEnvelopeSweepAmount = 0..7; 16 TEnvelopeSweepAmount = 0..7;
17 17
@@ -282,7 +282,7 @@ begin
282 NR43.ShiftClockFrequency := $F - (Frequency shr 7); // Quantize CH4 note 282 NR43.ShiftClockFrequency := $F - (Frequency shr 7); // Quantize CH4 note
283 283
284 NR43.DividingRatio:= Instr.DividingRatio; 284 NR43.DividingRatio:= Instr.DividingRatio;
285 NR43.SevenBitCounter:=Instr.CounterStep = Seven; 285 NR43.SevenBitCounter:=Instr.CounterStep = swSeven;
286 286
287 NR44.Initial:= Initial; 287 NR44.Initial:= Initial;
288 NR44.UseLength:=Instr.LengthEnabled; 288 NR44.UseLength:=Instr.LengthEnabled;
Modifiedmodimport.pas +5−5
@@ -196,13 +196,13 @@ begin
196 // Create the instruments. 196 // Create the instruments.
197 197
198 // First four are just the default instrument with a different duty cycle. 198 // First four are just the default instrument with a different duty cycle.
199 Result.Instruments[1].Duty := 1; 199 Result.Instruments.Duty[1].Duty := 1;
200 Result.Instruments[2].Duty := 2; 200 Result.Instruments.Duty[2].Duty := 2;
201 Result.Instruments[3].Duty := 3; 201 Result.Instruments.Duty[3].Duty := 3;
202 Result.Instruments[4].Duty := 0; 202 Result.Instruments.Duty[4].Duty := 0;
203 203
204 for I := 8 to 15 do 204 for I := 8 to 15 do
205 with Result.Instruments[I] do begin 205 with Result.Instruments.Wave[I] do begin
206 Waveform := I - 8; 206 Waveform := I - 8;
207 Type_ := itWave; 207 Type_ := itWave;
208 end; 208 end;
Modifiedsong.pas +43−24
@@ -78,6 +78,8 @@ function UpgradeSong(S: TSongV3): TSong; overload;
78 78
79 implementation 79 implementation
80 80
81 uses Utils;
82
81 // Thanks to WP on the FreePascal forums for this code! 83 // Thanks to WP on the FreePascal forums for this code!
82 // https://forum.lazarus.freepascal.org/index.php/topic,47892.msg344152.html#msg344152 84 // https://forum.lazarus.freepascal.org/index.php/topic,47892.msg344152.html#msg344152
83 85
@@ -263,8 +265,8 @@ begin
263 Comment := ''; 265 Comment := '';
264 end; 266 end;
265 267
266 for I := Low(S.Instruments.DutyInstruments) to High(S.Instruments.DutyInstruments) do 268 for I := Low(S.Instruments.Duty) to High(S.Instruments.Duty) do
267 with S.Instruments.DutyInstruments[I] do begin 269 with S.Instruments.Duty[I] do begin
268 Type_ := itSquare; 270 Type_ := itSquare;
269 Length := 0; 271 Length := 0;
270 LengthEnabled := False; 272 LengthEnabled := False;
@@ -281,40 +283,27 @@ begin
281 OutputLevel := 1; 283 OutputLevel := 1;
282 end; 284 end;
283 285
284 for I := Low(S.Instruments.WaveInstruments) to High(S.Instruments.WaveInstruments) do 286 for I := Low(S.Instruments.Wave) to High(S.Instruments.Wave) do
285 with S.Instruments.WaveInstruments[I] do begin 287 with S.Instruments.Wave[I] do begin
286 Type_ := itWave; 288 Type_ := itWave;
287 Length := 0; 289 Length := 0;
288 LengthEnabled := False; 290 LengthEnabled := False;
289 InitialVolume := High(TEnvelopeVolume);
290 VolSweepDirection := Down;
291 VolSweepAmount := 0;
292
293 SweepTime := 0;
294 SweepIncDec := Down;
295 SweepShift := 0;
296
297 Duty := 2;
298
299 OutputLevel := 1; 291 OutputLevel := 1;
292 Waveform := 0;
300 end; 293 end;
301 294
302 for I := Low(S.Instruments.NoiseInstruments) to High(S.Instruments.NoiseInstruments) do 295 for I := Low(S.Instruments.Noise) to High(S.Instruments.Noise) do
303 with S.Instruments.NoiseInstruments[I] do begin 296 with S.Instruments.Noise[I] do begin
304 Type_ := itSquare; 297 Type_ := itNoise;
305 Length := 0; 298 Length := 0;
306 LengthEnabled := False; 299 LengthEnabled := False;
307 InitialVolume := High(TEnvelopeVolume); 300 InitialVolume := High(TEnvelopeVolume);
308 VolSweepDirection := Down; 301 VolSweepDirection := Down;
309 VolSweepAmount := 0; 302 VolSweepAmount := 0;
310 303
311 SweepTime := 0; 304 ShiftClockFreq := 0;
312 SweepIncDec := Down; 305 DividingRatio := 0;
313 SweepShift := 0; 306 CounterStep := swFifteen;
314
315 Duty := 2;
316
317 OutputLevel := 1;
318 end; 307 end;
319 308
320 for I := Low(S.Waves) to High(S.Waves) do begin 309 for I := Low(S.Waves) to High(S.Waves) do begin
@@ -356,6 +345,36 @@ begin
356 end; 345 end;
357 346
358 function UpgradeSong(S: TSongV2): TSong; 347 function UpgradeSong(S: TSongV2): TSong;
348 var
349 SV3: TSongV3;
350 I: Integer;
351 begin
352 InitializeSong(SV3);
353 SV3.Patterns.Free; // We already have one in S, so free the one InitializeSong creates.
354
355 SV3.Version:=3;
356 SV3.Name:=S.Name;
357 SV3.Artist:=S.Artist;
358 SV3.Comment:=S.Comment;
359
360 for I := Low(S.Instruments) to High(S.Instruments) do begin
361 case S.Instruments[I].Type_ of
362 itSquare: SV3.Instruments.Duty[I] := S.Instruments[I];
363 itWave: SV3.Instruments.Wave[I] := S.Instruments[I];
364 itNoise: SV3.Instruments.Noise[I] := S.Instruments[I];
365 end;
366 end;
367
368 SV3.Waves:=S.Waves;
369 SV3.TicksPerRow:=S.TicksPerRow;
370 SV3.Patterns:=S.Patterns;
371 SV3.OrderMatrix:=S.OrderMatrix;
372 SV3.Routines:=S.Routines;
373
374 Result := UpgradeSong(SV3);
375 end;
376
377 function UpgradeSong(S: TSongV3): TSong;
359 begin 378 begin
360 Result := S; 379 Result := S;
361 end; 380 end;
Modifiedtracker.lfm +96−62
@@ -1,11 +1,11 @@
1 object frmTracker: TfrmTracker 1 object frmTracker: TfrmTracker
2 Left = 1832 2 Left = 1888
3 Height = 688 3 Height = 726
4 Top = 19 4 Top = 59
5 Width = 1166 5 Width = 1180
6 Caption = 'hUGETracker' 6 Caption = 'hUGETracker'
7 ClientHeight = 668 7 ClientHeight = 706
8 ClientWidth = 1166 8 ClientWidth = 1180
9 KeyPreview = True 9 KeyPreview = True
10 Menu = MainMenu1 10 Menu = MainMenu1
11 OnClose = FormClose 11 OnClose = FormClose
@@ -19,7 +19,7 @@ object frmTracker: TfrmTracker
19 LCLVersion = '2.0.6.0' 19 LCLVersion = '2.0.6.0'
20 object TreeView1: TTreeView 20 object TreeView1: TTreeView
21 Left = 0 21 Left = 0
22 Height = 442 22 Height = 480
23 Top = 203 23 Top = 203
24 Width = 193 24 Width = 193
25 Align = alLeft 25 Align = alLeft
@@ -29,34 +29,37 @@ object frmTracker: TfrmTracker
29 OnDblClick = TreeView1DblClick 29 OnDblClick = TreeView1DblClick
30 Options = [tvoAutoItemHeight, tvoHideSelection, tvoKeepCollapsedNodes, tvoReadOnly, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw] 30 Options = [tvoAutoItemHeight, tvoHideSelection, tvoKeepCollapsedNodes, tvoReadOnly, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw]
31 Items.Data = { 31 Items.Data = {
32 F9FFFFFF020003000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000 32 F9FFFFFF020003000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF030000000000
33 0000000B000000496E737472756D656E7473FFFFFFFFFFFFFFFFFFFFFFFFFFFF 33 0000010B000000496E737472756D656E7473FFFFFFFFFFFFFFFFFFFFFFFFFFFF
34 FFFF000000000000000000050000005761766573FFFFFFFFFFFFFFFFFFFFFFFF 34 FFFF0000000000000000000400000044757479FFFFFFFFFFFFFFFFFFFFFFFFFF
35 FFFFFFFF00000000000000000008000000526F7574696E6573 35 FFFFFF0000000000000000000400000057617665FFFFFFFFFFFFFFFFFFFFFFFF
36 FFFFFFFF000000000000000000050000004E6F697365FFFFFFFFFFFFFFFFFFFF
37 FFFFFFFFFFFF000000000000000000050000005761766573FFFFFFFFFFFFFFFF
38 FFFFFFFFFFFFFFFF00000000000000000008000000526F7574696E6573
36 } 39 }
37 end 40 end
38 object Splitter1: TSplitter 41 object Splitter1: TSplitter
39 Left = 193 42 Left = 193
40 Height = 442 43 Height = 480
41 Top = 203 44 Top = 203
42 Width = 5 45 Width = 5
43 end 46 end
44 object Panel1: TPanel 47 object Panel1: TPanel
45 Left = 198 48 Left = 198
46 Height = 442 49 Height = 480
47 Top = 203 50 Top = 203
48 Width = 968 51 Width = 982
49 Align = alClient 52 Align = alClient
50 BevelOuter = bvNone 53 BevelOuter = bvNone
51 ClientHeight = 442 54 ClientHeight = 480
52 ClientWidth = 968 55 ClientWidth = 982
53 ParentFont = False 56 ParentFont = False
54 TabOrder = 2 57 TabOrder = 2
55 object PageControl1: TPageControl 58 object PageControl1: TPageControl
56 Left = 0 59 Left = 0
57 Height = 442 60 Height = 480
58 Top = 0 61 Top = 0
59 Width = 968 62 Width = 982
60 ActivePage = InstrumentTabSheet 63 ActivePage = InstrumentTabSheet
61 Align = alClient 64 Align = alClient
62 ParentFont = False 65 ParentFont = False
@@ -285,18 +288,18 @@ object frmTracker: TfrmTracker
285 end 288 end
286 object InstrumentTabSheet: TTabSheet 289 object InstrumentTabSheet: TTabSheet
287 Caption = 'Instruments' 290 Caption = 'Instruments'
288 ClientHeight = 414 291 ClientHeight = 452
289 ClientWidth = 960 292 ClientWidth = 974
290 ParentFont = False 293 ParentFont = False
291 object PaintBox1: TPaintBox 294 object PaintBox1: TPaintBox
292 AnchorSideTop.Control = FlowPanel1 295 AnchorSideTop.Control = FlowPanel1
293 AnchorSideTop.Side = asrBottom 296 AnchorSideTop.Side = asrBottom
294 AnchorSideBottom.Side = asrBottom 297 AnchorSideBottom.Side = asrBottom
295 Left = 0 298 Left = 0
296 Height = 9 299 Height = 14
297 Hint = 'Preview of how the resulting waveform will look with envelope applied' 300 Hint = 'Preview of how the resulting waveform will look with envelope applied'
298 Top = 405 301 Top = 438
299 Width = 960 302 Width = 974
300 Align = alClient 303 Align = alClient
301 Color = clBlack 304 Color = clBlack
302 ParentColor = False 305 ParentColor = False
@@ -306,9 +309,9 @@ object frmTracker: TfrmTracker
306 end 309 end
307 object FlowPanel1: TFlowPanel 310 object FlowPanel1: TFlowPanel
308 Left = 0 311 Left = 0
309 Height = 405 312 Height = 438
310 Top = 0 313 Top = 0
311 Width = 960 314 Width = 974
312 Align = alTop 315 Align = alTop
313 AutoSize = True 316 AutoSize = True
314 BevelOuter = bvNone 317 BevelOuter = bvNone
@@ -344,7 +347,7 @@ object frmTracker: TfrmTracker
344 TabOrder = 0 347 TabOrder = 0
345 object InstrumentGroupBox: TGroupBox 348 object InstrumentGroupBox: TGroupBox
346 Left = 7 349 Left = 7
347 Height = 208 350 Height = 241
348 Top = 7 351 Top = 7
349 Width = 271 352 Width = 271
350 Anchors = [] 353 Anchors = []
@@ -353,7 +356,7 @@ object frmTracker: TfrmTracker
353 BorderSpacing.Right = 7 356 BorderSpacing.Right = 7
354 BorderSpacing.Bottom = 7 357 BorderSpacing.Bottom = 7
355 Caption = 'Instrument' 358 Caption = 'Instrument'
356 ClientHeight = 188 359 ClientHeight = 221
357 ClientWidth = 267 360 ClientWidth = 267
358 ParentFont = False 361 ParentFont = False
359 TabOrder = 0 362 TabOrder = 0
@@ -361,7 +364,7 @@ object frmTracker: TfrmTracker
361 Left = 80 364 Left = 80
362 Height = 23 365 Height = 23
363 Hint = 'What instrument to edit' 366 Hint = 'What instrument to edit'
364 Top = 1 367 Top = 38
365 Width = 176 368 Width = 176
366 MaxValue = 15 369 MaxValue = 15
367 MinValue = 1 370 MinValue = 1
@@ -373,7 +376,7 @@ object frmTracker: TfrmTracker
373 object Label1: TLabel 376 object Label1: TLabel
374 Left = 8 377 Left = 8
375 Height = 15 378 Height = 15
376 Top = 8 379 Top = 46
377 Width = 58 380 Width = 58
378 Caption = 'Instrument' 381 Caption = 'Instrument'
379 ParentColor = False 382 ParentColor = False
@@ -382,7 +385,7 @@ object frmTracker: TfrmTracker
382 object Label2: TLabel 385 object Label2: TLabel
383 Left = 8 386 Left = 8
384 Height = 15 387 Height = 15
385 Top = 34 388 Top = 78
386 Width = 32 389 Width = 32
387 Caption = 'Name' 390 Caption = 'Name'
388 ParentColor = False 391 ParentColor = False
@@ -392,7 +395,7 @@ object frmTracker: TfrmTracker
392 Left = 80 395 Left = 80
393 Height = 23 396 Height = 23
394 Hint = 'The name of the instrument' 397 Hint = 'The name of the instrument'
395 Top = 26 398 Top = 70
396 Width = 176 399 Width = 176
397 OnChange = InstrumentNameEditChange 400 OnChange = InstrumentNameEditChange
398 ParentFont = False 401 ParentFont = False
@@ -401,18 +404,19 @@ object frmTracker: TfrmTracker
401 object Label3: TLabel 404 object Label3: TLabel
402 Left = 8 405 Left = 8
403 Height = 15 406 Height = 15
404 Top = 61 407 Top = 16
405 Width = 24 408 Width = 44
406 Caption = 'Type' 409 Caption = 'Channel'
410 Font.Style = [fsBold]
407 ParentColor = False 411 ParentColor = False
408 ParentFont = False 412 ParentFont = False
409 end 413 end
410 object InstrumentTypeCombobox: TComboBox 414 object InstrumentTypeCombobox: TComboBox
411 Left = 80 415 Left = 78
412 Height = 23 416 Height = 23
413 Hint = 'What type of channel this instrument will be played on' 417 Hint = 'What type of channel this instrument will be played on'
414 Top = 53 418 Top = 8
415 Width = 176 419 Width = 178
416 ItemHeight = 15 420 ItemHeight = 15
417 ItemIndex = 0 421 ItemIndex = 0
418 Items.Strings = ( 422 Items.Strings = (
@@ -427,10 +431,10 @@ object frmTracker: TfrmTracker
427 Text = 'Square' 431 Text = 'Square'
428 end 432 end
429 object LengthEnabledCheckbox: TCheckBox 433 object LengthEnabledCheckbox: TCheckBox
430 Left = 8 434 Left = 12
431 Height = 19 435 Height = 19
432 Hint = 'Cut the sound after a certain length of time' 436 Hint = 'Cut the sound after a certain length of time'
433 Top = 84 437 Top = 118
434 Width = 57 438 Width = 57
435 Caption = 'Length' 439 Caption = 'Length'
436 OnChange = LengthEnabledCheckboxChange 440 OnChange = LengthEnabledCheckboxChange
@@ -438,9 +442,9 @@ object frmTracker: TfrmTracker
438 TabOrder = 3 442 TabOrder = 3
439 end 443 end
440 object InstrumentImportButton: TButton 444 object InstrumentImportButton: TButton
441 Left = 14 445 Left = 12
442 Height = 25 446 Height = 25
443 Top = 151 447 Top = 184
444 Width = 116 448 Width = 116
445 Caption = 'Import' 449 Caption = 'Import'
446 OnClick = InstrumentImportButtonClick 450 OnClick = InstrumentImportButtonClick
@@ -448,9 +452,9 @@ object frmTracker: TfrmTracker
448 TabOrder = 4 452 TabOrder = 4
449 end 453 end
450 object InstrumentExportButton: TButton 454 object InstrumentExportButton: TButton
451 Left = 137 455 Left = 138
452 Height = 25 456 Height = 25
453 Top = 151 457 Top = 184
454 Width = 116 458 Width = 116
455 Caption = 'Export' 459 Caption = 'Export'
456 OnClick = InstrumentExportButtonClick 460 OnClick = InstrumentExportButtonClick
@@ -458,10 +462,10 @@ object frmTracker: TfrmTracker
458 TabOrder = 5 462 TabOrder = 5
459 end 463 end
460 object Button1: TButton 464 object Button1: TButton
461 Left = 14 465 Left = 12
462 Height = 25 466 Height = 25
463 Hint = 'Test out the instrument with a C-5 note' 467 Hint = 'Test out the instrument with a C-5 note'
464 Top = 119 468 Top = 152
465 Width = 242 469 Width = 242
466 Caption = 'Test C-5' 470 Caption = 'Test C-5'
467 OnClick = Button1Click 471 OnClick = Button1Click
@@ -469,9 +473,9 @@ object frmTracker: TfrmTracker
469 TabOrder = 6 473 TabOrder = 6
470 end 474 end
471 object LengthTrackbar: TTrackBar 475 object LengthTrackbar: TTrackBar
472 Left = 78 476 Left = 76
473 Height = 25 477 Height = 25
474 Top = 82 478 Top = 112
475 Width = 178 479 Width = 178
476 Max = 63 480 Max = 63
477 OnChange = LengthSpinnerChange 481 OnChange = LengthSpinnerChange
@@ -587,7 +591,7 @@ object frmTracker: TfrmTracker
587 object SquareGroupBox: TGroupBox 591 object SquareGroupBox: TGroupBox
588 Left = 7 592 Left = 7
589 Height = 169 593 Height = 169
590 Top = 229 594 Top = 262
591 Width = 319 595 Width = 319
592 Anchors = [] 596 Anchors = []
593 BorderSpacing.Left = 7 597 BorderSpacing.Left = 7
@@ -718,7 +722,7 @@ object frmTracker: TfrmTracker
718 object WaveGroupBox: TGroupBox 722 object WaveGroupBox: TGroupBox
719 Left = 340 723 Left = 340
720 Height = 169 724 Height = 169
721 Top = 229 725 Top = 262
722 Width = 297 726 Width = 297
723 Anchors = [] 727 Anchors = []
724 BorderSpacing.Left = 7 728 BorderSpacing.Left = 7
@@ -827,7 +831,7 @@ object frmTracker: TfrmTracker
827 object NoiseGroupBox: TGroupBox 831 object NoiseGroupBox: TGroupBox
828 Left = 651 832 Left = 651
829 Height = 169 833 Height = 169
830 Top = 229 834 Top = 262
831 Width = 264 835 Width = 264
832 Anchors = [] 836 Anchors = []
833 BorderSpacing.Left = 7 837 BorderSpacing.Left = 7
@@ -981,14 +985,14 @@ object frmTracker: TfrmTracker
981 end 985 end
982 object CommentsTabSheet: TTabSheet 986 object CommentsTabSheet: TTabSheet
983 Caption = 'Comments' 987 Caption = 'Comments'
984 ClientHeight = 412 988 ClientHeight = 414
985 ClientWidth = 960 989 ClientWidth = 960
986 ParentFont = False 990 ParentFont = False
987 object CommentMemo: TMemo 991 object CommentMemo: TMemo
988 AnchorSideTop.Control = Label17 992 AnchorSideTop.Control = Label17
989 AnchorSideTop.Side = asrBottom 993 AnchorSideTop.Side = asrBottom
990 Left = 0 994 Left = 0
991 Height = 376 995 Height = 378
992 Hint = 'The comments section for your song. Greetings/links/etc' 996 Hint = 'The comments section for your song. Greetings/links/etc'
993 Top = 36 997 Top = 36
994 Width = 960 998 Width = 960
@@ -1012,14 +1016,14 @@ object frmTracker: TfrmTracker
1012 end 1016 end
1013 object RoutinesTabSheet: TTabSheet 1017 object RoutinesTabSheet: TTabSheet
1014 Caption = 'Routines' 1018 Caption = 'Routines'
1015 ClientHeight = 412 1019 ClientHeight = 414
1016 ClientWidth = 960 1020 ClientWidth = 960
1017 ParentFont = False 1021 ParentFont = False
1018 inline RoutineSynedit: TSynEdit 1022 inline RoutineSynedit: TSynEdit
1019 AnchorSideTop.Control = Label19 1023 AnchorSideTop.Control = Label19
1020 AnchorSideTop.Side = asrBottom 1024 AnchorSideTop.Side = asrBottom
1021 Left = 0 1025 Left = 0
1022 Height = 284 1026 Height = 286
1023 Top = 128 1027 Top = 128
1024 Width = 960 1028 Width = 960
1025 Align = alBottom 1029 Align = alBottom
@@ -1557,17 +1561,17 @@ object frmTracker: TfrmTracker
1557 Left = 0 1561 Left = 0
1558 Height = 178 1562 Height = 178
1559 Top = 25 1563 Top = 25
1560 Width = 1166 1564 Width = 1180
1561 Align = alTop 1565 Align = alTop
1562 BevelOuter = bvNone 1566 BevelOuter = bvNone
1563 ChildSizing.HorizontalSpacing = 10 1567 ChildSizing.HorizontalSpacing = 10
1564 ClientHeight = 178 1568 ClientHeight = 178
1565 ClientWidth = 1166 1569 ClientWidth = 1180
1566 ParentFont = False 1570 ParentFont = False
1567 TabOrder = 3 1571 TabOrder = 3
1568 object LEDMeter1: TLEDMeter 1572 object LEDMeter1: TLEDMeter
1569 AnchorSideRight.Side = asrBottom 1573 AnchorSideRight.Side = asrBottom
1570 Left = 721 1574 Left = 735
1571 Height = 178 1575 Height = 178
1572 Top = 0 1576 Top = 0
1573 Width = 50 1577 Width = 50
@@ -1591,7 +1595,7 @@ object frmTracker: TfrmTracker
1591 end 1595 end
1592 object LEDMeter2: TLEDMeter 1596 object LEDMeter2: TLEDMeter
1593 AnchorSideRight.Side = asrBottom 1597 AnchorSideRight.Side = asrBottom
1594 Left = 671 1598 Left = 685
1595 Height = 178 1599 Height = 178
1596 Top = 0 1600 Top = 0
1597 Width = 50 1601 Width = 50
@@ -1614,7 +1618,7 @@ object frmTracker: TfrmTracker
1614 Section3Value = 80 1618 Section3Value = 80
1615 end 1619 end
1616 object Panel6: TPanel 1620 object Panel6: TPanel
1617 Left = 772 1621 Left = 786
1618 Height = 178 1622 Height = 178
1619 Top = 0 1623 Top = 0
1620 Width = 394 1624 Width = 394
@@ -1666,8 +1670,8 @@ object frmTracker: TfrmTracker
1666 object StatusBar1: TStatusBar 1670 object StatusBar1: TStatusBar
1667 Left = 0 1671 Left = 0
1668 Height = 23 1672 Height = 23
1669 Top = 645 1673 Top = 683
1670 Width = 1166 1674 Width = 1180
1671 AutoHint = True 1675 AutoHint = True
1672 Panels = < 1676 Panels = <
1673 item 1677 item
@@ -1688,7 +1692,7 @@ object frmTracker: TfrmTracker
1688 Left = 0 1692 Left = 0
1689 Height = 25 1693 Height = 25
1690 Top = 0 1694 Top = 0
1691 Width = 1166 1695 Width = 1180
1692 AutoSize = True 1696 AutoSize = True
1693 Caption = 'ToolBar1' 1697 Caption = 'ToolBar1'
1694 EdgeBorders = [ebBottom] 1698 EdgeBorders = [ebBottom]
@@ -1822,6 +1826,36 @@ object frmTracker: TfrmTracker
1822 '13:' 1826 '13:'
1823 '14:' 1827 '14:'
1824 '15:' 1828 '15:'
1829 '16:'
1830 '17:'
1831 '18:'
1832 '19:'
1833 '20:'
1834 '21:'
1835 '22:'
1836 '23:'
1837 '24:'
1838 '25:'
1839 '26:'
1840 '27:'
1841 '28:'
1842 '29:'
1843 '30:'
1844 '31:'
1845 '32:'
1846 '33:'
1847 '34:'
1848 '35:'
1849 '36:'
1850 '37:'
1851 '38:'
1852 '39:'
1853 '40:'
1854 '41:'
1855 '42:'
1856 '43:'
1857 '44:'
1858 '45:'
1825 ) 1859 )
1826 OnChange = InstrumentComboBoxChange 1860 OnChange = InstrumentComboBoxChange
1827 ParentFont = False 1861 ParentFont = False
Modifiedtracker.pas +24−25
@@ -351,6 +351,7 @@ type
351 Song: TSong; 351 Song: TSong;
352 CurrentInstrument: ^TInstrument; 352 CurrentInstrument: ^TInstrument;
353 CurrentWave: ^TWave; 353 CurrentWave: ^TWave;
354 CurrentInstrumentBank: TInstrumentType;
354 355
355 EmulationThread: TThread; 356 EmulationThread: TThread;
356 357
@@ -429,11 +430,12 @@ begin
429 RecreateTrackerGrid; 430 RecreateTrackerGrid;
430 CopyOrderMatrixToOrderGrid; 431 CopyOrderMatrixToOrderGrid;
431 432
432 for I := Low(Song.Instruments) to High(song.Instruments) do 433 // PLACEHOLDER
433 InstrumentComboBox.Items[I] := IntToStr(I)+': '+Song.Instruments[I].Name; 434 for I := Low(Song.Instruments.All) to High(song.Instruments.All) do
435 InstrumentComboBox.Items[I] := IntToStr(ModInst(I))+': '+Song.Instruments.All[ModInst(I)].Name;
434 436
435 for I := Low(Song.Instruments) to High(song.Instruments) do 437 for I := Low(Song.Instruments.All) to High(song.Instruments.All) do
436 InstrumentsNode.Items[I-1].Text := IntToStr(I)+': '+Song.Instruments[I].Name; 438 InstrumentsNode.Items[I-1].Text := IntToStr(ModInst(I))+': '+Song.Instruments.All[ModInst(I)].Name;
437 439
438 LoadingFile := False; // HACK!!!! 440 LoadingFile := False; // HACK!!!!
439 441
@@ -543,11 +545,11 @@ begin
543 // TODO: Find some way to synchronize with the playback thread, so it doesn't 545 // TODO: Find some way to synchronize with the playback thread, so it doesn't
544 // fail sometimes. 546 // fail sometimes.
545 547
546 with Song.Instruments[Instr] do 548 with Song.Instruments.All[Instr] do //PLACEHOLDER
547 begin 549 begin
548 case Type_ of 550 case Type_ of
549 itSquare: begin 551 itSquare: begin
550 Regs := SquareInstrumentToRegisters(Freq, True, Song.Instruments[Instr]); 552 Regs := SquareInstrumentToRegisters(Freq, True, Song.Instruments.All[Instr]);
551 Spokeb(NR10, Regs.NR10); 553 Spokeb(NR10, Regs.NR10);
552 Spokeb(NR11, Regs.NR11); 554 Spokeb(NR11, Regs.NR11);
553 Spokeb(NR12, Regs.NR12); 555 Spokeb(NR12, Regs.NR12);
@@ -560,7 +562,7 @@ begin
560 for I := Low(NewWaveform) to High(NewWaveform) do 562 for I := Low(NewWaveform) to High(NewWaveform) do
561 Spokeb(AUD3_WAVE_RAM+I, NewWaveform[I]); 563 Spokeb(AUD3_WAVE_RAM+I, NewWaveform[I]);
562 564
563 Regs := WaveInstrumentToRegisters(Freq, True, Song.Instruments[Instr]); 565 Regs := WaveInstrumentToRegisters(Freq, True, Song.Instruments.All[Instr]);
564 566
565 Spokeb(NR30, Regs.NR30); 567 Spokeb(NR30, Regs.NR30);
566 Spokeb(NR31, Regs.NR31); 568 Spokeb(NR31, Regs.NR31);
@@ -569,7 +571,7 @@ begin
569 Spokeb(NR34, Regs.NR34) 571 Spokeb(NR34, Regs.NR34)
570 end; 572 end;
571 itNoise: begin 573 itNoise: begin
572 Regs := NoiseInstrumentToRegisters(Freq, True, Song.Instruments[Instr]); 574 Regs := NoiseInstrumentToRegisters(Freq, True, Song.Instruments.All[Instr]);
573 Spokeb(NR41, Regs.NR41); 575 Spokeb(NR41, Regs.NR41);
574 Spokeb(NR42, Regs.NR42); 576 Spokeb(NR42, Regs.NR42);
575 Spokeb(NR43, Regs.NR43); 577 Spokeb(NR43, Regs.NR43);
@@ -788,7 +790,11 @@ procedure TfrmTracker.LoadInstrument(Instr: Integer);
788 var 790 var
789 CI: ^TInstrument; 791 CI: ^TInstrument;
790 begin 792 begin
791 CurrentInstrument := @Song.Instruments[Instr]; 793 case CurrentInstrumentBank of
794 itSquare: CurrentInstrument := @Song.Instruments.Duty[Instr];
795 itWave: CurrentInstrument := @Song.Instruments.Wave[Instr];
796 itNoise: CurrentInstrument := @Song.Instruments.Noise[Instr];
797 end;
792 CI := CurrentInstrument; 798 CI := CurrentInstrument;
793 799
794 InstrumentNumberSpinner.Value := Instr; 800 InstrumentNumberSpinner.Value := Instr;
@@ -837,7 +843,7 @@ begin
837 itNoise: begin 843 itNoise: begin
838 ShiftClockTrackbar.Position := CI^.ShiftClockFreq; 844 ShiftClockTrackbar.Position := CI^.ShiftClockFreq;
839 DivRatioTrackbar.Position := CI^.DividingRatio; 845 DivRatioTrackbar.Position := CI^.DividingRatio;
840 SevenBitCounterCheckbox.Checked := CI^.CounterStep = Seven; 846 SevenBitCounterCheckbox.Checked := CI^.CounterStep = swSeven;
841 end; 847 end;
842 end; 848 end;
843 849
@@ -908,9 +914,9 @@ end;
908 procedure TfrmTracker.SevenBitCounterCheckboxChange(Sender: TObject); 914 procedure TfrmTracker.SevenBitCounterCheckboxChange(Sender: TObject);
909 begin 915 begin
910 if SevenBitCounterCheckbox.Checked then 916 if SevenBitCounterCheckbox.Checked then
911 CurrentInstrument^.CounterStep := Seven 917 CurrentInstrument^.CounterStep := swSeven
912 else 918 else
913 CurrentInstrument^.CounterStep := Fifteen; 919 CurrentInstrument^.CounterStep := swFifteen;
914 end; 920 end;
915 921
916 procedure TfrmTracker.SongEditChange(Sender: TObject); 922 procedure TfrmTracker.SongEditChange(Sender: TObject);
@@ -949,20 +955,12 @@ end;
949 955
950 procedure TfrmTracker.InstrumentTypeComboboxChange(Sender: TObject); 956 procedure TfrmTracker.InstrumentTypeComboboxChange(Sender: TObject);
951 begin 957 begin
952 case InstrumentTypeComboBox.Text of 958 case InstrumentTypeCombobox.ItemIndex of
953 'Square': begin 959 0: CurrentInstrumentBank := itSquare;
954 CurrentInstrument^.Type_ := itSquare; 960 1: CurrentInstrumentBank := itWave;
955 ChangeToSquare 961 2: CurrentInstrumentBank := itNoise;
956 end;
957 'Wave': begin
958 CurrentInstrument^.Type_ := itWave;
959 ChangeToWave
960 end;
961 'Noise': begin
962 CurrentInstrument^.Type_ := itNoise;
963 ChangeToNoise
964 end;
965 end; 962 end;
963 LoadInstrument(InstrumentNumberSpinner.Value);
966 end; 964 end;
967 965
968 procedure TfrmTracker.RandomizeNoiseButtonClick(Sender: TObject); 966 procedure TfrmTracker.RandomizeNoiseButtonClick(Sender: TObject);
@@ -1016,6 +1014,7 @@ begin
1016 // Initialize ticks per row 1014 // Initialize ticks per row
1017 Song.TicksPerRow := TicksPerRowSpinEdit.Value; 1015 Song.TicksPerRow := TicksPerRowSpinEdit.Value;
1018 1016
1017 CurrentInstrumentBank := itSquare;
1019 LoadInstrument(1); 1018 LoadInstrument(1);
1020 LoadWave(0); 1019 LoadWave(0);
1021 1020
Modifiedutils.pas +8−49
@@ -5,7 +5,7 @@ unit Utils;
5 interface 5 interface
6 6
7 uses 7 uses
8 Classes, SysUtils, Song, Waves, HugeDatatypes, Constants, gHashSet; 8 Classes, SysUtils, Song, Waves, HugeDatatypes, Constants, gHashSet, fgl;
9 9
10 type 10 type
11 11
@@ -17,16 +17,6 @@ type
17 17
18 TUsedMap = specialize THashSet<Integer, TIntegerHash>; 18 TUsedMap = specialize THashSet<Integer, TIntegerHash>;
19 19
20 { TOrderMapHelper }
21
22 TOrderMapHelper = class helper for TPatternMap
23 function GetOrCreateNew(Key: Integer): PPattern;
24 function CreateNewPattern(Key: Integer): PPattern;
25 function MaxKey: Integer;
26
27 procedure DeletePattern(Key: Integer);
28 end;
29
30 { TSongUsageReport } 20 { TSongUsageReport }
31 21
32 TSongUsageReport = record 22 TSongUsageReport = record
@@ -46,6 +36,8 @@ procedure BlankCell(var Cell: TCell);
46 function EffectCodeToStr(Code: Integer; Params: TEffectParams): String; 36 function EffectCodeToStr(Code: Integer; Params: TEffectParams): String;
47 function EffectToExplanation(Code: Integer; Params: TEffectParams): String; 37 function EffectToExplanation(Code: Integer; Params: TEffectParams): String;
48 38
39 function ModInst(Inst: Integer): Integer;
40
49 function GetUsageReport(Song: TSong): TSongUsageReport; 41 function GetUsageReport(Song: TSong): TSongUsageReport;
50 procedure FreeUsageReport(Report: TSongUsageReport); 42 procedure FreeUsageReport(Report: TSongUsageReport);
51 43
@@ -58,44 +50,6 @@ begin
58 Result := I mod N; 50 Result := I mod N;
59 end; 51 end;
60 52
61 { TOrderMapHelper }
62
63 function TOrderMapHelper.GetOrCreateNew(Key: Integer): PPattern;
64 begin
65 if Self.IndexOf(Key) <> -1 then
66 Result := Self.KeyData[Key]
67 else begin
68 New(Result);
69 BlankPattern(Result);
70 Self.Add(Key, Result);
71 end;
72 end;
73
74 function TOrderMapHelper.CreateNewPattern(Key: Integer): PPattern;
75 begin
76 if IndexOf(Key) <> -1 then Exit(KeyData[Key]);
77
78 New(Result);
79 BlankPattern(Result);
80 Self.Add(Key, Result);
81 end;
82
83 function TOrderMapHelper.MaxKey: Integer;
84 var
85 X: Integer;
86 begin
87 Result := 0;
88 for X := 0 to Self.Count-1 do
89 if Self.Keys[X] > Result then Result := Self.Keys[X];
90 Inc(Result);
91 end;
92
93 procedure TOrderMapHelper.DeletePattern(Key: Integer);
94 begin
95 Dispose(KeyData[Key]);
96 Self.Remove(Key);
97 end;
98
99 function Lerp(v0, v1, t: Double): Double; 53 function Lerp(v0, v1, t: Double): Double;
100 begin 54 begin
101 Result := ((1 - t) * v0) + (t * v1); 55 Result := ((1 - t) * v0) + (t * v1);
@@ -156,6 +110,11 @@ begin
156 end; 110 end;
157 end; 111 end;
158 112
113 function ModInst(Inst: Integer): Integer;
114 begin
115 Result := ((Inst-1) mod 15)+1;
116 end;
117
159 function GetUsageReport(Song: TSong): TSongUsageReport; 118 function GetUsageReport(Song: TSong): TSongUsageReport;
160 var 119 var
161 I, J, X, Y: Integer; 120 I, J, X, Y: Integer;