Commit 57f2d36

Nick committed on
More WIP GBT import. Only thing left is noise channel...
commit 57f2d36afc848ce3aa0622b142676e53fb123a9c parent c389751
4 changed files +114−54
Modifiedinstruments.pas +14−14
@@ -8,7 +8,7 @@ uses
8 Classes, SysUtils; 8 Classes, SysUtils;
9 9
10 type 10 type
11 TInstrumentType = (Square, Wave, Noise); 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 = (Fifteen, Seven);
@@ -27,7 +27,7 @@ type
27 VolSweepDirection: TSweepType; 27 VolSweepDirection: TSweepType;
28 VolSweepAmount: TEnvelopeSweepAmount; 28 VolSweepAmount: TEnvelopeSweepAmount;
29 29
30 // Square 30 // itSquare
31 // NR10 31 // NR10
32 SweepTime: Integer; 32 SweepTime: Integer;
33 SweepIncDec: TSweepType; 33 SweepIncDec: TSweepType;
@@ -36,14 +36,14 @@ type
36 // NR11 36 // NR11
37 Duty: TDutyType; 37 Duty: TDutyType;
38 38
39 // Wave 39 // itWave
40 40
41 // NR32 41 // NR32
42 OutputLevel: Integer; 42 OutputLevel: Integer;
43 // Wave 43 // itWave
44 Waveform: Integer; 44 Waveform: Integer;
45 45
46 // Noise 46 // itNoise
47 // NR42 47 // NR42
48 ShiftClockFreq: Integer; // Unused 48 ShiftClockFreq: Integer; // Unused
49 CounterStep: TStepWidth; 49 CounterStep: TStepWidth;
@@ -54,9 +54,9 @@ type
54 54
55 TRegisters = record 55 TRegisters = record
56 case Type_: TInstrumentType of 56 case Type_: TInstrumentType of
57 Square: (NR10, NR11, NR12, NR13, NR14: Byte); 57 itSquare: (NR10, NR11, NR12, NR13, NR14: Byte);
58 Wave: (NR30, NR31, NR32, NR33, NR34: Byte); 58 itWave: (NR30, NR31, NR32, NR33, NR34: Byte);
59 Noise: (NR41, NR42, NR43, NR44: Byte); 59 itNoise: (NR41, NR42, NR43, NR44: Byte);
60 end; 60 end;
61 61
62 Bit = Boolean; 62 Bit = Boolean;
@@ -215,9 +215,9 @@ end;
215 function InstrumentToBytes(Instrument: TInstrument): TAsmInstrument; 215 function InstrumentToBytes(Instrument: TInstrument): TAsmInstrument;
216 begin 216 begin
217 case Instrument.Type_ of 217 case Instrument.Type_ of
218 Square: Result := SquareInstrumentToBytes(Instrument); 218 itSquare: Result := SquareInstrumentToBytes(Instrument);
219 Wave: Result := WaveInstrumentToBytes(Instrument); 219 itWave: Result := WaveInstrumentToBytes(Instrument);
220 Noise: Result := NoiseInstrumentToBytes(Instrument); 220 itNoise: Result := NoiseInstrumentToBytes(Instrument);
221 end; 221 end;
222 end; 222 end;
223 223
@@ -250,7 +250,7 @@ begin
250 NR34.FrequencyBits := (Frequency and %0000011100000000) shr 8; 250 NR34.FrequencyBits := (Frequency and %0000011100000000) shr 8;
251 NR34.UseLength := Instr.LengthEnabled; 251 NR34.UseLength := Instr.LengthEnabled;
252 252
253 Result.Type_ := Wave; 253 Result.Type_ := itWave;
254 Result.NR30 := NR30.ByteValue; 254 Result.NR30 := NR30.ByteValue;
255 Result.NR31 := NR31; 255 Result.NR31 := NR31;
256 Result.NR32 := NR32.ByteValue; 256 Result.NR32 := NR32.ByteValue;
@@ -287,7 +287,7 @@ begin
287 NR44.Initial:= Initial; 287 NR44.Initial:= Initial;
288 NR44.UseLength:=Instr.LengthEnabled; 288 NR44.UseLength:=Instr.LengthEnabled;
289 289
290 Result.Type_ := Noise; 290 Result.Type_ := itNoise;
291 Result.NR41 := NR41; 291 Result.NR41 := NR41;
292 Result.NR42 := NR42.ByteValue; 292 Result.NR42 := NR42.ByteValue;
293 Result.NR43 := NR43.ByteValue; 293 Result.NR43 := NR43.ByteValue;
@@ -328,7 +328,7 @@ begin
328 NR14.Initial := Initial; 328 NR14.Initial := Initial;
329 NR14.UseLength := Instr.LengthEnabled; 329 NR14.UseLength := Instr.LengthEnabled;
330 330
331 Result.Type_ := Square; 331 Result.Type_ := itSquare;
332 Result.NR10:=NR10.ByteValue; 332 Result.NR10:=NR10.ByteValue;
333 Result.NR11:=NR11.ByteValue; 333 Result.NR11:=NR11.ByteValue;
334 Result.NR12:=NR12.ByteValue; 334 Result.NR12:=NR12.ByteValue;
Modifiedmodimport.pas +86−26
@@ -5,7 +5,8 @@ unit MODImport;
5 interface 5 interface
6 6
7 uses 7 uses
8 Classes, SysUtils, Song, hugedatatypes, fgl, utils, constants; 8 Classes, SysUtils, Song, hugedatatypes, fgl, math, utils, constants,
9 instruments;
9 10
10 type 11 type
11 TPeriodToCodeMap = specialize TFPGMap<Integer, Integer>; 12 TPeriodToCodeMap = specialize TFPGMap<Integer, Integer>;
@@ -65,6 +66,18 @@ type
65 66
66 function LoadSongFromModStream(Stream: TStream): TSong; 67 function LoadSongFromModStream(Stream: TStream): TSong;
67 68
69 const
70 // https://github.com/AntonioND/gbt-player/blob/master/rgbds_example/gbt_player_bank1.asm
71 GBT_WAVEFORMS: array[0..7] of array[0..15] of Byte =
72 (($A5,$D7,$C9,$E1,$BC,$9A,$76,$31,$0C,$BA,$DE,$60,$1B,$CA,$03,$93),
73 ($F0,$E1,$D2,$C3,$B4,$A5,$96,$87,$78,$69,$5A,$4B,$3C,$2D,$1E,$0F),
74 ($FD,$EC,$DB,$CA,$B9,$A8,$97,$86,$79,$68,$57,$46,$35,$24,$13,$02),
75 ($DE,$FE,$DC,$BA,$9A,$A9,$87,$77,$88,$87,$65,$56,$54,$32,$10,$12),
76 ($AB,$CD,$EF,$ED,$CB,$A0,$12,$3E,$DC,$BA,$BC,$DE,$FE,$DC,$32,$10),
77 ($FF,$EE,$DD,$CC,$BB,$AA,$99,$88,$77,$66,$55,$44,$33,$22,$11,$00),
78 ($FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$00,$00,$00,$00,$00,$00,$00),
79 ($79,$BC,$DE,$EF,$FF,$EE,$DC,$B9,$75,$43,$21,$10,$00,$11,$23,$45));
80
68 var 81 var
69 PeriodsToCodeMap: TPeriodToCodeMap; 82 PeriodsToCodeMap: TPeriodToCodeMap;
70 83
@@ -88,24 +101,37 @@ end;
88 101
89 function ConvertInstrument(Instr: Integer): Integer; 102 function ConvertInstrument(Instr: Integer): Integer;
90 begin 103 begin
91 if Instr = 0 then 104 Result := EnsureRange(Instr, 0, 15);
92 Result := 0
93 else
94 Result := 1;
95 end; 105 end;
96 106
97 procedure ConvertEffect(Code, Params: Integer; out OutCode: Integer; out OutParams: TEffectParams); 107 procedure ConvertEffect(Code, Params: Integer; out OutCode: Integer; out OutParams: TEffectParams);
108 var
109 EP: TEffectParams absolute Params;
110 label IdentityEffect;
98 begin 111 begin
99 case Code of 112 if Code in [$F, $B, $D] then begin
100 $C: begin 113 OutCode := Code;
101 OutCode := $C; 114 OutParams.Value := Params + 1;
102 OutParams.Value := ;
103 end;
104 else begin
105 OutCode := Code;
106 OutParams := Params;
107 end;
108 end 115 end
116 else
117 case Code of
118 $C: begin
119 OutCode := $C;
120 OutParams.Value := Trunc((Params / $40)*$F);
121 end;
122 $E: begin
123 if EP.Param1 = $C then begin
124 OutCode := $E;
125 OutParams.Value := EP.Param2;
126 end
127 else goto IdentityEffect;
128 end;
129 else begin
130 IdentityEffect:
131 OutCode := Code;
132 OutParams.Value := Params;
133 end;
134 end
109 end; 135 end;
110 136
111 function ConvertCell(MC: TMODRow): TCell; 137 function ConvertCell(MC: TMODRow): TCell;
@@ -115,15 +141,25 @@ begin
115 ConvertEffect(MC.Effect.Code, MC.Effect.Params, Result.EffectCode, Result.EffectParams); 141 ConvertEffect(MC.Effect.Code, MC.Effect.Params, Result.EffectCode, Result.EffectParams);
116 end; 142 end;
117 143
118 procedure TranscribePattern(MP: TMODPattern; P1, P2, P3, P4: PPattern); 144 procedure TranscribeColumn(MP: TMODPattern; Pat: PPattern; Column: Integer);
119 var 145 var
120 I: Integer; 146 I: Integer;
147 LastPlayedNote: Integer;
148 LastPlayedInstrument: Integer;
121 begin 149 begin
150 LastPlayedNote := C_5;
151 LastPlayedInstrument := 0;
152
122 for I := Low(MP) to High(MP) do begin 153 for I := Low(MP) to High(MP) do begin
123 P1^[I] := ConvertCell(MP[I, 1]); 154 Pat^[I] := ConvertCell(MP[I, Column]);
124 P2^[I] := ConvertCell(MP[I, 2]); 155
125 P3^[I] := ConvertCell(MP[I, 3]); 156 if (Pat^[I].EffectCode = $C) and (Pat^[I].Note = NO_NOTE) then begin
126 P4^[I] := ConvertCell(MP[I, 4]); 157 Pat^[I].Note := LastPlayedNote;
158 Pat^[I].Instrument := LastPlayedInstrument;
159 end;
160
161 if (Pat^[I].Note <> NO_NOTE) then LastPlayedNote := Pat^[I].Note;
162 if (Pat^[I].Instrument <> 0) then LastPlayedInstrument := Pat^[I].Instrument;
127 end; 163 end;
128 end; 164 end;
129 165
@@ -157,15 +193,39 @@ begin
157 193
158 InitializeSong(Result); 194 InitializeSong(Result);
159 195
160 for I := Low(ModFile.Patterns) to High(ModFile.Patterns) do 196 // Create the instruments.
161 TranscribePattern(ModFile.Patterns[I], 197
162 Result.Patterns.CreateNewPattern(I*10 + 0), 198 // First four are just the default instrument with a different duty cycle.
163 Result.Patterns.CreateNewPattern(I*10 + 1), 199 Result.Instruments[1].Duty := 1;
164 Result.Patterns.CreateNewPattern(I*10 + 2), 200 Result.Instruments[2].Duty := 2;
165 Result.Patterns.CreateNewPattern(I*10 + 3)); 201 Result.Instruments[3].Duty := 3;
202 Result.Instruments[4].Duty := 0;
203
204 for I := 8 to 15 do
205 with Result.Instruments[I] do begin
206 Waveform := I - 8;
207 Type_ := itWave;
208 end;
209
210 // Waveforms.
211 for I := Low(GBT_WAVEFORMS) to High(GBT_WAVEFORMS) do
212 for J := Low(GBT_WAVEFORMS[I]) to High(GBT_WAVEFORMS[I]) do begin
213 Result.Waves[I, J*2] := hi(GBT_WAVEFORMS[I, J]);
214 Result.Waves[I, (J*2) + 1] := lo(GBT_WAVEFORMS[I, J]);
215 end;
216
217 // Convert all patterns
218 for I := Low(ModFile.Patterns) to High(ModFile.Patterns) do begin
219 TranscribeColumn(ModFile.Patterns[I], Result.Patterns.CreateNewPattern(I*10 + 0), 1);
220 TranscribeColumn(ModFile.Patterns[I], Result.Patterns.CreateNewPattern(I*10 + 1), 2);
221 TranscribeColumn(ModFile.Patterns[I], Result.Patterns.CreateNewPattern(I*10 + 2), 3);
222 TranscribeColumn(ModFile.Patterns[I], Result.Patterns.CreateNewPattern(I*10 + 3), 4);
223 end;
166 224
225 // Import the order table. Uses a weird numbering scheme because hUGE has
226 // 4 separate patterns like AHX and unlike MOD.
167 for I := Low(Result.OrderMatrix) to High(Result.OrderMatrix) do begin 227 for I := Low(Result.OrderMatrix) to High(Result.OrderMatrix) do begin
168 SetLength(Result.OrderMatrix[I], ModFile.SongLen); 228 SetLength(Result.OrderMatrix[I], ModFile.SongLen+1);
169 229
170 for J := 0 to ModFile.SongLen do 230 for J := 0 to ModFile.SongLen do
171 Result.OrderMatrix[I, J] := (ModFile.Positions[J]*10) + I; 231 Result.OrderMatrix[I, J] := (ModFile.Positions[J]*10) + I;
Modifiedsong.pas +1−1
@@ -199,7 +199,7 @@ begin
199 end; 199 end;
200 for I := Low(S.Instruments) to High(S.Instruments) do 200 for I := Low(S.Instruments) to High(S.Instruments) do
201 with S.Instruments[I] do begin 201 with S.Instruments[I] do begin
202 Type_ := Square; 202 Type_ := itSquare;
203 Length := 0; 203 Length := 0;
204 LengthEnabled := False; 204 LengthEnabled := False;
205 InitialVolume := High(TEnvelopeVolume); 205 InitialVolume := High(TEnvelopeVolume);
Modifiedtracker.pas +13−13
@@ -533,7 +533,7 @@ begin
533 with Song.Instruments[Instr] do 533 with Song.Instruments[Instr] do
534 begin 534 begin
535 case Type_ of 535 case Type_ of
536 Square: begin 536 itSquare: begin
537 Regs := SquareInstrumentToRegisters(Freq, True, Song.Instruments[Instr]); 537 Regs := SquareInstrumentToRegisters(Freq, True, Song.Instruments[Instr]);
538 Spokeb(NR10, Regs.NR10); 538 Spokeb(NR10, Regs.NR10);
539 Spokeb(NR11, Regs.NR11); 539 Spokeb(NR11, Regs.NR11);
@@ -541,9 +541,9 @@ begin
541 Spokeb(NR13, Regs.NR13); 541 Spokeb(NR13, Regs.NR13);
542 Spokeb(NR14, Regs.NR14); 542 Spokeb(NR14, Regs.NR14);
543 end; 543 end;
544 Wave: begin 544 itWave: begin
545 NewWaveform := ConvertWaveform(Song.Waves[Waveform]); 545 NewWaveform := ConvertWaveform(Song.Waves[Waveform]);
546 // Fill Wave RAM with the waveform 546 // Fill itWave RAM with the waveform
547 for I := Low(NewWaveform) to High(NewWaveform) do 547 for I := Low(NewWaveform) to High(NewWaveform) do
548 Spokeb(AUD3_WAVE_RAM+I, NewWaveform[I]); 548 Spokeb(AUD3_WAVE_RAM+I, NewWaveform[I]);
549 549
@@ -555,7 +555,7 @@ begin
555 Spokeb(NR33, Regs.NR33); 555 Spokeb(NR33, Regs.NR33);
556 Spokeb(NR34, Regs.NR34) 556 Spokeb(NR34, Regs.NR34)
557 end; 557 end;
558 Noise: begin 558 itNoise: begin
559 Regs := NoiseInstrumentToRegisters(Freq, True, Song.Instruments[Instr]); 559 Regs := NoiseInstrumentToRegisters(Freq, True, Song.Instruments[Instr]);
560 Spokeb(NR41, Regs.NR41); 560 Spokeb(NR41, Regs.NR41);
561 Spokeb(NR42, Regs.NR42); 561 Spokeb(NR42, Regs.NR42);
@@ -784,15 +784,15 @@ begin
784 LengthTrackbar.Position := CI^.Length; 784 LengthTrackbar.Position := CI^.Length;
785 785
786 case CI^.Type_ of 786 case CI^.Type_ of
787 Square: begin 787 itSquare: begin
788 InstrumentTypeComboBox.Text := 'Square'; 788 InstrumentTypeComboBox.Text := 'Square';
789 ChangeToSquare; 789 ChangeToSquare;
790 end; 790 end;
791 Wave: begin 791 itWave: begin
792 InstrumentTypeComboBox.Text := 'Wave'; 792 InstrumentTypeComboBox.Text := 'Wave';
793 ChangeToWave; 793 ChangeToWave;
794 end; 794 end;
795 Noise: begin 795 itNoise: begin
796 InstrumentTypeComboBox.Text := 'Noise'; 796 InstrumentTypeComboBox.Text := 'Noise';
797 ChangeToNoise; 797 ChangeToNoise;
798 end; 798 end;
@@ -806,7 +806,7 @@ begin
806 EnvChangeTrackbar.Position := CI^.VolSweepAmount; 806 EnvChangeTrackbar.Position := CI^.VolSweepAmount;
807 807
808 case CI^.Type_ of 808 case CI^.Type_ of
809 Square: begin 809 itSquare: begin
810 SweepTimeCombobox.ItemIndex := CI^.SweepTime; 810 SweepTimeCombobox.ItemIndex := CI^.SweepTime;
811 case CI^.SweepIncDec of 811 case CI^.SweepIncDec of
812 Up: SweepDirectionCombobox.Text := 'Up'; 812 Up: SweepDirectionCombobox.Text := 'Up';
@@ -816,12 +816,12 @@ begin
816 DutyCombobox.ItemIndex := CI^.Duty; 816 DutyCombobox.ItemIndex := CI^.Duty;
817 end; 817 end;
818 818
819 Wave: begin 819 itWave: begin
820 WaveVolumeCombobox.ItemIndex := CI^.OutputLevel; 820 WaveVolumeCombobox.ItemIndex := CI^.OutputLevel;
821 WaveformCombobox.ItemIndex := CI^.Waveform; 821 WaveformCombobox.ItemIndex := CI^.Waveform;
822 end; 822 end;
823 823
824 Noise: begin 824 itNoise: begin
825 ShiftClockTrackbar.Position := CI^.ShiftClockFreq; 825 ShiftClockTrackbar.Position := CI^.ShiftClockFreq;
826 DivRatioTrackbar.Position := CI^.DividingRatio; 826 DivRatioTrackbar.Position := CI^.DividingRatio;
827 SevenBitCounterCheckbox.Checked := CI^.CounterStep = Seven; 827 SevenBitCounterCheckbox.Checked := CI^.CounterStep = Seven;
@@ -938,15 +938,15 @@ procedure TfrmTracker.InstrumentTypeComboboxChange(Sender: TObject);
938 begin 938 begin
939 case InstrumentTypeComboBox.Text of 939 case InstrumentTypeComboBox.Text of
940 'Square': begin 940 'Square': begin
941 CurrentInstrument^.Type_ := Square; 941 CurrentInstrument^.Type_ := itSquare;
942 ChangeToSquare 942 ChangeToSquare
943 end; 943 end;
944 'Wave': begin 944 'Wave': begin
945 CurrentInstrument^.Type_ := Wave; 945 CurrentInstrument^.Type_ := itWave;
946 ChangeToWave 946 ChangeToWave
947 end; 947 end;
948 'Noise': begin 948 'Noise': begin
949 CurrentInstrument^.Type_ := Noise; 949 CurrentInstrument^.Type_ := itNoise;
950 ChangeToNoise 950 ChangeToNoise
951 end; 951 end;
952 end; 952 end;