mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-29 14:42:26 +00:00
Patch #1365914: "SCUMM: CMS support." Disabled by default. Still plenty to do.
svn-id: r41282
This commit is contained in:
parent
986a0b83b6
commit
cda17beff5
@ -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},
|
||||
|
@ -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 \
|
||||
|
@ -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
@ -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) {
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user