diff options
Diffstat (limited to 'engines/scumm/imuse/imuse_internal.h')
-rw-r--r-- | engines/scumm/imuse/imuse_internal.h | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h new file mode 100644 index 0000000000..3640cafa64 --- /dev/null +++ b/engines/scumm/imuse/imuse_internal.h @@ -0,0 +1,472 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001 Ludvig Strigeus + * Copyright (C) 2001-2006 The ScummVM project + * + * 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 DEFINED_IMUSE_INTERNAL +#define DEFINED_IMUSE_INTERNAL + +#include "common/scummsys.h" +#include "scumm/imuse/instrument.h" +#include "scumm/saveload.h" +#include "sound/mididrv.h" + +class MidiParser; +class OSystem; + +namespace Scumm { + +// Unremark this statement to activate some of +// the most common iMuse diagnostic messages. +// #define IMUSE_DEBUG + +struct ParameterFader; +struct DeferredCommand; +struct ImTrigger; +struct SustainingNotes; +struct CommandQueue; +struct IsNoteCmdData; +class Player; +struct Part; +class IMuseInternal; + +// Some entities also referenced +class ScummEngine; + + + +////////////////////////////////////////////////// +// +// Some constants +// +////////////////////////////////////////////////// + +#define TICKS_PER_BEAT 480 + +#define TRIGGER_ID 0 +#define COMMAND_ID 1 + +#define MDPG_TAG "MDpg" + + +//////////////////////////////////////// +// +// Helper functions +// +//////////////////////////////////////// + +inline int clamp(int val, int min, int max) { + if (val < min) + return min; + if (val > max) + return max; + return val; +} + +inline int transpose_clamp(int a, int b, int c) { + if (b > a) + a += (b - a + 11) / 12 * 12; + if (c < a) + a -= (a - c + 11) / 12 * 12; + return a; +} + + + +////////////////////////////////////////////////// +// +// Entity declarations +// +////////////////////////////////////////////////// + +struct HookDatas { + byte _jump[2]; + byte _transpose; + byte _part_onoff[16]; + byte _part_volume[16]; + byte _part_program[16]; + byte _part_transpose[16]; + + int query_param(int param, byte chan); + int set(byte cls, byte value, byte chan); + HookDatas() { memset(this, 0, sizeof(HookDatas)); } +}; + +struct ParameterFader { + enum { + pfVolume = 1, + pfTranspose = 3, + pfSpeed = 4 + }; + + int param; + int start; + int end; + uint32 total_time; + uint32 current_time; + + ParameterFader() { param = 0; } + void init() { param = 0; } +}; + +struct DeferredCommand { + uint32 time_left; + int a, b, c, d, e, f; + DeferredCommand() { memset(this, 0, sizeof(DeferredCommand)); } +}; + +struct ImTrigger { + int sound; + byte id; + uint16 expire; + int command [8]; + ImTrigger() { memset(this, 0, sizeof(ImTrigger)); } +}; + +struct CommandQueue { + uint16 array[8]; + CommandQueue() { memset(this, 0, sizeof(CommandQueue)); } +}; + +class Player : public MidiDriver { +protected: + // Moved from IMuseInternal. + // This is only used by one player at a time. + static uint16 _active_notes[128]; + +protected: + MidiDriver *_midi; + MidiParser *_parser; + bool _passThrough; // Only respond to EOT, all else direct to MidiDriver + + Part *_parts; + bool _active; + bool _scanning; + int _id; + byte _priority; + byte _volume; + int8 _pan; + int8 _transpose; + int8 _detune; + byte _vol_eff; + + uint _track_index; + uint _loop_to_beat; + uint _loop_from_beat; + uint _loop_counter; + uint _loop_to_tick; + uint _loop_from_tick; + byte _speed; + bool _abort; + + // This does not get used by us! It is only + // here for save/load purposes, and gets + // passed on to the MidiParser during + // fixAfterLoad(). + uint32 _music_tick; + + HookDatas _hook; + ParameterFader _parameterFaders[4]; + + bool _isMT32; + bool _isMIDI; + +protected: + // Player part + void hook_clear(); + void uninit_parts(); + byte *parse_midi(byte *s); + void part_set_transpose(uint8 chan, byte relative, int8 b); + void parse_sysex(byte *p, uint len); + void maybe_jump(byte cmd, uint track, uint beat, uint tick); + void maybe_set_transpose(byte *data); + void maybe_part_onoff(byte *data); + void maybe_set_volume(byte *data); + void maybe_set_program(byte *data); + void maybe_set_transpose_part(byte *data); + void turn_off_pedals(); + int query_part_param(int param, byte chan); + void turn_off_parts(); + void play_active_notes(); + + void transitionParameters(); + + static void decode_sysex_bytes(const byte *src, byte *dst, int len); + + // Sequencer part + int start_seq_sound(int sound, bool reset_vars = true); + int query_param(int param); + +public: + IMuseInternal *_se; + uint _vol_chan; + +public: + Player(); + virtual ~Player(); + + int addParameterFader(int param, int target, int time); + void clear(); + void clearLoop(); + void fixAfterLoad(); + Part * getActivePart(uint8 part); + uint getBeatIndex(); + int8 getDetune() const { return _detune; } + byte getEffectiveVolume() const { return _vol_eff; } + int getID() const { return _id; } + MidiDriver *getMidiDriver() const { return _midi; } + int getParam(int param, byte chan); + int8 getPan() const { return _pan; } + Part * getPart(uint8 part); + byte getPriority() const { return _priority; } + uint getTicksPerBeat() const { return TICKS_PER_BEAT; } + int8 getTranspose() const { return _transpose; } + byte getVolume() const { return _volume; } + bool isActive() const { return _active; } + bool isFadingOut() const; + bool isMIDI() const { return _isMIDI; } + bool isMT32() const { return _isMT32; } + bool jump(uint track, uint beat, uint tick); + void onTimer(); + void removePart(Part *part); + int scan(uint totrack, uint tobeat, uint totick); + void saveLoadWithSerializer(Serializer *ser); + int setHook(byte cls, byte value, byte chan) { return _hook.set(cls, value, chan); } + void setDetune(int detune); + bool setLoop(uint count, uint tobeat, uint totick, uint frombeat, uint fromtick); + void setPan(int pan); + void setPriority(int pri); + void setSpeed(byte speed); + int setTranspose(byte relative, int b); + int setVolume(byte vol); + bool startSound(int sound, MidiDriver *midi, bool passThrough); + int getMusicTimer() const; + +public: + // MidiDriver interface + int open() { return 0; } + void close() { } + void send(uint32 b); + const char *getErrorName(int error_code) { return "Unknown"; } + void sysEx(byte *msg, uint16 length); + void metaEvent(byte type, byte *data, uint16 length); + void setTimerCallback(void *timer_param, void(*timer_proc)(void *)) { } + uint32 getBaseTempo(); + MidiChannel *allocateChannel() { return 0; } + MidiChannel *getPercussionChannel() { return 0; } +}; + +struct Part : public Serializable { + IMuseInternal *_se; + int _slot; + Part *_next, *_prev; + MidiChannel *_mc; + Player *_player; + int16 _pitchbend; + byte _pitchbend_factor; + int8 _transpose, _transpose_eff; + byte _vol, _vol_eff; + int8 _detune, _detune_eff; + int8 _pan, _pan_eff; + bool _on; + byte _modwheel; + bool _pedal; + int8 _pri; + byte _pri_eff; + byte _chan; + byte _effect_level; + byte _chorus; + byte _percussion; + byte _bank; + + // New abstract instrument definition + Instrument _instrument; + bool _unassigned_instrument; // For diagnostic reporting purposes only + + // MidiChannel interface + // (We don't currently derive from MidiChannel, + // but if we ever do, this will make it easy.) + void noteOff(byte note); + void noteOn(byte note, byte velocity); + void programChange(byte value); + void pitchBend(int16 value); + void modulationWheel(byte value); + void volume(byte value); + void pitchBendFactor(byte value); + void sustain(bool value); + void effectLevel(byte value); + void chorusLevel(byte value); + void allNotesOff(); + + void set_param(byte param, int value) { } + void init(); + void setup(Player *player); + void uninit(); + void off(); + void set_instrument(uint b); + void set_instrument(byte *data); + void load_global_instrument(byte b); + + void set_transpose(int8 transpose); + void set_detune(int8 detune); + void set_pri(int8 pri); + void set_pan(int8 pan); + + void set_onoff(bool on); + void fix_after_load(); + + void sendAll(); + void sendPitchBend(); + bool clearToTransmit(); + + Part(); + + void saveLoadWithSerializer(Serializer *ser); +}; + +// WARNING: This is the internal variant of the IMUSE class. +// imuse.h contains a public version of the same class. +// the public version, only contains a set of methods. +class IMuseInternal { + friend class Player; + friend struct Part; + +protected: + bool _native_mt32; + bool _enable_gs; + bool _sc55; + MidiDriver *_midi_adlib; + MidiDriver *_midi_native; + + byte **_base_sounds; + +protected: + bool _paused; + bool _initialized; + + int _tempoFactor; + + int _player_limit; // Limits how many simultaneous music tracks are played + bool _recycle_players; // Can we stop a player in order to start another one? + bool _direct_passthrough; // Pass data direct to MidiDriver (no interactivity) + + uint _queue_end, _queue_pos, _queue_sound; + byte _queue_adding; + + byte _queue_marker; + byte _queue_cleared; + byte _master_volume; // Master volume. 0-255 + byte _music_volume; // Global music volume. 0-255 + + uint16 _trigger_count; + ImTrigger _snm_triggers[16]; // Sam & Max triggers + uint16 _snm_trigger_index; + + uint16 _channel_volume[8]; + uint16 _channel_volume_eff[8]; // No Save + uint16 _volchan_table[8]; + + Player _players[8]; + Part _parts[32]; + + Instrument _global_adlib_instruments[32]; + CommandQueue _cmd_queue[64]; + DeferredCommand _deferredCommands[4]; + +protected: + byte *findStartOfSound(int sound); + bool isMT32(int sound); + bool isMIDI(int sound); + int get_queue_sound_status(int sound) const; + void handle_marker(uint id, byte data); + int get_channel_volume(uint a); + void initMidiDriver(MidiDriver *midi); + void initGM(MidiDriver *midi); + void initMT32(MidiDriver *midi); + void init_players(); + void init_parts(); + void init_queue(); + + void sequencer_timers(MidiDriver *midi); + + MidiDriver *getBestMidiDriver(int sound); + Player *allocate_player(byte priority); + Part *allocate_part(byte pri, MidiDriver *midi); + + int32 ImSetTrigger(int sound, int id, int a, int b, int c, int d, int e, int f, int g, int h); + int32 ImClearTrigger(int sound, int id); + int32 ImFireAllTriggers(int sound); + + void addDeferredCommand(int time, int a, int b, int c, int d, int e, int f); + void handleDeferredCommands(MidiDriver *midi); + + int enqueue_command(int a, int b, int c, int d, int e, int f, int g); + int enqueue_trigger(int sound, int marker); + int query_queue(int param); + Player *findActivePlayer(int id); + + int get_volchan_entry(uint a); + int set_volchan_entry(uint a, uint b); + int set_channel_volume(uint chan, uint vol); + void update_volumes(); + void reset_tick(); + + int set_volchan(int sound, int volchan); + + void fix_parts_after_load(); + void fix_players_after_load(ScummEngine *scumm); + + static void midiTimerCallback(void *data); + +public: + IMuseInternal(); + + int initialize(OSystem *syst, MidiDriver *nativeMidiDriver, MidiDriver *adlibMidiDriver); + void reallocateMidiChannels(MidiDriver *midi); + void setGlobalAdlibInstrument(byte slot, byte *data); + void copyGlobalAdlibInstrument(byte slot, Instrument *dest); + bool isNativeMT32() { return _native_mt32; } + + // IMuse interface + + void on_timer(MidiDriver *midi); + void pause(bool paused); + int terminate1(); + int terminate2(); + int save_or_load(Serializer *ser, ScummEngine *scumm); + int setMusicVolume(uint vol); + int setImuseMasterVolume(uint vol); + bool startSound(int sound); + int stopSound(int sound); + int stopAllSounds(); + int getSoundStatus(int sound, bool ignoreFadeouts = true) const; + int getMusicTimer() const; + int32 doCommand (int a, int b, int c, int d, int e, int f, int g, int h); + int32 doCommand (int numargs, int args[]); + int clear_queue(); + void setBase(byte **base); + uint32 property(int prop, uint32 value); + + static IMuseInternal *create(OSystem *syst, MidiDriver *nativeMidiDriver, MidiDriver *adlibMidiDriver); +}; + +} // End of namespace Scumm + +#endif |