ScummVM API documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
c64.music.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #include "audio/audiostream.h"
23 #include "audio/mixer.h"
24 #include "audio/softsynth/sid.h"
25 #include "common/debug.h"
26 
27 namespace Freescape {
28 
30 
31  // --- Voice State Structure ---
32  struct VoiceState {
33  // Pointers & Indices
34  const uint8_t *trackDataPtr; // Pointer to current track data array
35  uint8_t trackIndex; // Index within trackDataPtr
36  const uint8_t *patternDataPtr; // Pointer to current pattern data array
37  uint8_t patternIndex; // Index within patternDataPtr
38  uint8_t instrumentIndex; // Current instrument (0-21, scaled by 8 for lookup)
39 
40  // Playback Control & Tempo
41  int8_t delayCounter; // Counts down frames for note duration (maps to voiceX_ctrl2)
42  uint8_t noteDuration; // Duration set by FD xx (maps to voiceX_something+2)
43  uint8_t gateMask; // Control gating/retriggering (maps to control3 behavior)
44 
45  // Note & Frequency
46  uint8_t currentNote; // Current raw note value (0-95)
47  uint8_t portaTargetNote; // Target note for portamento
48  uint16_t currentFreq; // Current frequency being sent to SID
49  uint16_t baseFreq; // Note frequency without effects
50  uint16_t targetFreq; // Used for portamento target
51 
52  // Pulse Width
53  uint16_t pulseWidth; // Current pulse width
54  // Placeholder for PWM effects if needed later
55 
56  // ADSR
57  uint8_t attackDecay; // SID Attack / Decay register value
58  uint8_t sustainRelease; // SID Sustain / Release register value
59 
60  // Effects State
61  uint8_t effect; // Current active effect (0:None, 1:Arpeggio, 2:Vibrato, 3:Portamento Up, 4:Portamento Down, 5: PWM LFO?)
62  uint8_t arpeggioIndex; // Index in arpeggio table
63  uint8_t arpeggioSpeed; // Counter divisor for arpeggio step
64  uint8_t arpeggioCounter; // Counter for arpeggio step
65  uint8_t arpeggioNoteOffsetIndex; // 0, 1, 2 for arpeggio notes
66 
67  int16_t vibratoDepth; // Depth for vibrato effect
68  uint8_t vibratoSpeed; // Speed/delay for vibrato effect
69  uint8_t vibratoDelay; // Counter for vibrato step
70  uint8_t vibratoDirection; // 0: up, 1: down
71  int16_t vibratoCurrentOffset; // Current frequency offset for vibrato
72 
73  int16_t portaSpeed; // Speed for portamento effect (positive for up, negative for down)
74 
75  // Hard Restart / Buzz Effect (from L1005, possibly instrument related)
76  uint8_t hardRestartValue; // Value from instrument table (a1+5)
77  uint8_t hardRestartDelay; // Counter for delay phase (voiceX_whatever+3)
78  uint8_t hardRestartCounter; // Counter for frequency change phase (voiceX_whatever+4)
79  bool hardRestartActive; // Is the effect currently running?
80 
81  // From disassembly variables (mapping might need refinement)
82  // voice1_whatever: 0CCE[5] - effect state? (arp, vib, porta)
83  uint8_t whatever0; // 0CCE - Vibrato state? (0=off, 1=active, 3-4=sweep?)
84  uint8_t whatever1; // 0CCF - Arpeggio state? (0=off, 1=active)
85  uint8_t whatever2; // 0CD0 - Portamento type (0=off, 1=down(FB), 2=up(FC), 3=down H(FB), 4=up H(FC))?
86  uint8_t whatever3; // 0CD1 - Hard restart delay counter
87  uint8_t whatever4; // 0CD2 - Hard restart step counter
88 
89  // voice1_whatever2: 0CD4 - Vibrato direction toggle?
90  uint8_t whatever2_vibDirToggle;
91 
92  // voice1_something: 0CE3[3] - Porta speed?, Note duration
93  uint16_t portaStepRaw; // 0CE3/4 - Raw value from FB/FC command
94  // uint8_t noteDuration // 0CE5 - Covered above
95 
96  // voice1_something_else: 0CE7[3] - PW Low, PW High? (ADSR in disassembly?) - Needs clarification
97  uint8_t something_else[3]; // Re-add this array as it's used in the code logic
98 
99  // voice1_ctrl0: 0CF8 - ADSR lower nibble (Sustain/Release)
100  uint8_t ctrl0; // Re-add this as it's used in the code logic
101 
102  // voice1_ctrl1: 0CF9 - Arpeggio table index / Arp speed upper nibble
103  uint8_t arpTableIndex;
104  uint8_t arpSpeedHiNibble;
105 
106  // voice1_ctrl2: 0CFE - Note delay counter (covered by delayCounter)
107 
108  // voice1_stuff: 0D14[7] - Current freq, base freq, hard restart freq store? Arp counter?
109  uint16_t stuff_freq_porta_vib; // 0D14/15 - Current frequency including porta/vib
110  uint16_t stuff_freq_base; // 0D16/17 - Base frequency of the note
111  uint16_t stuff_freq_hard_restart; // 0D18/19 - Frequency stored during hard restart buzz
112  uint8_t stuff_arp_counter; // 0D1A - Arpeggio counter (0..speed-1)
113  uint8_t stuff_arp_note_index; // 0D1B - Index into arp notes (0, 1, 2)
114 
115  // voice1_things: 0D29[7] - Vibrato state/params
116  uint8_t things_vib_state; // 0D29 - Vibrato state (0=down1, 1=up, 2=down2, 3=sweepdown1, 4=sweepup)
117  uint16_t things_vib_depth; // 0D2A/2B - Vibrato depth
118  uint8_t things_vib_delay_reload; // 0D2C - Vibrato delay reload value
119  uint8_t things_vib_delay_ctr; // 0D2D - Vibrato delay counter
120  // 0D2E/F unused?
121  uint8_t currentNoteSlideTarget; // 0D30 - Last played note (used for slide target?)
122 
123  // voice1_two_ctr: 0D3E - Glide down timer? (Instrument related)
124  uint8_t glideDownTimer;
125 
126  // Temp values during processing
127  uint8_t waveform; // Current waveform for SID
128  bool keyOn; // Current key state (attack vs release)
129  bool sync; // Sync bit state
130  bool ringMod; // Ring mod bit state
131 
132  // Pulse width parts matching something_else (if it maps to PW)
133  uint8_t pwLo() const { return something_else[0]; } // Example mapping
134  uint8_t pwHi() const { return something_else[2]; } // Example mapping
135  void setPwLo(uint8_t val) { something_else[0] = val; }
136  void setPwHi(uint8_t val) { something_else[2] = val; }
137 
138  void reset() {
139  trackDataPtr = nullptr;
140  trackIndex = 0;
141  patternDataPtr = nullptr;
142  patternIndex = 0;
143  instrumentIndex = 0;
144  delayCounter = 0;
145  noteDuration = 0;
146  gateMask = 0xFF;
147  currentNote = 0;
148  portaTargetNote = 0;
149  currentFreq = 0;
150  baseFreq = 0;
151  targetFreq = 0;
152  pulseWidth = 0;
153  attackDecay = 0;
154  sustainRelease = 0;
155  effect = 0;
156  arpeggioIndex = 0;
157  arpeggioSpeed = 0;
158  arpeggioCounter = 0;
159  arpeggioNoteOffsetIndex = 0;
160  vibratoDepth = 0;
161  vibratoSpeed = 0;
162  vibratoDelay = 0;
163  vibratoDirection = 0;
164  vibratoCurrentOffset = 0;
165  portaSpeed = 0;
166  hardRestartValue = 0;
167  hardRestartDelay = 0;
168  hardRestartCounter = 0;
169  hardRestartActive = false;
170  waveform = 0x10; // Default to triangle?
171  keyOn = false;
172  sync = false;
173  ringMod = false;
174 
175  // Reset mapped vars
176  whatever0 = 0;
177  whatever1 = 0;
178  whatever2 = 0;
179  whatever3 = 0;
180  whatever4 = 0;
181  whatever2_vibDirToggle = 0;
182  portaStepRaw = 0;
183  memset(something_else, 0, sizeof(something_else)); // Reset the array
184  ctrl0 = 0; // Reset the added member
185  arpTableIndex = 0;
186  arpSpeedHiNibble = 0;
187  stuff_freq_porta_vib = 0;
188  stuff_freq_base = 0;
189  stuff_freq_hard_restart = 0;
190  stuff_arp_counter = 0;
191  stuff_arp_note_index = 0;
192  things_vib_state = 0;
193  things_vib_depth = 0;
194  things_vib_delay_reload = 0;
195  things_vib_delay_ctr = 0;
196  currentNoteSlideTarget = 0;
197  glideDownTimer = 0;
198  }
199  };
200 
201  // --- Member Variables ---
202  Resid::SID *_sid;
203  Audio::Mixer *_mixer;
204  Audio::SoundHandle _soundHandle; // Changed from pointer
205  int _sampleRate;
206  float _cyclesPerSample;
207  double _cycleCounter;
208 
209  // Player State
210  enum PlayState { STOPPED,
211  PLAYING,
212  CHANGING_TUNE };
213  PlayState _playState;
214  uint8_t _targetTuneIndex; // Tune index requested via startMusic
215 
216  // Global Timing
217  uint8_t _globalTempo; // Tempo value for current tune (0xD10)
218  uint8_t _globalTempoCounter; // Frame counter for tempo (0xD12)
219 
220  // Voice States
221  VoiceState _voiceState[3];
222 
223  // Internal helpers
224  uint8_t _tempControl3; // Temporary storage for gate mask (0xD13)
225  // uint8_t _tempControl1; // Temp storage from instrument data (0xD11)
226 
227 public:
229  ~DrillerSIDPlayer();
230  void startMusic(int tuneIndex = 1);
231  void stopMusic();
232 
233  int readBuffer(int16 *buffer, const int numSamples) override;
234 
235  bool isStereo() const override { return false; }
236  bool endOfData() const override { return false; }
237  int getRate() const override { return _sampleRate; }
238 
239 private:
240  void SID_Write(int reg, uint8_t data);
241  void initSID();
242  void playFrame();
243  void handleChangeTune(int tuneIndex);
244  void handleResetVoices();
245  void playVoice(int voiceIndex, bool tempoTick);
246  void applyNote(VoiceState &v, int sidOffset, const uint8_t *instA0, const uint8_t *instA1, int voiceIndex);
247  void applyContinuousEffects(VoiceState &v, int sidOffset, const uint8_t *instA0, const uint8_t *instA1);
248  void applyHardRestart(VoiceState &v, int sidOffset, const uint8_t *instA0, const uint8_t *instA1);
249 };
250 
251 } // namespace Freescape
bool endOfData() const override
Definition: c64.music.h:236
bool isStereo() const override
Definition: c64.music.h:235
Definition: area.h:36
Definition: sid.h:305
Definition: mixer.h:49
Definition: c64.music.h:29
Definition: mixer.h:59
Definition: audiostream.h:50
int getRate() const override
Definition: c64.music.h:237
int readBuffer(int16 *buffer, const int numSamples) override