Commit bf10cbc

Nick committed on
Getting emulator core wired up.. Noise instrument preview working
commit bf10cbc65b4769c7d756551847ec6875771ed309 parent f9f27a8
6 changed files +314−6
ModifiedGBEmu.lpi +11−1
@@ -63,7 +63,7 @@
63 <PackageName Value="LCL"/> 63 <PackageName Value="LCL"/>
64 </Item6> 64 </Item6>
65 </RequiredPackages> 65 </RequiredPackages>
66 <Units Count="15"> 66 <Units Count="17">
67 <Unit0> 67 <Unit0>
68 <Filename Value="GBEmu.lpr"/> 68 <Filename Value="GBEmu.lpr"/>
69 <IsPartOfProject Value="True"/> 69 <IsPartOfProject Value="True"/>
@@ -138,6 +138,16 @@
138 <IsPartOfProject Value="True"/> 138 <IsPartOfProject Value="True"/>
139 <UnitName Value="Song"/> 139 <UnitName Value="Song"/>
140 </Unit14> 140 </Unit14>
141 <Unit15>
142 <Filename Value="emulationthread.pas"/>
143 <IsPartOfProject Value="True"/>
144 <UnitName Value="EmulationThread"/>
145 </Unit15>
146 <Unit16>
147 <Filename Value="utils.pas"/>
148 <IsPartOfProject Value="True"/>
149 <UnitName Value="Utils"/>
150 </Unit16>
141 </Units> 151 </Units>
142 </ProjectOptions> 152 </ProjectOptions>
143 <CompilerOptions> 153 <CompilerOptions>
Addedemulationthread.pas +89−0
@@ -0,0 +1,89 @@
1 unit EmulationThread;
2
3 {$mode delphi}
4
5 interface
6
7 uses
8 {$ifdef unix}
9 cthreads,
10 cmem, // the c memory manager is on some systems much faster for multi-threading
11 {$endif}
12 Classes, SysUtils;
13
14 type
15 TEmulationThread = class(TThread)
16 private
17 //stuff
18 protected
19 procedure Execute; override;
20 public
21 Constructor Create;
22 end;
23
24 implementation
25
26 uses sound, mainloop, vars, machine,
27 windows;
28
29 const
30 CyclesPerFrame : Integer = 70224;
31 TimePerFrame: Double = 1.0 / 60.0;
32
33 procedure TEmulationThread.Execute;
34 var
35 li: Large_Integer;
36 tickFreq, cycles: Integer;
37 frameStart, frameEnd: Integer;
38 frameElapsedInSec: Double;
39 function GetCounter: Integer;
40 begin
41 QueryPerformanceCounter(@li);
42 Result := li.QuadPart
43 end;
44 begin
45 lastTime := 0;
46
47 cycles := 0;
48
49 QueryPerformanceFrequency(@li);
50 tickFreq := li.QuadPart;
51 FrameStart := GetCounter;
52
53 repeat
54 while (cycles < CyclesPerFrame) do
55 cycles += z80_decode;
56
57 cycles -= CyclesPerFrame;
58
59 repeat
60 FrameEnd := GetCounter;
61
62 frameElapsedInSec := (frameEnd - frameStart) / tickFreq;
63 until (frameElapsedInSec > TimePerFrame) and (not SoundBufferTooFull);
64
65 frameStart := frameEnd;
66 until Terminated;
67 end;
68
69 constructor TEmulationThread.Create;
70 begin
71 inherited Create(True);
72 FreeOnTerminate := True;
73 z80_reset;
74 ResetSound;
75 enablesound;
76
77 load('../../halt.gb');
78
79 {halt_mode := 1;
80 z80_decode;
81 Spokeb($FF1A, $80);
82 z80_decode;
83 Spokeb($FF25, $FF);
84 z80_decode;
85 Spokeb($FF24, $77);}
86 end;
87
88 end.
89
Addedhalt.z80 +26−0
@@ -0,0 +1,26 @@
1 include "hugedriver/hardware.inc"
2 SECTION "init", ROM0[$0100]
3 jp yeah
4
5
6 SECTION "romname", ROM0[$0134]
7 ; $0134 - $013E: The title, in upper-case letters, followed by zeroes.
8 DB "HALT"
9 DS 7 ; padding
10 ; $013F - $0142: The manufacturer code. Empty for now
11 DS 4
12 DS 1
13 ; $0144 - $0145: "New" Licensee Code, a two character name.
14 DB "NF"
15
16 SECTION "code", ROM0
17 yeah:
18 ld a, $80
19 ld [rAUDENA], a
20 ; Enable all channels in stereo
21 ld a, $FF
22 ld [rAUDTERM], a
23 ; Set volume
24 ld a, $77
25 ld [rAUDVOL], a
26 halt
Modifiedtracker.lfm +19−4
@@ -50,9 +50,9 @@ object frmTracker: TfrmTracker
50 Height = 685 50 Height = 685
51 Top = 0 51 Top = 0
52 Width = 1108 52 Width = 1108
53 ActivePage = CommentsTabSheet 53 ActivePage = InstrumentTabSheet
54 Align = alClient 54 Align = alClient
55 TabIndex = 3 55 TabIndex = 2
56 TabOrder = 0 56 TabOrder = 0
57 object GeneralTabSheet: TTabSheet 57 object GeneralTabSheet: TTabSheet
58 Caption = 'General' 58 Caption = 'General'
@@ -88,6 +88,7 @@ object frmTracker: TfrmTracker
88 Height = 23 88 Height = 23
89 Top = 8 89 Top = 8
90 Width = 216 90 Width = 216
91 OnChange = SongEditChange
91 TabOrder = 0 92 TabOrder = 0
92 end 93 end
93 object ArtistEdit: TEdit 94 object ArtistEdit: TEdit
@@ -95,6 +96,7 @@ object frmTracker: TfrmTracker
95 Height = 23 96 Height = 23
96 Top = 40 97 Top = 40
97 Width = 216 98 Width = 216
99 OnChange = ArtistEditChange
98 TabOrder = 1 100 TabOrder = 1
99 end 101 end
100 end 102 end
@@ -122,7 +124,6 @@ object frmTracker: TfrmTracker
122 Top = 0 124 Top = 0
123 Width = 1100 125 Width = 1100
124 Align = alTop 126 Align = alTop
125 Caption = 'Panel3'
126 ClientHeight = 336 127 ClientHeight = 336
127 ClientWidth = 1100 128 ClientWidth = 1100
128 TabOrder = 0 129 TabOrder = 0
@@ -1354,7 +1355,17 @@ object frmTracker: TfrmTracker
1354 Height = 23 1355 Height = 23
1355 Top = 887 1356 Top = 887
1356 Width = 1306 1357 Width = 1306
1357 Panels = <> 1358 Panels = <
1359 item
1360 Width = 200
1361 end
1362 item
1363 Width = 200
1364 end
1365 item
1366 Width = 200
1367 end>
1368 SimplePanel = False
1358 end 1369 end
1359 object MainMenu1: TMainMenu 1370 object MainMenu1: TMainMenu
1360 left = 928 1371 left = 928
@@ -1374,5 +1385,9 @@ object frmTracker: TfrmTracker
1374 Caption = 'About hUGETracker' 1385 Caption = 'About hUGETracker'
1375 end 1386 end
1376 end 1387 end
1388 object MenuItem6: TMenuItem
1389 Caption = 'Debug shite'
1390 OnClick = MenuItem6Click
1391 end
1377 end 1392 end
1378 end 1393 end
Modifiedtracker.pas +76−1
@@ -7,7 +7,8 @@ interface
7 uses 7 uses
8 Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, ComCtrls, 8 Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, ComCtrls,
9 Menus, Spin, StdCtrls, SynEdit, VirtualTrees, ECSlider, ECProgressBar, 9 Menus, Spin, StdCtrls, SynEdit, VirtualTrees, ECSlider, ECProgressBar,
10 instruments, song; 10 Instruments, Song, EmulationThread, Utils,
11 mainloop, sound, vars, machine;
11 12
12 type 13 type
13 { TfrmTracker } 14 { TfrmTracker }
@@ -15,6 +16,7 @@ type
15 TfrmTracker = class(TForm) 16 TfrmTracker = class(TForm)
16 CommentMemo: TMemo; 17 CommentMemo: TMemo;
17 Label19: TLabel; 18 Label19: TLabel;
19 MenuItem6: TMenuItem;
18 RoutineNumberSpinner: TSpinEdit; 20 RoutineNumberSpinner: TSpinEdit;
19 Label17: TLabel; 21 Label17: TLabel;
20 EnvelopePaintbox: TPaintBox; 22 EnvelopePaintbox: TPaintBox;
@@ -85,6 +87,7 @@ type
85 NoiseFreqSpinner: TECSpinPosition; 87 NoiseFreqSpinner: TECSpinPosition;
86 DivRatioSpinner: TECSpinPosition; 88 DivRatioSpinner: TECSpinPosition;
87 TreeView1: TTreeView; 89 TreeView1: TTreeView;
90 procedure ArtistEditChange(Sender: TObject);
88 procedure CommentMemoChange(Sender: TObject); 91 procedure CommentMemoChange(Sender: TObject);
89 procedure DirectionComboBoxChange(Sender: TObject); 92 procedure DirectionComboBoxChange(Sender: TObject);
90 procedure DivRatioSpinnerChange(Sender: TObject); 93 procedure DivRatioSpinnerChange(Sender: TObject);
@@ -95,12 +98,14 @@ type
95 procedure InstrumentNameEditChange(Sender: TObject); 98 procedure InstrumentNameEditChange(Sender: TObject);
96 procedure InstrumentNumberSpinnerChange(Sender: TObject); 99 procedure InstrumentNumberSpinnerChange(Sender: TObject);
97 procedure LengthSpinnerChange(Sender: TObject); 100 procedure LengthSpinnerChange(Sender: TObject);
101 procedure MenuItem6Click(Sender: TObject);
98 procedure NoiseFreqSpinnerChange(Sender: TObject); 102 procedure NoiseFreqSpinnerChange(Sender: TObject);
99 procedure RandomizeNoiseButtonClick(Sender: TObject); 103 procedure RandomizeNoiseButtonClick(Sender: TObject);
100 procedure InstrumentTypeComboboxChange(Sender: TObject); 104 procedure InstrumentTypeComboboxChange(Sender: TObject);
101 procedure LengthEnabledCheckboxChange(Sender: TObject); 105 procedure LengthEnabledCheckboxChange(Sender: TObject);
102 procedure PaintBox1Paint(Sender: TObject); 106 procedure PaintBox1Paint(Sender: TObject);
103 procedure SevenBitCounterCheckboxChange(Sender: TObject); 107 procedure SevenBitCounterCheckboxChange(Sender: TObject);
108 procedure SongEditChange(Sender: TObject);
104 procedure StartVolSpinnerChange(Sender: TObject); 109 procedure StartVolSpinnerChange(Sender: TObject);
105 procedure SweepDirectionComboboxChange(Sender: TObject); 110 procedure SweepDirectionComboboxChange(Sender: TObject);
106 procedure SweepSizeSpinnerChange(Sender: TObject); 111 procedure SweepSizeSpinnerChange(Sender: TObject);
@@ -111,10 +116,14 @@ type
111 Song: TSong; 116 Song: TSong;
112 CurrentInstrument: ^TInstrument; 117 CurrentInstrument: ^TInstrument;
113 118
119 EmulationThread: TThread;
120
114 procedure ChangeToSquare; 121 procedure ChangeToSquare;
115 procedure ChangeToWave; 122 procedure ChangeToWave;
116 procedure ChangeToNoise; 123 procedure ChangeToNoise;
117 procedure LoadInstrument(Instr: Integer); 124 procedure LoadInstrument(Instr: Integer);
125
126 procedure PlayC4WithInstrument(Instr: Integer);
118 public 127 public
119 128
120 end; 129 end;
@@ -128,6 +137,44 @@ implementation
128 137
129 { TfrmTracker } 138 { TfrmTracker }
130 139
140 const
141 NR10 = $FF10;
142 NR11 = $FF11;
143 NR12 = $FF12;
144 NR13 = $FF13;
145 NR14 = $FF14;
146 NR21 = $FF16;
147 NR22 = $FF17;
148 NR23 = $FF18;
149 NR24 = $FF19;
150 NR30 = $FF1A;
151 NR31 = $FF1B;
152 NR32 = $FF1C;
153 NR33 = $FF1D;
154 NR34 = $FF1E;
155 NR41 = $FF20;
156 NR42 = $FF21;
157 NR43 = $FF22;
158 NR44 = $FF23;
159
160 procedure TfrmTracker.PlayC4WithInstrument(Instr: Integer);
161 var
162 Regs: TRegisters;
163 begin
164 with Song.Instruments[Instr] do
165 begin
166 case Type_ of
167 Noise: begin
168 Regs := NoiseInstrumentToRegisters(True, Song.Instruments[Instr]);
169 Spokeb(NR41, Regs.NR41);
170 Spokeb(NR42, Regs.NR42);
171 Spokeb(NR43, Regs.NR43);
172 Spokeb(NR44, Regs.NR44);
173 end;
174 end;
175 end;
176 end;
177
131 procedure TfrmTracker.LoadInstrument(Instr: Integer); 178 procedure TfrmTracker.LoadInstrument(Instr: Integer);
132 var 179 var
133 CI: ^TInstrument; 180 CI: ^TInstrument;
@@ -230,6 +277,11 @@ begin
230 CurrentInstrument^.CounterStep := Fifteen; 277 CurrentInstrument^.CounterStep := Fifteen;
231 end; 278 end;
232 279
280 procedure TfrmTracker.SongEditChange(Sender: TObject);
281 begin
282 Song.Name := SongEdit.Text;
283 end;
284
233 procedure TfrmTracker.StartVolSpinnerChange(Sender: TObject); 285 procedure TfrmTracker.StartVolSpinnerChange(Sender: TObject);
234 begin 286 begin
235 CurrentInstrument^.InitialVolume := Round(StartVolSpinner.Position); 287 CurrentInstrument^.InitialVolume := Round(StartVolSpinner.Position);
@@ -276,6 +328,10 @@ begin
276 NoiseFreqSpinner.Position := Random(Round(NoiseFreqSpinner.Max)); 328 NoiseFreqSpinner.Position := Random(Round(NoiseFreqSpinner.Max));
277 DivRatioSpinner.Position := Random(Round(DivRatioSpinner.Max)); 329 DivRatioSpinner.Position := Random(Round(DivRatioSpinner.Max));
278 SevenBitCounterCheckbox.Checked := Random <= 0.5; 330 SevenBitCounterCheckbox.Checked := Random <= 0.5;
331 LengthEnabledCheckbox.Checked := Random <= 0.5;
332 LengthSpinner.Position := Random(Round(LengthSpinner.Max));
333
334 PlayC4WithInstrument(InstrumentNumberSpinner.Value);
279 end; 335 end;
280 336
281 procedure TfrmTracker.FormCreate(Sender: TObject); 337 procedure TfrmTracker.FormCreate(Sender: TObject);
@@ -299,6 +355,10 @@ begin
299 end; 355 end;
300 356
301 LoadInstrument(1); 357 LoadInstrument(1);
358
359 // Get the emulator ready to make sound...
360 EmulationThread := TEmulationThread.Create;
361 EmulationThread.Start;
302 end; 362 end;
303 363
304 procedure TfrmTracker.DirectionComboBoxChange(Sender: TObject); 364 procedure TfrmTracker.DirectionComboBoxChange(Sender: TObject);
@@ -314,6 +374,11 @@ begin
314 Song.Comment := CommentMemo.Text; 374 Song.Comment := CommentMemo.Text;
315 end; 375 end;
316 376
377 procedure TfrmTracker.ArtistEditChange(Sender: TObject);
378 begin
379 Song.Artist := ArtistEdit.Text;
380 end;
381
317 procedure TfrmTracker.DivRatioSpinnerChange(Sender: TObject); 382 procedure TfrmTracker.DivRatioSpinnerChange(Sender: TObject);
318 begin 383 begin
319 CurrentInstrument^.DividingRatio := Round(DivRatioSpinner.Position); 384 CurrentInstrument^.DividingRatio := Round(DivRatioSpinner.Position);
@@ -352,6 +417,16 @@ begin
352 CurrentInstrument^.Length := Round(LengthSpinner.Position); 417 CurrentInstrument^.Length := Round(LengthSpinner.Position);
353 end; 418 end;
354 419
420 procedure TfrmTracker.MenuItem6Click(Sender: TObject);
421 begin
422 PlayC4WithInstrument(InstrumentNumberSpinner.Value);
423 {Spokeb($FF10, 0);
424 Spokeb($FF11, %11111111);
425 Spokeb($FF12, %11110000);
426 Spokeb($FF13, 10);
427 Spokeb($FF14, %10000000 or 6);}
428 end;
429
355 procedure TfrmTracker.NoiseFreqSpinnerChange(Sender: TObject); 430 procedure TfrmTracker.NoiseFreqSpinnerChange(Sender: TObject);
356 begin 431 begin
357 CurrentInstrument^.ShiftClockFreq := Round(NoiseFreqSpinner.Position); 432 CurrentInstrument^.ShiftClockFreq := Round(NoiseFreqSpinner.Position);
Addedutils.pas +93−0
@@ -0,0 +1,93 @@
1 unit Utils;
2
3 {$mode objfpc}
4
5 interface
6
7 uses
8 Classes, SysUtils, instruments;
9
10 type
11 TRegisters = record
12 case Type_: TInstrumentType of
13 Noise: (NR41, NR42, NR43, NR44: Byte);
14 end;
15
16 function BuildEnvelope(
17 InitialVol: TEnvelopeVolume;
18 Direction: TSweepType;
19 Amount: TEnvelopeSweepAmount): Byte;
20
21 function BuildHighByte(
22 Initial: Boolean;
23 LengthEnabled: Boolean;
24 Frequency: Integer): Byte; overload;
25
26 function BuildHighByte(
27 Initial: Boolean;
28 LengthEnabled: Boolean): Byte; overload;
29
30 function NoiseInstrumentToRegisters(
31 Initial: Boolean;
32 Instr: TInstrument): TRegisters;
33
34 implementation
35
36 function BuildEnvelope(
37 InitialVol: TEnvelopeVolume;
38 Direction: TSweepType;
39 Amount: TEnvelopeSweepAmount): Byte;
40 var
41 DirectionNumber: Integer;
42 begin
43 if Direction = Up then DirectionNumber := 1
44 else DirectionNumber := 0;
45 Result := (InitialVol shl 4);
46 Result := Result or (DirectionNumber shl 2);
47 Result := Result or Amount;
48 end;
49
50 function BuildHighByte(
51 Initial: Boolean;
52 LengthEnabled: Boolean;
53 Frequency: Integer): Byte;
54 begin
55 Result := 0;
56 if Initial then Result := %10000000;
57 if LengthEnabled then Result := Result or %01000000;
58 Result := Result or Frequency;
59 end;
60
61 function BuildHighByte(
62 Initial: Boolean;
63 LengthEnabled: Boolean): Byte;
64 begin
65 BuildHighByte(Initial, LengthEnabled, 0);
66 end;
67
68 function NoiseInstrumentToRegisters(
69 Initial: Boolean;
70 Instr: TInstrument): TRegisters;
71 function BuildPolynomialCounter(
72 ShiftClockFreq: Integer;
73 CounterStep: TStepWidth;
74 DividingRatio: Integer): Byte;
75 begin
76 Result := (ShiftClockFreq shl 4);
77 if CounterStep = Seven then
78 Result := Result or %00001000;
79 Result := Result or DividingRatio;
80 end;
81
82 begin
83 with Instr do
84 begin
85 Result.NR41 := Length;
86 Result.NR42 := BuildEnvelope(InitialVolume, VolSweepDirection, VolSweepAmount);
87 Result.NR43 := BuildPolynomialCounter(ShiftClockFreq, CounterStep, DividingRatio);
88 Result.NR44 := BuildHighByte(Initial, LengthEnabled);
89 end;
90 end;
91
92 end.
93