Patch #1365914: "SCUMM: CMS support." Disabled by default. Still plenty to do.

svn-id: r41282
This commit is contained in:
Eugene Sandulenko 2009-06-06 18:21:49 +00:00
parent 986a0b83b6
commit cda17beff5
9 changed files with 2064 additions and 10 deletions

View File

@ -207,13 +207,13 @@ static const GameSettings gameVariantsTable[] = {
{"zak", "V2", "v2", GID_ZAK, 2, 0, MDT_PCSPK, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},
{"zak", "FM-TOWNS", 0, GID_ZAK, 3, 0, MDT_TOWNS, GF_OLD256 | GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI},
{"indy3", "EGA", "ega", GID_INDY3, 3, 0, MDT_PCSPK | MDT_ADLIB, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},
{"indy3", "EGA", "ega", GID_INDY3, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},
{"indy3", "No Adlib", "ega", GID_INDY3, 3, 0, MDT_PCSPK, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},
{"indy3", "VGA", "vga", GID_INDY3, 3, 0, MDT_PCSPK | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
{"indy3", "FM-TOWNS", 0, GID_INDY3, 3, 0, MDT_TOWNS, GF_OLD256 | GF_FEW_LOCALS | GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI},
{"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH},
{"loom", "No Adlib", "ega", GID_LOOM, 3, 0, MDT_PCSPK, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},
{"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH},
{"loom", "No Adlib", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},
{"loom", "PC-Engine", 0, GID_LOOM, 3, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformPCEngine, GUIO_NOSPEECH | GUIO_NOMIDI},
{"loom", "FM-TOWNS", 0, GID_LOOM, 3, 0, MDT_TOWNS, GF_AUDIOTRACKS | GF_OLD256, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI},
{"loom", "VGA", "vga", GID_LOOM, 4, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
@ -221,7 +221,7 @@ static const GameSettings gameVariantsTable[] = {
{"pass", 0, 0, GID_PASS, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
{"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH},
{"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH},
{"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH},
{"monkey", "No Adlib", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK, GF_16COLOR, Common::kPlatformAtariST, GUIO_NOSPEECH | GUIO_NOMIDI},
{"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI},
{"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK, GUIO_NOSPEECH | GUIO_NOMIDI},

View File

@ -38,6 +38,7 @@ MODULE_OBJS := \
player_v1.o \
player_v2.o \
player_v2a.o \
player_v2cms.o \
player_v3a.o \
resource_v2.o \
resource_v3.o \

View File

@ -158,6 +158,179 @@ private:
void next_freqs(ChannelInfo *channel);
};
/**
* Scumm V2 CMS/Gameblaster MIDI driver.
*/
class Player_V2CMS : public Audio::AudioStream, public MusicEngine {
public:
Player_V2CMS(ScummEngine *scumm, Audio::Mixer *mixer);
virtual ~Player_V2CMS();
virtual void setMusicVolume(int vol);
virtual void startSound(int sound);
virtual void stopSound(int sound);
virtual void stopAllSounds();
virtual int getMusicTimer() const;
virtual int getSoundStatus(int sound) const;
// AudioStream API
int readBuffer(int16 *buffer, const int numSamples);
bool isStereo() const { return true; }
bool endOfData() const { return false; }
int getRate() const { return _sample_rate; }
protected:
#include "common/pack-start.h" // START STRUCT PACKING
struct Voice {
byte attack;
byte decay;
byte sustain;
byte release;
byte octadd;
int16 vibrato;
int16 vibrato2;
int16 noise;
} PACKED_STRUCT;
struct Voice2 {
byte *amplitudeOutput;
byte *freqOutput;
byte *octaveOutput;
int8 channel;
int8 sustainLevel;
int8 attackRate;
int8 maxAmpl;
int8 decayRate;
int8 sustainRate;
int8 releaseRate;
int8 releaseTime;
int8 vibratoRate;
int8 vibratoDepth;
int8 curVibratoRate;
int8 curVibratoUnk;
int8 unkVibratoRate;
int8 unkVibratoDepth;
int8 unkRate;
int8 unkCount;
int nextProcessState;
int8 curVolume;
int8 curOctave;
int8 curFreq;
int8 octaveAdd;
int8 playingNote;
Voice2 *nextVoice;
byte chanNumber;
} PACKED_STRUCT;
struct MusicChip {
byte ampl[4];
byte freq[4];
byte octave[2];
} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
Voice _cmsVoicesBase[16];
Voice2 _cmsVoices[8];
MusicChip _cmsChips[2];
char _tempo;
char _tempoSum;
byte _looping;
byte _octaveMask;
int16 _midiDelay;
Voice2 *_midiChannel[16];
byte _midiChannelUse[16];
byte *_midiData;
byte *_midiSongBegin;
int _loadedMidiSong;
byte _lastMidiCommand;
uint _outputTableReady;
byte _clkFrequenz;
byte _restart;
byte _curSno;
void loadMidiData(byte *data, int sound);
void play();
void processChannel(Voice2 *channel);
void processRelease(Voice2 *channel);
void processAttack(Voice2 *channel);
void processDecay(Voice2 *channel);
void processSustain(Voice2 *channel);
void processVibrato(Voice2 *channel);
void playMusicChips(const MusicChip *table);
void playNote(byte *&data);
void clearNote(byte *&data);
void offAllChannels();
void playVoice();
void processMidiData(uint ticks);
Voice2 *getFreeVoice();
Voice2 *getPlayVoice(byte param);
// from Player_V2
protected:
bool _isV3Game;
Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
ScummEngine *_vm;
int _header_len;
uint32 _sample_rate;
uint32 _next_tick;
uint32 _tick_len;
int _timer_count[4];
int _timer_output;
int _current_nr;
byte *_current_data;
int _next_nr;
byte *_next_data;
byte *_retaddr;
private:
union ChannelInfo {
channel_data d;
uint16 array[sizeof(channel_data)/2];
};
int _music_timer;
int _music_timer_ctr;
int _ticks_per_music_timer;
Common::Mutex _mutex;
ChannelInfo _channels[5];
protected:
void mutex_up();
void mutex_down();
virtual void nextTick();
virtual void clear_channel(int i);
virtual void chainSound(int nr, byte *data);
virtual void chainNextSound();
private:
void do_mix(int16 *buf, uint len);
void execute_cmd(ChannelInfo *channel);
void next_freqs(ChannelInfo *channel);
};
} // End of namespace Scumm
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1585,6 +1585,13 @@ void ScummEngine::setupMusic(int midi) {
case MD_PCJR:
_musicType = MDT_PCSPK;
break;
case MD_CMS:
#if 1
_musicType = MDT_ADLIB;
#else
_musicType = MDT_CMS; // Still has number of bugs, disable by default
#endif
break;
case MD_TOWNS:
_musicType = MDT_TOWNS;
break;
@ -1639,7 +1646,7 @@ void ScummEngine::setupMusic(int midi) {
* automatically when samples need to be generated */
if (!_mixer->isReady()) {
warning("Sound mixer initialization failed");
if (_musicType == MDT_ADLIB || _musicType == MDT_PCSPK) {
if (_musicType == MDT_ADLIB || _musicType == MDT_PCSPK || _musicType == MDT_CMS) {
midiDriver = MD_NULL;
_musicType = MDT_NONE;
warning("MIDI driver depends on sound mixer, switching to null MIDI driver");
@ -1669,6 +1676,8 @@ void ScummEngine::setupMusic(int midi) {
_musicEngine = new Player_V2(this, _mixer, midiDriver != MD_PCSPK);
} else if ((_musicType == MDT_PCSPK) && (_game.version > 2 && _game.version <= 4)) {
_musicEngine = new Player_V2(this, _mixer, midiDriver != MD_PCSPK);
} else if (_musicType == MDT_CMS) {
_musicEngine = new Player_V2CMS(this, _mixer);
} else if (_game.platform == Common::kPlatform3DO && _game.heversion == 61) {
// 3DO versions use digital music and sound samples.
} else if (_game.version >= 3 && _game.heversion <= 61) {

View File

@ -1181,7 +1181,7 @@ int ScummEngine::readSoundResource(int idx) {
break;
}
if ((_musicType == MDT_PCSPK) && pri != 11)
if ((_musicType == MDT_PCSPK || _musicType == MDT_CMS) && pri != 11)
pri = -1;
debugC(DEBUG_RESOURCE, " tag: %s, total_size=%d, pri=%d", tag2str(tag), size, pri);
@ -2121,6 +2121,19 @@ int ScummEngine::readSoundResourceSmallHeader(int idx) {
_fileHandle->read(_res->createResource(rtSound, idx, wa_size + 6), wa_size + 6);
}
return 1;
} else if (_musicType == MDT_CMS && ad_offs != 0) {
if (_game.features & GF_OLD_BUNDLE) {
_fileHandle->seek(wa_offs + wa_size + 6, SEEK_SET);
byte musType = _fileHandle->readByte();
if (musType == 0x80) {
_fileHandle->seek(ad_offs, SEEK_SET);
_fileHandle->read(_res->createResource(rtSound, idx, ad_size), ad_size);
} else {
_fileHandle->seek(wa_offs, SEEK_SET);
_fileHandle->read(_res->createResource(rtSound, idx, wa_size), wa_size);
}
}
} else if (ad_offs != 0) {
// AD resources have a header, instrument definitions and one MIDI track.
// We build an 'ADL ' resource from that:

View File

@ -706,6 +706,9 @@ void ScummEngine::resetScummVars() {
case MDT_PCSPK:
VAR(VAR_SOUNDCARD) = 0;
break;
case MDT_CMS:
VAR(VAR_SOUNDCARD) = 2;
break;
case MDT_ADLIB:
VAR(VAR_SOUNDCARD) = 3;
break;

View File

@ -88,6 +88,7 @@ static const MidiDriverDescription s_musicDrivers[] = {
{"adlib", "AdLib", MD_ADLIB, MDT_ADLIB},
{"pcspk", "PC Speaker", MD_PCSPK, MDT_PCSPK},
{"pcjr", "IBM PCjr", MD_PCJR, MDT_PCSPK},
{"cms", "Creative Music System", MD_CMS, MDT_CMS},
{"towns", "FM Towns", MD_TOWNS, MDT_TOWNS},
#if defined(UNIX)
{"timidity", "TiMidity", MD_TIMIDITY, MDT_MIDI},
@ -236,6 +237,7 @@ MidiDriver *MidiDriver::createMidi(int midiDriver) {
// outside the MidiDriver architecture, so
// don't create anything for now.
case MD_PCSPK:
case MD_CMS:
case MD_PCJR: return NULL;
#ifdef USE_FLUIDSYNTH

View File

@ -80,6 +80,7 @@ enum MidiDriverType {
// "Fake" MIDI devices
MD_ADLIB,
MD_PCSPK,
MD_CMS,
MD_PCJR,
MD_TOWNS,
MD_TIMIDITY
@ -98,10 +99,11 @@ enum MidiDriverType {
enum MidiDriverFlags {
MDT_NONE = 0,
MDT_PCSPK = 1 << 0, // PC Speaker: Maps to MD_PCSPK and MD_PCJR
MDT_ADLIB = 1 << 1, // Adlib: Maps to MD_ADLIB
MDT_TOWNS = 1 << 2, // FM-TOWNS: Maps to MD_TOWNS
MDT_MIDI = 1 << 3, // Real MIDI
MDT_PREFER_MIDI = 1 << 4 // Real MIDI output is preferred
MDT_CMS = 1 << 1, // Creative Music System / Gameblaster: Maps to MD_CMS
MDT_ADLIB = 1 << 2, // Adlib: Maps to MD_ADLIB
MDT_TOWNS = 1 << 3, // FM-TOWNS: Maps to MD_TOWNS
MDT_MIDI = 1 << 4, // Real MIDI
MDT_PREFER_MIDI = 1 << 5 // Real MIDI output is preferred
};
/**