1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
|
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef SCUMM_PLAYERS_PLAYER_SID_H
#define SCUMM_PLAYERS_PLAYER_SID_H
#include "common/mutex.h"
#include "common/scummsys.h"
#include "scumm/music.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
#include "audio/softsynth/sid.h"
namespace Scumm {
// the "channel" parameters seem to be in fact SID register
// offsets. Should be replaced.
enum sid_reg_t {
FREQ_VOICE1,
FREQ_VOICE2,
FREQ_VOICE3,
FREQ_FILTER,
PULSE_VOICE1,
PULSE_VOICE2,
PULSE_VOICE3
};
enum VideoStandard {
PAL,
NTSC
};
class ScummEngine;
class Player_SID : public Audio::AudioStream, public MusicEngine {
public:
Player_SID(ScummEngine *scumm, Audio::Mixer *mixer);
virtual ~Player_SID();
virtual void setMusicVolume(int vol) { _maxvol = vol; }
virtual void startSound(int sound);
virtual void stopSound(int sound);
virtual void stopAllSounds();
virtual int getSoundStatus(int sound) const;
virtual int getMusicTimer();
// AudioStream API
int readBuffer(int16 *buffer, const int numSamples);
bool isStereo() const { return false; }
bool endOfData() const { return false; }
int getRate() const { return _sampleRate; }
private:
Resid::SID *_sid;
void SID_Write(int reg, uint8 data);
void initSID();
uint8 *getResource(int resID);
// number of cpu cycles until next frame update
Resid::cycle_count _cpuCyclesLeft;
ScummEngine *_vm;
Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
int _sampleRate;
int _maxvol;
Common::Mutex _mutex;
VideoStandard _videoSystem;
int _music_timer;
uint8* _music;
private:
void initMusic(int songResIndex); // $7de6
int initSound(int soundResID); // $4D0A
void stopSound_intern(int soundResID); // $5093
void stopMusic_intern(); // $4CAA
void resetSID(); // $48D8
void update(); // $481B
void handleMusicBuffer();
int setupSongFileData(); // $36cb
void func_3674(int channel); // $3674
void resetPlayerState(); // $48f7
void processSongData(int channel); // $4939
void readSetSIDFilterAndProps(int *offset, uint8* dataPtr); // $49e7
void saveSongPos(int y, int channel);
void updateFreq(int channel);
void resetFreqDelta(int channel);
void readSongChunk(int channel); // $4a6b
void setSIDFreqAS(int channel); // $4be6
void setSIDWaveCtrlReg(int channel); // $4C0D
int setupSongPtr(int channel); // $4C1C
void unlockResource(int chanResIndex); // $4CDA
void countFreeChannels(); // $4f26
void func_4F45(int channel); // $4F45
void safeUnlockResource(int resIndex); // $4FEA
void releaseResource(int resIndex); // $5031
void releaseResChannels(int resIndex); // $5070
void releaseResourceUnk(int resIndex); // $50A4
void releaseChannel(int channel);
void clearSIDWaveform(int channel);
void stopChannel(int channel);
void swapVars(int channel, int swapIndex); // $51a5
void resetSwapVars(); // $52d0
void prepareSwapVars(int channel); // $52E5
void useSwapVars(int channel); // $5342
void lockResource(int resIndex); // $4ff4
void reserveChannel(int channel, uint8 prioValue, int chanResIndex); // $4ffe
void unlockCodeLocation(); // $513e
void lockCodeLocation(); // $514f
void func_7eae(int channel, uint8* songFileDataPtr); // $7eae
void func_819b(int channel); // $819b
void buildStepTbl(int step); // $82B4
int reserveSoundFilter(uint8 value, uint8 chanResIndex); // $4ED0
int reserveSoundVoice(uint8 value, uint8 chanResIndex); // $4EB8
void findLessPrioChannels(uint8 soundPrio); // $4ED8
void releaseResourceBySound(int resID); // $5088
void readVec6Data(int x, int *offset, uint8 *songFilePtr, int chanResID); // $4E99
void unused1(); // $50AF
uint8 chanBuffer[3][45];
int resID_song;
// statusBits1A/1B are always equal
uint8 statusBits1A;
uint8 statusBits1B;
uint8 busyChannelBits;
uint8 SIDReg23;
uint8 SIDReg23Stuff;
uint8 SIDReg24;
uint8* chanFileData[3];
uint16 chanDataOffset[3];
uint8* songPosPtr[7];
// 0..2: freq value voice1/2/3
// 3: filter freq
// 4..6: pulse width
uint16 freqReg[7];
// start offset[i] for songFileOrChanBufData to obtain songPosPtr[i]
// vec6[0..2] = 0x0008;
// vec6[4..6] = 0x0019;
uint16 vec6[7];
// current offset[i] for songFileOrChanBufData to obtain songPosPtr[i] (starts with vec6[i], increased later)
uint16 songFileOrChanBufOffset[7];
uint16 freqDelta[7];
int freqDeltaCounter[7];
uint8* swapSongPosPtr[3];
uint8* swapVec5[3];
uint16 swapVec8[3];
uint16 swapVec10[3];
uint16 swapFreqReg[3];
int swapVec11[3];
// never read
//uint8* vec5[7];
// never read
//uint8 vec19[7];
// never read (needed by scumm engine?)
//bool curChannelActive;
uint8* vec20[7];
uint8* swapVec20[3];
// resource status (never read)
// bit7: some flag
// bit6..0: counter (use-count?), maybe just bit0 as flag (used/unused?)
uint8 resStatus[70];
uint8* songFileOrChanBufData;
uint8* actSongFileData;
uint16 stepTbl[33];
bool initializing;
bool _soundInQueue;
bool isVoiceChannel;
bool isMusicPlaying;
bool swapVarLoaded;
bool bgSoundActive;
bool filterUsed;
uint8 bgSoundResID;
uint8 freeChannelCount;
// seems to be used for managing the three voices
// bit[0..2]: 0 -> unused, 1 -> already in use
uint8 usedChannelBits;
uint8 attackReg[3];
uint8 sustainReg[3];
// -1/0/1
int var481A;
// bit-array: 00000cba
// a/b/c: channel1/2/3
uint8 songChannelBits;
bool pulseWidthSwapped;
bool swapPrepared;
// never read
//uint8 var5163;
bool filterSwapped;
uint8 SIDReg24_HiNibble;
bool keepSwapVars;
uint8 phaseBit[3];
bool releasePhase[3];
// values: a resID or -1
// resIDs: 3, 4, 5 or song-number
int _soundQueue[7];
// values: a resID or 0
// resIDs: 3, 4, 5 or song-number
int channelMap[7];
uint8 songPosUpdateCounter[7];
// priortity of channel contents
// MM: 1: lowest .. 120: highest (1,2,A,64,6E,73,78)
// Zak: -???: lowest .. 120: highest (5,32,64,65,66,6E,78, A5,A6,AF,D7)
uint8 chanPrio[7];
// only [0..2] used?
uint8 waveCtrlReg[7];
uint8 swapAttack[2];
uint8 swapSustain[2];
uint8 swapSongPrio[3];
int swapVec479C[3];
uint8 swapVec19[3];
uint8 swapSongPosUpdateCounter[3];
uint8 swapWaveCtrlReg[3];
bool actFilterHasLowerPrio;
uint8 chansWithLowerPrioCount;
uint8 minChanPrio;
uint8 minChanPrioIndex;
};
} // End of namespace Scumm
#endif
|