ScummVM API documentation
psound.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 file.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  */
11 
12 #ifndef MADS_PHANTOM_SOUND_PSOUND_H
13 #define MADS_PHANTOM_SOUND_PSOUND_H
14 
15 #include "mads/core/native_sound_timer.h"
16 #include "mads/core/sound_manager.h"
17 
18 namespace OPL {
19 class OPL;
20 }
21 
22 namespace MADS {
23 namespace Phantom {
24 namespace Sound {
25 
27  uint16 panning;
28  uint16 frequency;
29  uint16 bank;
30  uint16 channel;
31  uint16 operators;
32 };
33 
35  const char *filename;
36  int dataOffset;
37  int initializedDataSize;
38  int totalDataSize;
39  uint16 randomSeedOffset;
40  uint16 nullSequenceOffset;
41  uint16 patchTableOffset;
42  byte patchCount;
43  PSoundTableLayout tables;
44 };
45 
47 class PSound : public SoundDriver {
48 public:
49  enum {
50  kChannelCount = 9,
51  kMusicChannelCount = 6,
52  kPatchSize = 0x40,
53  kScriptVarCount = 32,
54  kOpcodeBudgetPerTick = 256
55  };
56 
57 protected:
58  enum RegisterBank {
59  kFirstBank = 1,
60  kSecondBank = 2,
61  kBothBanks = kFirstBank | kSecondBank
62  };
63 
65  struct Channel {
66  byte activeCount; // +00
67  int8 pitchBend; // +01
68  int8 volumeFadeStep; // +02
69  int8 panningFadeStep; // +03
70  byte note; // +04
71  byte patch; // +05
72  byte volume; // +06
73  byte noteOffset; // +07
74  byte keyOnDelay; // +08
75  byte volumeFadeCounter; // +09
76  byte volumeFadeReload; // +0a
77  byte panningFadeCounter; // +0b
78  byte panningFadeReload; // +0c
79  byte panning; // +0d
80  int8 volumeOffset; // +0e
81  byte mode; // +0f
82  byte operatorTotalLevel[4]; // +10..+13
83  uint16 loopStart; // +14
84  uint16 position; // +16
85  uint16 innerLoopStart; // +18
86  uint16 outerLoopStart; // +1a
87  uint16 innerLoopCount; // +1c
88  uint16 outerLoopCount; // +1e
89  uint16 originalSequence; // +20
90  uint16 branchReturn; // +22
91  uint16 noiseMask; // +24
92  uint16 noiseBase; // +26
93  int16 noiseStep; // +28
94  byte noiseTicks; // +2a
95  byte savedNoiseTicks; // +2b
96  int8 transpose; // +2c
97  int8 noteTranspose; // +2d
98  byte pendingStop; // +2e
99  int8 patchAttenuation; // +2f
100  byte durationOverride; // +30
101 
102  void reset();
103  void load(uint16 sequenceOffset);
104  };
105 
106  OPL::OPL *_opl;
107  byte _registerCache[2][256];
108  NativeSoundTimer _hostTimer;
109  Channel _channels[kChannelCount];
110  byte _scriptVars[kScriptVarCount];
111  int _masterVolume;
112  uint16 _randomSeed;
113  uint16 _frameCounter;
114  int16 _pollResult;
115  int8 _resultFlag;
116  uint16 _nullSequenceOffset;
117  uint16 _patchTableOffset;
118  PSoundTableLayout _tableLayout;
119  byte _patchCount;
120  bool _updatesEnabled;
121  bool _noiseServiceEnabled;
122  // The native BE-C1 opcodes update these fields, but the audited overlays'
123  // per-tick tempo hook is a no-op. Preserve the state without inventing a
124  // duration transform.
125  uint16 _tickEnabled;
126  uint16 _tickCounter;
127  uint16 _tempoReload;
128  uint16 _tempoTarget;
129  int16 _tempoShift;
130  uint16 _tempoBase;
131  uint16 _tempoCurrent;
132  uint16 _tempoScale;
133  int _frameNumber2;
134 
135  PSound(Audio::Mixer *mixer, const PSoundDriverData &driverData);
136  ~PSound() override;
137 
138  bool isDataRangeValid(uint32 offset, uint32 length) const;
139  const byte *getDataPointer(uint32 offset, uint32 length,
140  const char *operation) const;
141  byte *getDataPointer(uint32 offset, uint32 length, const char *operation);
142  byte readDataByte(uint32 offset) const;
143  uint16 readDataUint16(uint32 offset) const;
144  void writeDataByte(uint32 offset, byte value);
145  void writeDataUint16(uint32 offset, uint16 value);
146 
147  byte getBankMask(uint channel) const;
148  byte getOplChannel(uint channel) const;
149  byte getOperatorOffset(uint channel, uint operatorIndex) const;
150  const byte *getPatch(uint patchIndex) const;
151  byte getPanningAttenuation(byte panning) const;
152  uint16 getFrequencyNumber(byte semitone) const;
153  void writeRegister(byte banks, byte reg, byte value);
154  byte getCachedRegister(byte banks, byte reg) const;
155 
156  void initializePas16();
157  void shutdownPas16();
158  void resetDriver();
159  int command0();
160  int command1();
161  int command2();
162  int command3();
163  int command4();
164  int command5();
165  int command6();
166  int command7();
167  int command8();
168 
169  void requestStop(uint firstChannel, uint endChannel);
170  void setCurrentSequence(uint firstChannel, uint endChannel,
171  uint16 sequenceOffset);
172  void loadChannel(uint channel, uint16 sequenceOffset);
173  void playSound(uint16 sequenceOffset);
174  void playMusicAny(uint16 sequenceOffset);
175  bool isSoundActive(uint16 sequenceOffset) const;
176 
177  void onTimer();
178  int serviceUpdate();
179  void serviceNoise();
180  void update();
181  void updateChannel(uint channelIndex);
182  bool isOpcodeDataValid(uint16 position, uint32 length) const;
183  byte readOpcodeByte(uint16 position, uint16 delta) const;
184  uint16 readOpcodeWord(uint16 position, uint16 delta) const;
185  bool isScriptVariableValid(byte index) const;
186  bool transferOpcode(Channel &channel, uint16 position, bool take,
187  bool isCall);
188  bool executeOpcode(uint channelIndex, byte opcode, bool &levelsDirty);
189  void finishChannel(uint channelIndex);
190  void checkPendingStops();
191 
192  void loadPatch(uint channelIndex, byte patchIndex);
193  void programOperator(byte banks, uint channelIndex, uint operatorIndex,
194  const byte *operatorData);
195  void updatePanning(uint channelIndex);
196  void updateChannelLevels(uint channelIndex);
197  void updateChannelFrequency(uint channelIndex, bool keyOn);
198  void updatePitchBend(uint channelIndex);
199  void keyOff(uint channelIndex);
200  void setNoiseFrequency(uint channelIndex, int frequency);
201  void resultCheck();
202 
203  uint16 nextRandom();
204 
206  virtual bool callFunction(uint16 targetOffset, Channel &channel) = 0;
207 
208 public:
209  static bool validateFile(const PSoundDriverData &driverData,
210  const char *first8192Md5, Common::String *reason = nullptr);
211  bool isReady() const { return _opl != nullptr; }
212 
213  int stop() override;
214  int poll() override;
215  void noise() override;
216  void setVolume(int volume) override;
217 };
218 
219 } // namespace Sound
220 } // namespace Phantom
221 } // namespace MADS
222 
223 #endif // MADS_PHANTOM_SOUND_PSOUND_H
Definition: str.h:59
Definition: mixer.h:70
Definition: native_sound_timer.h:33
Definition: sound_manager.h:40
Definition: fmopl.h:35
Definition: anim_timer.h:27
Definition: fmopl.h:116
Definition: psound.h:47