MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { const GameSettings *g; const char *gameid = ConfMan.get("gameid").c_str(); for (g = madeSettings; g->gameid; ++g) if (!scumm_stricmp(g->gameid, gameid)) _gameId = g->id; _rnd = new Common::RandomSource(); syst->getEventManager()->registerRandomSource(*_rnd, "made"); int cd_num = ConfMan.getInt("cdrom"); if (cd_num >= 0) _system->openCD(cd_num); _pmvPlayer = new PmvPlayer(this, _mixer); _res = new ResourceReader(); _screen = new Screen(this); if (getGameID() == GID_LGOP2 || getGameID() == GID_MANHOLE || getGameID() == GID_RODNEY) { _dat = new GameDatabaseV2(this); } else if (getGameID() == GID_RTZ) { _dat = new GameDatabaseV3(this); } else { error("Unknown GameID"); } _script = new ScriptInterpreter(this); int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); //bool adlib = (midiDriver == MD_ADLIB); MidiDriver *driver = MidiDriver::createMidi(midiDriver); if (native_mt32) driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); _music = new MusicPlayer(driver); _music->setNativeMT32(native_mt32); //_music->setAdlib(adlib); // Set default sound frequency switch (getGameID()) { case GID_RODNEY: _soundRate = 11025; break; case GID_MANHOLE: _soundRate = 11025; break; case GID_LGOP2: _soundRate = 8000; break; case GID_RTZ: // Return to Zork sets it itself via a script funtion break; } syncSoundSettings(); }
// MIDI messages can be found at http://www.midi.org/techspecs/midimessages.php void MidiDriver_MT32::send(uint32 b) { byte command = b & 0xf0; byte channel = b & 0xf; if (command == 0xF0) { if (_driver) { _driver->send(b); } return; } if (_MIDIchannelActive[channel]) { // Only forward MIDI-data in case the channel is currently enabled via music-data if (_driver) { _driver->send(b); } } }
int MidiDriver_MT32::open() { assert(!_driver); debugC(kDebugLevelMT32Driver, "MT32: starting driver"); // Setup midi driver MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_PREFER_MT32); MusicType musicType = MidiDriver::getMusicType(dev); switch (musicType) { case MT_MT32: _nativeMT32 = true; break; case MT_GM: if (ConfMan.getBool("native_mt32")) { _nativeMT32 = true; } break; default: break; } _driver = MidiDriver::createMidi(dev); if (!_driver) return 255; if (_nativeMT32) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); int ret = _driver->open(); if (ret) return ret; if (_nativeMT32) _driver->sendMT32Reset(); else _driver->sendGMReset(); return 0; }
void MidiDriver_MT32::mt32SysEx(const byte *&dataPtr, int32 &bytesLeft) { byte sysExMessage[270]; uint16 sysExPos = 0; byte sysExByte = 0; uint16 sysExChecksum = 0; memset(&sysExMessage, 0, sizeof(sysExMessage)); sysExMessage[0] = 0x41; // Roland sysExMessage[1] = 0x10; sysExMessage[2] = 0x16; // Model MT32 sysExMessage[3] = 0x12; // Command DT1 sysExPos = 4; sysExChecksum = 0; while (1) { assert(bytesLeft); sysExByte = *dataPtr++; bytesLeft--; if (sysExByte == 0xff) break; // Message done assert(sysExPos < sizeof(sysExMessage)); sysExMessage[sysExPos++] = sysExByte; sysExChecksum -= sysExByte; } // Calculate checksum assert(sysExPos < sizeof(sysExMessage)); sysExMessage[sysExPos++] = sysExChecksum & 0x7f; debugC(kDebugLevelMT32Driver, "MT32: uploading patch data, size %d", sysExPos); // Send SysEx _driver->sysEx(sysExMessage, sysExPos); // Wait the time it takes to send the SysEx data uint32 delay = (sysExPos + 2) * 1000 / 3125; // Plus an additional delay for the MT-32 rev00 if (_nativeMT32) delay += 40; g_system->delayMillis(delay); }
TestExitStatus MidiTests::playMidiMusic() { Testsuite::clearScreen(); Common::String info = "Testing Midi Sound output.\n" "Here, We generate some Music by using the Midi Driver selected in the GUI.\n" "You should expect to hear that. The initialization may take some time.\n"; if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) { Testsuite::logPrintf("Info! Skipping test : Play Midi Music\n"); return kTestSkipped; } MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB); // Create a driver instance MidiDriver *driver = MidiDriver::createMidi(dev); // Create a SMF parser MidiParser *smfParser = MidiParser::createParser_SMF(); // Open the driver int errCode = driver->open(); if (errCode) { Common::String errMsg = driver->getErrorName(errCode); Testsuite::writeOnScreen(errMsg, Common::Point(0, 100)); Testsuite::logPrintf("Error! %s", errMsg.c_str()); return kTestFailed; } Testsuite::logDetailedPrintf("Info! Midi: Succesfully opened the driver\n"); Common::MemoryWriteStreamDynamic ws(DisposeAfterUse::YES); loadMusicInMemory(&ws); // start playing if (smfParser->loadMusic(ws.getData(), ws.size())) { smfParser->setTrack(0); smfParser->setMidiDriver(driver); smfParser->setTimerRate(driver->getBaseTempo()); driver->setTimerCallback(smfParser, MidiParser::timerCallback); Testsuite::logDetailedPrintf("Info! Midi: Parser Successfully loaded Music data.\n"); if (smfParser->isPlaying()) { Testsuite::writeOnScreen("Playing Midi Music, Click to end.", Common::Point(0, 100)); Testsuite::logDetailedPrintf("Info! Midi: Playing music!\n"); } } // Play until track ends or an exit is requested. waitForMusicToPlay(smfParser); // Done. Clean up. smfParser->unloadMusic(); driver->setTimerCallback(NULL, NULL); driver->close(); delete smfParser; delete driver; if (Testsuite::handleInteractiveInput("Were you able to hear the music as described?", "Yes", "No", kOptionRight)) { Testsuite::logDetailedPrintf("Error! Midi: Can't play Music\n"); return kTestFailed; } return kTestPassed; }
Common::Error KyraEngine_v1::init() { // Setup mixer syncSoundSettings(); if (!_flags.useDigSound) { if (_flags.platform == Common::kPlatformFMTowns) { if (_flags.gameID == GI_KYRA1) _sound = new SoundTowns(this, _mixer); else _sound = new SoundTownsPC98_v2(this, _mixer); } else if (_flags.platform == Common::kPlatformPC98) { if (_flags.gameID == GI_KYRA1) _sound = new SoundPC98(this, _mixer); else _sound = new SoundTownsPC98_v2(this, _mixer); } else if (_flags.platform == Common::kPlatformAmiga) { _sound = new SoundAmiga(this, _mixer); } else { // In Kyra 1 users who have specified a default MT-32 device in the launcher settings // will get MT-32 music, otherwise AdLib. In Kyra 2 and LoL users who have specified a // default GM device in the launcher will get GM music, otherwise AdLib. Users who want // MT-32 music in Kyra2 or LoL have to select this individually (since we assume that // most users rather have a GM device than a MT-32 device). // Users who want PC speaker sound always have to select this individually for all // Kyra games. MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | ((_flags.gameID == GI_KYRA2 || _flags.gameID == GI_LOL) ? MDT_PREFER_GM : MDT_PREFER_MT32)); if (MidiDriver::getMusicType(dev) == MT_ADLIB) { _sound = new SoundAdLibPC(this, _mixer); } else { Sound::kType type; const MusicType midiType = MidiDriver::getMusicType(dev); if (midiType == MT_PCSPK || midiType == MT_NULL) type = Sound::kPCSpkr; else if (midiType == MT_MT32 || ConfMan.getBool("native_mt32")) type = Sound::kMidiMT32; else type = Sound::kMidiGM; MidiDriver *driver = 0; if (MidiDriver::getMusicType(dev) == MT_PCSPK) { driver = new MidiDriver_PCSpeaker(_mixer); } else { driver = MidiDriver::createMidi(dev); if (type == Sound::kMidiMT32) driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); } assert(driver); SoundMidiPC *soundMidiPc = new SoundMidiPC(this, _mixer, driver, type); _sound = soundMidiPc; assert(_sound); // Unlike some SCUMM games, it's not that the MIDI sounds are // missing. It's just that at least at the time of writing they // are decidedly inferior to the AdLib ones. if (ConfMan.getBool("multi_midi")) { SoundAdLibPC *adlib = new SoundAdLibPC(this, _mixer); assert(adlib); _sound = new MixedSoundDriver(this, _mixer, soundMidiPc, adlib); } } } assert(_sound); } if (_sound) _sound->updateVolumeSettings(); _res = new Resource(this); assert(_res); _res->reset(); if (_flags.isDemo) { // HACK: check whether this is the HOF demo or the LOL demo. // The LOL demo needs to be detected and run as KyraEngine_HoF, // but the static resource loader and the sequence player will // need correct IDs. if (_res->exists("scene1.cps")) #ifdef ENABLE_LOL _flags.gameID = GI_LOL; #else error("Lands of Lore demo is not supported in this build"); #endif // !ENABLE_LOL } _staticres = new StaticResource(this); assert(_staticres); if (!_staticres->init()) error("_staticres->init() failed"); if (!screen()->init()) error("screen()->init() failed"); _timer = new TimerManager(this, _system); assert(_timer); setupTimers(); _emc = new EMCInterpreter(this); assert(_emc); setupOpcodeTable(); readSettings(); if (ConfMan.hasKey("save_slot")) { _gameToLoad = ConfMan.getInt("save_slot"); if (!saveFileLoadable(_gameToLoad)) _gameToLoad = -1; } setupKeyMap(); // Prevent autosave on game startup _lastAutosave = _system->getMillis(); return Common::kNoError; }
void MidiDriver_MT32::close() { if (_driver) { _driver->close(); } }