scummvm/engines/lastexpress/game/sound.h
2011-02-07 23:01:06 +00:00

385 lines
9.1 KiB
C++

/* 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/data/snd.h"
#include "lastexpress/data/subtitle.h"
#include "lastexpress/shared.h"
#include "lastexpress/helpers.h"
#include "common/list.h"
#include "common/mutex.h"
#include "common/system.h"
#include "common/serializer.h"
namespace LastExpress {
class LastExpressEngine;
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);
bool 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();
// Serializable
void saveLoadWithSerializer(Common::Serializer &ser);
uint32 count();
private:
typedef int32 *SoundBuffer;
enum SoundStatus {
kSoundStatus_20 = 0x20,
kSoundStatus_40 = 0x40,
kSoundStatusRemoved = 0x200,
kSoundStatus_400 = 0x400,
kSoundStatus_8000 = 0x8000,
kSoundStatus_20000 = 0x20000,
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 SubtitleEntry;
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)
SubtitleEntry *subtitle;
// Sound stream
StreamedSound *soundStream;
SoundEntry() {
status.status = 0;
type = kSoundTypeNone;
field_1C = 0;
time = 0;
stream = NULL;
field_34 = 0;
field_38 = 0;
field_3C = 0;
field_40 = 0;
entity = kEntityPlayer;
field_48 = 0;
field_4C = 0;
subtitle = NULL;
soundStream = NULL;
}
~SoundEntry() {
// Entries that have been queued would have their streamed disposed automatically
if (!soundStream)
SAFE_DELETE(stream);
delete soundStream;
}
};
struct SubtitleEntry {
Common::String filename;
SoundStatusUnion status;
SoundEntry *sound;
SubtitleManager *data;
SubtitleEntry() {
status.status = 0;
sound = NULL;
data = NULL;
}
~SubtitleEntry() {
SAFE_DELETE(data);
}
};
// Engine
LastExpressEngine *_engine;
// State flag
int _state;
SoundType _currentType;
Common::Mutex _mutex;
// 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
int _drawSubtitles;
Common::List<SubtitleEntry *> _subtitles;
SubtitleEntry *_currentSubtitle;
void showSubtitle(SoundEntry *entry, Common::String filename);
SubtitleEntry *loadSubtitle(Common::String filename, SoundEntry *soundEntry);
void loadSubtitleData(SubtitleEntry * entry);
void setupSubtitleAndDraw(SubtitleEntry *subtitle);
void drawSubtitle(SubtitleEntry *subtitle);
void drawSubtitleOnScreen(SubtitleEntry *subtitle);
// Sound filter
void applyFilter(SoundEntry *entry, SoundBuffer buffer);
};
} // End of namespace LastExpress
#endif // LASTEXPRESS_SOUND_H