aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm/player_sid.h
blob: bfc945307035f26de368f233e5985b44936a319f (plain)
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
277
278
279
280
/* 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.
 *
 * $URL$
 * $Id$
 *
 */

#ifndef SCUMM_PLAYER_SID_H
#define SCUMM_PLAYER_SID_H

#include "common/mutex.h"
#include "common/scummsys.h"
#include "scumm/music.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
#include "sound/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; };
	void startMusic(int songResIndex);
	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 _sample_rate; }

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 _sample_rate;
	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 stopAllSounds_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