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
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
|
/* 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 LASTEXPRESS_SOUND_H
#define LASTEXPRESS_SOUND_H
/*
Sound entry: 68 bytes (this is what appears in the savegames)
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - entity
uint32 {4} - ??
uint32 {4} - ??
char {16} - name 1
char {16} - name 2
Sound queue entry: 120 bytes
uint16 {2} - status
byte {1} - ??
byte {1} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - file data pointer
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - archive structure pointer
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - ??
uint32 {4} - entity
uint32 {4} - ??
uint32 {4} - ??
char {16} - name 1
char {16} - name 2
uint32 {4} - pointer to next entry in the queue
uint32 {4} - subtitle data pointer
*/
#include "lastexpress/shared.h"
#include "common/list.h"
#include "common/system.h"
#include "common/serializer.h"
namespace LastExpress {
class LastExpressEngine;
class StreamedSound;
class SubtitleManager;
class SoundManager : Common::Serializable {
public:
enum SoundType {
kSoundTypeNone = 0,
kSoundType1,
kSoundType2,
kSoundType3,
kSoundType4,
kSoundType5,
kSoundType6,
kSoundType7,
kSoundType8,
kSoundType9,
kSoundType10,
kSoundType11,
kSoundType12,
kSoundType13,
kSoundType14,
kSoundType15,
kSoundType16
};
enum FlagType {
kFlagInvalid = -1,
kFlagNone = 0x0,
kFlag2 = 0x2,
kFlag3 = 0x3,
kFlag4 = 0x4,
kFlag5 = 0x5,
kFlag6 = 0x6,
kFlag7 = 0x7,
kFlag8 = 0x8,
kFlag9 = 0x9,
kFlag10 = 0xA,
kFlag11 = 0xB,
kFlag12 = 0xC,
kFlag13 = 0xD,
kFlag14 = 0xE,
kFlag15 = 0xF,
kFlagDefault = 0x10,
kFlagType1_2 = 0x1000000,
kFlagSteam = 0x1001007,
kFlagType13 = 0x3000000,
kFlagMenuClock = 0x3080010,
kFlagType7 = 0x4000000,
kFlagType11 = 0x5000000,
kFlagMusic = 0x5000010,
kFlagType3 = 0x6000000,
kFlagLoop = 0x6001008,
kFlagType9 = 0x7000000
};
SoundManager(LastExpressEngine *engine);
~SoundManager();
// Timer
void handleTimer();
// State
void resetState() { _state |= kSoundType1; }
// Sound queue
void updateQueue();
void resetQueue(SoundType type1, SoundType type2 = kSoundTypeNone);
void clearQueue();
// Subtitles
void updateSubtitles();
// Entry
bool isBuffered(Common::String filename, bool testForEntity = false);
bool isBuffered(EntityIndex entity);
void setupEntry(SoundType type, EntityIndex index);
void processEntry(EntityIndex entity);
void processEntry(SoundType type);
void processEntry(Common::String filename);
void processEntries();
void removeFromQueue(Common::String filename);
void removeFromQueue(EntityIndex entity);
uint32 getEntryTime(EntityIndex index);
// Misc
void unknownFunction4();
void clearStatus();
// Sound playing
void playSound(EntityIndex entity, Common::String filename, FlagType flag = kFlagInvalid, byte a4 = 0);
SoundType playSoundWithSubtitles(Common::String filename, FlagType flag, EntityIndex entity, byte a4 = 0);
void playSoundEvent(EntityIndex entity, byte action, byte a3 = 0);
void playDialog(EntityIndex entity, EntityIndex entityDialog, FlagType flag, byte a4);
void playSteam(CityIndex index);
void playFightSound(byte action, byte a4);
void playLocomotiveSound();
void playWarningCompartment(EntityIndex entity, ObjectIndex compartment);
// Dialog & Letters
void readText(int id);
const char *getDialogName(EntityIndex entity) const;
// Sound bites
void excuseMe(EntityIndex entity, EntityIndex entity2 = kEntityPlayer, FlagType flag = kFlagNone);
void excuseMeCath();
const char *justCheckingCath() const;
const char *wrongDoorCath() const;
const char *justAMinuteCath() const;
// FLags
SoundManager::FlagType getSoundFlag(EntityIndex index) const;
// Debug
void stopAllSound() const;
// Serializable
void saveLoadWithSerializer(Common::Serializer &ser);
private:
typedef int32 *SoundBuffer;
enum SoundStatus {
kSoundStatus_20 = 0x20,
kSoundStatusRemoved = 0x200,
kSoundStatus_8000 = 0x8000,
kSoundStatus_100000 = 0x100000,
kSoundStatus_40000000 = 0x40000000,
kSoundStatusClear0 = 0x10,
kSoundStatusClear1 = 0x1F,
kSoundStatusClear2 = 0x80,
kSoundStatusClear3 = 0x200,
kSoundStatusClear4 = 0x800,
kSoundStatusClearAll = 0xFFFFFFE0
};
enum SoundState {
kSoundState0 = 0,
kSoundState1 = 1,
kSoundState2 = 2
};
union SoundStatusUnion {
uint32 status;
byte status1;
byte status2;
byte status3;
byte status4;
SoundStatusUnion() {
status = 0;
}
};
struct SoundEntry {
SoundStatusUnion status;
SoundType type; // int
//int field_8;
//int field_C;
//int field_10;
//int fileData;
//int field_18;
//int field_1C;
uint32 time;
//int field_24;
//int field_28;
Common::SeekableReadStream *stream; // int
//int field_30;
//int field_34;
//int field_38;
int field_3C;
int field_40;
EntityIndex entity;
int field_48;
int field_4C;
Common::String name1; //char[16];
Common::String name2; //char[16];
//int next; // offset to the next structure in the list (not used)
SubtitleManager *subtitle;
bool isStreamed; // TEMPORARY
SoundEntry() {
status.status = 0;
type = kSoundTypeNone;
time = 0;
stream = NULL;
field_3C = 0;
field_40 = 0;
entity = kEntityPlayer;
field_48 = 0;
field_4C = 0;
subtitle = NULL;
isStreamed = false;
}
};
// Engine
LastExpressEngine *_engine;
// State flag
int _state;
SoundType _currentType;
// Sound stream
StreamedSound *_soundStream;
// Unknown data
uint32 _data0;
uint32 _data1;
uint32 _data2;
uint32 _flag;
// Filters
int32 _buffer[2940]; ///< Static sound buffer
// Compartment warnings by Mertens or Coudert
uint32 _lastWarning[12];
// Looping sound
void playLoopingSound();
// Sound cache
Common::List<SoundEntry *> _cache;
SoundEntry *getEntry(EntityIndex index);
SoundEntry *getEntry(Common::String name);
SoundEntry *getEntry(SoundType type);
void setupEntry(SoundEntry *entry, Common::String name, FlagType flag, int a4);
void setEntryType(SoundEntry *entry, FlagType flag);
void setEntryStatus(SoundEntry *entry, FlagType flag) const;
bool setupCache(SoundEntry *entry);
void loadSoundData(SoundEntry *entry, Common::String name);
void updateEntry(SoundEntry *entry, uint value) const;
void updateEntryState(SoundEntry *entry) const ;
void resetEntry(SoundEntry *entry) const;
void removeEntry(SoundEntry *entry);
// Subtitles
void showSubtitles(SoundEntry *entry, Common::String filename);
void drawSubtitles(SubtitleManager *subtitle);
// Sound filter
void applyFilter(SoundEntry *entry, SoundBuffer buffer);
};
} // End of namespace LastExpress
#endif // LASTEXPRESS_SOUND_H
|