diff options
Diffstat (limited to 'engines/scumm')
37 files changed, 994 insertions, 148 deletions
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index b8722b6963..0c375efcdd 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -573,19 +573,19 @@ bool Actor_v2::checkWalkboxesHaveDirectPath(Common::Point &foundPath) { return false; } -bool Actor_v0::intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End, - const Common::Point &line2Start, const Common::Point &line2End, Common::Point &result) +bool Actor_v0::intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End, + const Common::Point &line2Start, const Common::Point &line2End, Common::Point &result) { const Common::Point v1 = line1End - line1Start; // line1(n1) = line1Start + n1 * v1 const Common::Point v2 = line2End - line2Start; // line2(n2) = line2Start + n2 * v2 - + double det = v2.x * v1.y - v1.x * v2.y; if (det == 0) return false; - double n1 = ((double)v2.x * (line2Start.y - line1Start.y) - + double n1 = ((double)v2.x * (line2Start.y - line1Start.y) - (double)v2.y * (line2Start.x - line1Start.x)) / det; - double n2 = ((double)v1.x * (line2Start.y - line1Start.y) - + double n2 = ((double)v1.x * (line2Start.y - line1Start.y) - (double)v1.y * (line2Start.x - line1Start.x)) / det; // both coefficients have to be in [0, 1], otherwise the intersection is @@ -599,16 +599,16 @@ bool Actor_v0::intersectLineSegments(const Common::Point &line1Start, const Comm } /* - * MM v0 allows the actor to walk in a direct line between boxes to the target + * MM v0 allows the actor to walk in a direct line between boxes to the target * if actor and target share a horizontal or vertical corridor. - * If such a corridor is found the actor is not forced to go horizontally or + * If such a corridor is found the actor is not forced to go horizontally or * vertically from one box to the next but can also walk diagonally. * - * Note: the original v0 interpreter sets the target destination for diagonal + * Note: the original v0 interpreter sets the target destination for diagonal * walking only once and then rechecks whenever the actor reaches a new box if the - * walk destination is still suitable for the current box. - * ScummVM does not perform such a check, so it is possible to leave the walkboxes - * in some cases, for example L-shaped rooms like the swimming pool (actor walks over water) + * walk destination is still suitable for the current box. + * ScummVM does not perform such a check, so it is possible to leave the walkboxes + * in some cases, for example L-shaped rooms like the swimming pool (actor walks over water) * or the medical room (actor walks over examination table). * To solve this we intersect the new walk destination with the actor's walkbox borders, * so a recheck is done when the actor leaves his box. This is done by the @@ -992,7 +992,7 @@ void Actor_v0::setDirection(int direction) { res = 7; // Face Camera break; } - + _animFrameRepeat = -1; animateActor(res); if (_moving) @@ -1408,7 +1408,7 @@ void Actor::showActor() { if (_vm->_game.version == 0) { Actor_v0 *a = ((Actor_v0 *)this); - + a->_costCommand = a->_costCommandNew = 0xFF; for (int i = 0; i < 8; ++i) { @@ -2056,7 +2056,7 @@ void Actor_v0::animateCostume() { void Actor_v0::speakCheck() { if (v0ActorTalkArray[_number] & 0x80) return; - + int cmd = newDirToOldDir(_facing); if (_speaking & 0x80) @@ -2884,7 +2884,7 @@ void Actor_v0::animateActor(int anim) { _costCommandNew = anim; _vm->_costumeLoader->costumeDecodeData(this, 0, 0); - + if (dir == -1) return; diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h index 0ed239d005..a733fdb4ed 100644 --- a/engines/scumm/actor.h +++ b/engines/scumm/actor.h @@ -377,7 +377,7 @@ public: virtual void saveLoadWithSerializer(Serializer *ser); protected: - bool intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End, + bool intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End, const Common::Point &line2Start, const Common::Point &line2End, Common::Point &result); virtual bool checkWalkboxesHaveDirectPath(Common::Point &foundPath); }; diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 4064853b6b..9ae75b6683 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -69,7 +69,7 @@ void ScummEngine::loadCJKFont() { _cjkFont->setDrawingMode(Graphics::FontSJIS::kShadowMode); _2byteWidth = _2byteHeight = 12; - _useCJKMode = true; + _useCJKMode = true; #endif } else if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD && _language == Common::JA_JPN) { int numChar = 1413; @@ -499,7 +499,7 @@ int CharsetRendererV3::getCharWidth(uint16 chr) { if (_vm->_useCJKMode && (chr & 0x80)) spacing = _vm->_2byteWidth / 2; - + if (!spacing) spacing = *(_widthTable + chr); @@ -644,7 +644,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { drawBits1(*vs, _left + vs->xstart, drawTop, charPtr, drawTop, origWidth, origHeight); else drawBits1(_vm->_textSurface, _left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier, charPtr, drawTop, origWidth, origHeight); - + if (is2byte) { origWidth /= _vm->_textSurfaceMultiplier; height /= _vm->_textSurfaceMultiplier; @@ -1399,7 +1399,7 @@ void CharsetRendererTownsClassic::drawBitsN(const Graphics::Surface&, byte *dst, _vm->_cjkFont->drawChar(_vm->_textSurface, _sjisCurChar, _left * _vm->_textSurfaceMultiplier, (_top - _vm->_screenTop) * _vm->_textSurfaceMultiplier, _vm->_townsCharsetColorMap[1], _shadowColor); return; } - + bool scale2x = (_vm->_textSurfaceMultiplier == 2); dst = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch * _vm->_textSurfaceMultiplier + _left * _vm->_textSurfaceMultiplier; diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h index b8f1d84045..1c1df51921 100644 --- a/engines/scumm/charset.h +++ b/engines/scumm/charset.h @@ -112,7 +112,7 @@ public: class CharsetRendererClassic : public CharsetRendererCommon { protected: virtual void drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height); - void printCharIntern(bool is2byte, const byte *charPtr, int origWidth, int origHeight, int width, int height, VirtScreen *vs, bool ignoreCharsetMask); + void printCharIntern(bool is2byte, const byte *charPtr, int origWidth, int origHeight, int width, int height, VirtScreen *vs, bool ignoreCharsetMask); virtual bool prepareDraw(uint16 chr); int _width, _height, _origWidth, _origHeight; @@ -195,7 +195,7 @@ public: int getCharWidth(uint16 chr); int getFontHeight(); - + private: void enableShadow(bool enable); void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height); diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp index 3f89bc9611..4ebdd00fdc 100644 --- a/engines/scumm/costume.cpp +++ b/engines/scumm/costume.cpp @@ -1188,7 +1188,7 @@ byte V0CostumeRenderer::drawLimb(const Actor *a, int limb) { _draw_top = 200; _draw_bottom = 0; } - + // Invalid current position? if (a->_cost.curpos[limb] == 0xFFFF) return 0; @@ -1377,7 +1377,7 @@ byte V0CostumeLoader::increaseAnim(Actor *a, int limb) { // Reset the comstume command a0->_costCommandNew = 0xFF; a0->_costCommand = 0xFF; - + // Set the frame/start to invalid a0->_cost.frame[limb] = 0xFFFF; a0->_cost.start[limb] = 0xFFFF; diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp index 88681898f5..269ae9e10a 100644 --- a/engines/scumm/cursor.cpp +++ b/engines/scumm/cursor.cpp @@ -180,7 +180,7 @@ void ScummEngine_v70he::setDefaultCursor() { 0xff, 0xff, 0xff, 0, 0, 0, }; - + memset(_grabbedCursor, 5, sizeof(_grabbedCursor)); _cursor.hotspotX = _cursor.hotspotY = 2; diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp index edcf2e6fea..dc5acbdb7d 100644 --- a/engines/scumm/debugger.cpp +++ b/engines/scumm/debugger.cpp @@ -382,7 +382,7 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) { DebugPrintf("Actor[%d].costume = %d\n", actnum, a->_costume); } } else if (!strcmp(argv[2], "name")) { - DebugPrintf("Name of actor %d: %s\n", actnum, + DebugPrintf("Name of actor %d: %s\n", actnum, _vm->getObjOrActorName(_vm->actorToObj(actnum))); } else if (!strcmp(argv[2], "condmask")) { if (argc > 3) { diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 5404c7f8b1..e5c3023380 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -242,6 +242,10 @@ static Common::String generateFilenameForDetection(const char *pattern, Filename return result; } +bool ScummEngine::isMacM68kIMuse() const { + return _game.platform == Common::kPlatformMacintosh && (_game.id == GID_MONKEY2 || _game.id == GID_INDY4) && !(_game.features & GF_MAC_CONTAINER); +} + struct DetectorDesc { Common::FSNode node; Common::String md5; @@ -473,6 +477,11 @@ static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameF if (dr.language == UNK_LANG) { dr.language = detectLanguage(fslist, dr.game.id); } + + // HACK: Detect between 68k and PPC versions + if (dr.game.platform == Common::kPlatformMacintosh && dr.game.version >= 5 && dr.game.heversion == 0 && strstr(gfp->pattern, "Data")) + dr.game.features |= GF_MAC_CONTAINER; + break; } } diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index be1b90e356..3120017db6 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -236,7 +236,7 @@ static const GameSettings gameVariantsTable[] = { {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO1(GUIO_NOSPEECH)}, {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, GF_16COLOR, Common::kPlatformPC, GUIO1(GUIO_NOSPEECH)}, {"monkey", "No AdLib", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR, GF_16COLOR, Common::kPlatformAtariST, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, - {"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, + {"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, {"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, {"monkey", "FM-TOWNS", 0, GID_MONKEY, 5, 0, MDT_TOWNS, GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO4(GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_MIDITOWNS, GUIO_NOASPECT)}, {"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 0e531daf73..945c5b6611 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -180,7 +180,7 @@ static const ResString string_map_table_v345[] = { // "Moechten Sie wirklich neu starten? (J/N)J" // Will react to J as 'Yes' {5, _s("Are you sure you want to restart? (Y/N)")}, - // I18N: you may specify 'Yes' symbol at the end of the line. See previous comment + // I18N: you may specify 'Yes' symbol at the end of the line. See previous comment {6, _s("Are you sure you want to quit? (Y/N)")}, // Added in SCUMM4 diff --git a/engines/scumm/he/logic/soccer.cpp b/engines/scumm/he/logic/soccer.cpp index 05f377a736..2b29f93173 100644 --- a/engines/scumm/he/logic/soccer.cpp +++ b/engines/scumm/he/logic/soccer.cpp @@ -303,7 +303,7 @@ int LogicHEsoccer::op_1008(int outArray, int srcX, int srcY, int srcZ, int vecX, putInArray(outArray, segmentsSoFar, 5, vecX); putInArray(outArray, segmentsSoFar, 6, vecY); putInArray(outArray, segmentsSoFar++, 7, vecZ); - } + } } else { srcY = 0; int thisVecX = vecX; @@ -628,7 +628,7 @@ int LogicHEsoccer::op_1014(int32 srcX, int32 srcY, int32 srcZ, int32 velX, int32 adjustedVelZ = ((double)srcZ - 3869.0) / 100.0; break; } - + int foundCollision = 0; // work out which collision objects we might collide with (if any) diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp index 47b4b8ad33..798f703db6 100644 --- a/engines/scumm/he/wiz_he.cpp +++ b/engines/scumm/he/wiz_he.cpp @@ -2286,8 +2286,7 @@ void Wiz::fillWizLine(const WizParameters *params) { lineP.depth = bitDepth; if (params->processFlags & kWPFParams) { - assert (params->params2 == 1); // Catch untested usage - Graphics::drawThickLine(x1, y1, x2, y2, params->params1, color, drawProc, &lineP); + Graphics::drawThickLine(x1, y1, x2, y2, params->params1, params->params2, color, drawProc, &lineP); } else { Graphics::drawLine(x1, y1, x2, y2, color, drawProc, &lineP); } diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp index 27a72c2afe..016ba89e7b 100644 --- a/engines/scumm/imuse/imuse.cpp +++ b/engines/scumm/imuse/imuse.cpp @@ -164,7 +164,7 @@ bool IMuseInternal::isMT32(int sound) { return true; case MKTAG('M', 'A', 'C', ' '): // Occurs in the Mac version of FOA and MI2 - return true; + return false; case MKTAG('G', 'M', 'D', ' '): return false; @@ -226,6 +226,45 @@ bool IMuseInternal::isMIDI(int sound) { return false; } +bool IMuseInternal::supportsPercussion(int sound) { + byte *ptr = g_scumm->_res->_types[rtSound][sound]._address; + if (ptr == NULL) + return false; + + uint32 tag = READ_BE_UINT32(ptr); + switch (tag) { + case MKTAG('A', 'D', 'L', ' '): + case MKTAG('A', 'S', 'F', 'X'): // Special AD class for old AdLib sound effects + case MKTAG('S', 'P', 'K', ' '): + return false; + + case MKTAG('A', 'M', 'I', ' '): + case MKTAG('R', 'O', 'L', ' '): + return true; + + case MKTAG('M', 'A', 'C', ' '): // Occurs in the Mac version of FOA and MI2 + // This is MIDI, i.e. uses MIDI style program changes, but without a + // special percussion channel. + return false; + + case MKTAG('G', 'M', 'D', ' '): + case MKTAG('M', 'I', 'D', 'I'): // Occurs in Sam & Max + return true; + } + + // Old style 'RO' has equivalent properties to 'ROL' + if (ptr[0] == 'R' && ptr[1] == 'O') + return true; + // Euphony tracks show as 'SO' and have equivalent properties to 'ADL' + // FIXME: Right now we're pretending it's GM. + if (ptr[4] == 'S' && ptr[5] == 'O') + return true; + + error("Unknown music type: '%c%c%c%c'", (char)tag >> 24, (char)tag >> 16, (char)tag >> 8, (char)tag); + + return false; +} + MidiDriver *IMuseInternal::getBestMidiDriver(int sound) { MidiDriver *driver = NULL; diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h index 3b0d36e119..846e2d7545 100644 --- a/engines/scumm/imuse/imuse_internal.h +++ b/engines/scumm/imuse/imuse_internal.h @@ -204,6 +204,7 @@ protected: bool _isMT32; bool _isMIDI; + bool _supportsPercussion; protected: // Player part @@ -458,6 +459,7 @@ protected: byte *findStartOfSound(int sound, int ct = (kMThd | kFORM)); bool isMT32(int sound); bool isMIDI(int sound); + bool supportsPercussion(int sound); int get_queue_sound_status(int sound) const; void handle_marker(uint id, byte data); int get_channel_volume(uint a); diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp index 73e7704469..89c16a8bb5 100644 --- a/engines/scumm/imuse/imuse_part.cpp +++ b/engines/scumm/imuse/imuse_part.cpp @@ -27,6 +27,7 @@ #include "common/util.h" #include "scumm/imuse/imuse_internal.h" #include "scumm/saveload.h" +#include "scumm/scumm.h" namespace Scumm { @@ -365,7 +366,17 @@ void Part::set_instrument(uint b) { _bank = (byte)(b >> 8); if (_bank) error("Non-zero instrument bank selection. Please report this"); - _instrument.program((byte)b, _player->isMT32()); + // HACK: Horrible hack to allow tracing of program change source. + // The Mac m68k versions of MI2 and Indy4 use a different program "bank" + // when it gets program change events through the iMuse SysEx handler. + // We emulate this by introducing a special instrument, which sets + // the instrument via sysEx_customInstrument. This seems to be + // exclusively used for special sound effects like the "spit" sound. + if (g_scumm->isMacM68kIMuse()) { + _instrument.macSfx(b); + } else { + _instrument.program((byte)b, _player->isMT32()); + } if (clearToTransmit()) _instrument.send(_mc); } diff --git a/engines/scumm/imuse/imuse_player.cpp b/engines/scumm/imuse/imuse_player.cpp index 53ccfb3734..3a9c42a920 100644 --- a/engines/scumm/imuse/imuse_player.cpp +++ b/engines/scumm/imuse/imuse_player.cpp @@ -78,6 +78,7 @@ Player::Player() : _speed(128), _isMT32(false), _isMIDI(false), + _supportsPercussion(false), _se(0), _vol_chan(0) { } @@ -103,6 +104,7 @@ bool Player::startSound(int sound, MidiDriver *midi) { _isMT32 = _se->isMT32(sound); _isMIDI = _se->isMIDI(sound); + _supportsPercussion = _se->supportsPercussion(sound); _parts = NULL; _active = true; @@ -386,6 +388,8 @@ void Player::sysEx(const byte *p, uint16 len) { // SysEx manufacturer 0x97 has been spotted in the // Monkey Island 2 AdLib music, so don't make this a // fatal error. See bug #1481383. + // The Macintosh version of Monkey Island 2 simply + // ignores these SysEx events too. if (a == 0) warning("Unknown SysEx manufacturer 0x00 0x%02X 0x%02X", p[0], p[1]); else @@ -1009,6 +1013,7 @@ void Player::fixAfterLoad() { _parser->jumpToTick(_music_tick); // start_seq_sound already switched tracks _isMT32 = _se->isMT32(_id); _isMIDI = _se->isMIDI(_id); + _supportsPercussion = _se->supportsPercussion(_id); } } diff --git a/engines/scumm/imuse/instrument.cpp b/engines/scumm/imuse/instrument.cpp index 11bb4e7605..61c73b1e2d 100644 --- a/engines/scumm/imuse/instrument.cpp +++ b/engines/scumm/imuse/instrument.cpp @@ -278,6 +278,21 @@ private: byte _instrument[23]; }; +class Instrument_MacSfx : public InstrumentInternal { +private: + byte _program; + +public: + Instrument_MacSfx(byte program); + Instrument_MacSfx(Serializer *s); + void saveOrLoad(Serializer *s); + void send(MidiChannel *mc); + void copy_to(Instrument *dest) { dest->macSfx(_program); } + bool is_valid() { + return (_program < 128); + } +}; + //////////////////////////////////////// // // Instrument class members @@ -326,6 +341,14 @@ void Instrument::pcspk(const byte *instrument) { _instrument = new Instrument_PcSpk(instrument); } +void Instrument::macSfx(byte prog) { + clear(); + if (prog > 127) + return; + _type = itMacSfx; + _instrument = new Instrument_MacSfx(prog); +} + void Instrument::saveOrLoad(Serializer *s) { if (s->isSaving()) { s->saveByte(_type); @@ -349,6 +372,9 @@ void Instrument::saveOrLoad(Serializer *s) { case itPcSpk: _instrument = new Instrument_PcSpk(s); break; + case itMacSfx: + _instrument = new Instrument_MacSfx(s); + break; default: warning("No known instrument classification #%d", (int)_type); _type = itNone; @@ -528,4 +554,38 @@ void Instrument_PcSpk::send(MidiChannel *mc) { mc->sysEx_customInstrument('SPK ', (byte *)&_instrument); } +//////////////////////////////////////// +// +// Instrument_MacSfx class members +// +//////////////////////////////////////// + +Instrument_MacSfx::Instrument_MacSfx(byte program) : + _program(program) { + if (program > 127) { + _program = 255; + } +} + +Instrument_MacSfx::Instrument_MacSfx(Serializer *s) { + _program = 255; + if (!s->isSaving()) { + saveOrLoad(s); + } +} + +void Instrument_MacSfx::saveOrLoad(Serializer *s) { + if (s->isSaving()) { + s->saveByte(_program); + } else { + _program = s->loadByte(); + } +} + +void Instrument_MacSfx::send(MidiChannel *mc) { + if (_program > 127) { + return; + } + mc->sysEx_customInstrument('MAC ', &_program); +} } // End of namespace Scumm diff --git a/engines/scumm/imuse/instrument.h b/engines/scumm/imuse/instrument.h index a855c64155..7e09e86fa5 100644 --- a/engines/scumm/imuse/instrument.h +++ b/engines/scumm/imuse/instrument.h @@ -52,7 +52,8 @@ public: itProgram = 1, itAdLib = 2, itRoland = 3, - itPcSpk = 4 + itPcSpk = 4, + itMacSfx = 5 }; Instrument() : _type(0), _instrument(0) { } @@ -72,6 +73,7 @@ public: void adlib(const byte *instrument); void roland(const byte *instrument); void pcspk(const byte *instrument); + void macSfx(byte program); byte getType() { return _type; } bool isValid() { return (_instrument ? _instrument->is_valid() : false); } diff --git a/engines/scumm/imuse/mac_m68k.cpp b/engines/scumm/imuse/mac_m68k.cpp new file mode 100644 index 0000000000..0980ef1fd2 --- /dev/null +++ b/engines/scumm/imuse/mac_m68k.cpp @@ -0,0 +1,514 @@ +/* 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. + */ + +#include "scumm/imuse/mac_m68k.h" + +#include "common/util.h" +#include "common/macresman.h" +#include "common/stream.h" + +namespace Scumm { + +MacM68kDriver::MacM68kDriver(Audio::Mixer *mixer) + : MidiDriver_Emulated(mixer) { +} + +MacM68kDriver::~MacM68kDriver() { +} + +int MacM68kDriver::open() { + if (_isOpen) { + return MERR_ALREADY_OPEN; + } + + const int error = MidiDriver_Emulated::open(); + if (error) { + return error; + } + + for (uint i = 0; i < ARRAYSIZE(_channels); ++i) { + _channels[i].init(this, i); + } + + memset(_voiceChannels, 0, sizeof(_voiceChannels)); + _lastUsedVoiceChannel = 0; + + loadAllInstruments(); + + _pitchTable[116] = 1664510; + _pitchTable[117] = 1763487; + _pitchTable[118] = 1868350; + _pitchTable[119] = 1979447; + _pitchTable[120] = 2097152; + _pitchTable[121] = 2221855; + _pitchTable[122] = 2353973; + _pitchTable[123] = 2493948; + _pitchTable[124] = 2642246; + _pitchTable[125] = 2799362; + _pitchTable[126] = 2965820; + _pitchTable[127] = 3142177; + for (int i = 115; i >= 0; --i) { + _pitchTable[i] = _pitchTable[i + 12] / 2; + } + + _volumeTable = new byte[8192]; + for (int i = 0; i < 32; ++i) { + for (int j = 0; j < 256; ++j) { + _volumeTable[i * 256 + j] = ((-128 + j) * _volumeBaseTable[i]) / 127 - 128; + } + } + + _mixBuffer = 0; + _mixBufferLength = 0; + + // We set the output sound type to music here to allow sound volume + // adjustment. The drawback here is that we can not control the music and + // sfx separately here. But the AdLib output has the same issue so it + // should not be that bad. + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); + + return 0; +} + +void MacM68kDriver::close() { + if (!_isOpen) { + return; + } + + _mixer->stopHandle(_mixerSoundHandle); + _isOpen = false; + for (InstrumentMap::iterator i = _instruments.begin(); i != _instruments.end(); ++i) { + delete[] i->_value.data; + } + _instruments.clear(); + delete[] _volumeTable; + _volumeTable = 0; + delete[] _mixBuffer; + _mixBuffer = 0; + _mixBufferLength = 0; +} + +void MacM68kDriver::send(uint32 d) { + assert(false); +} + +void MacM68kDriver::sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { + assert(false); +} + +MidiChannel *MacM68kDriver::allocateChannel() { + for (uint i = 0; i < ARRAYSIZE(_channels); ++i) { + if (_channels[i].allocate()) { + return &_channels[i]; + } + } + + return 0; +} + +MacM68kDriver::Instrument MacM68kDriver::getInstrument(int idx) const { + InstrumentMap::const_iterator i = _instruments.find(idx); + if (i != _instruments.end()) { + return i->_value; + } else { + return _defaultInstrument; + } +} + +void MacM68kDriver::generateSamples(int16 *buf, int len) { + int silentChannels = 0; + + if (_mixBufferLength < len) { + delete[] _mixBuffer; + + _mixBufferLength = len; + _mixBuffer = new int[_mixBufferLength]; + assert(_mixBuffer); + } + memset(_mixBuffer, 0, sizeof(int) * _mixBufferLength); + + for (int i = 0; i < kChannelCount; ++i) { + OutputChannel &out = _voiceChannels[i].out; + if (out.isFinished) { + ++silentChannels; + continue; + } + + byte *volumeTable = &_volumeTable[(out.volume / 4) * 256]; + int *buffer = _mixBuffer; + + int samplesLeft = len; + while (samplesLeft) { + out.subPos += out.pitchModifier; + while (out.subPos >= 0x10000) { + out.subPos -= 0x10000; + out.instrument++; + } + + if (out.instrument >= out.end) { + if (!out.start) { + break; + } + + out.instrument = out.start; + out.subPos = 0; + } + + *buffer++ += volumeTable[*out.instrument]; + --samplesLeft; + } + + if (samplesLeft) { + out.isFinished = true; + while (samplesLeft--) { + *buffer++ += 0x80; + } + } + } + + const int *buffer = _mixBuffer; + const int silenceAdd = silentChannels << 7; + while (len--) { + *buf++ = (((*buffer++ + silenceAdd) >> 3) << 8) ^ 0x8000; + } +} + +void MacM68kDriver::loadAllInstruments() { + Common::MacResManager resource; + if (resource.open("iMUSE Setups")) { + if (!resource.hasResFork()) { + error("MacM68kDriver::loadAllInstruments: \"iMUSE Setups\" loaded, but no resource fork present"); + } + + for (int i = 0x3E7; i < 0x468; ++i) { + Common::SeekableReadStream *stream = resource.getResource(MKTAG('s', 'n', 'd', ' '), i); + if (stream) { + addInstrument(i, stream); + delete stream; + } + } + + for (int i = 0x7D0; i < 0x8D0; ++i) { + Common::SeekableReadStream *stream = resource.getResource(MKTAG('s', 'n', 'd', ' '), i); + if (stream) { + addInstrument(i, stream); + delete stream; + } + } + + InstrumentMap::iterator inst = _instruments.find(kDefaultInstrument); + if (inst != _instruments.end()) { + _defaultInstrument = inst->_value; + } else { + error("MacM68kDriver::loadAllInstruments: Could not load default instrument"); + } + } else { + error("MacM68kDriver::loadAllInstruments: Could not load \"iMUSE Setups\""); + } +} + +void MacM68kDriver::addInstrument(int idx, Common::SeekableReadStream *data) { + // We parse the "SND" files manually here, since we need special data + // from their header and need to work on them raw while mixing. + data->skip(2); + int count = data->readUint16BE(); + data->skip(2 * (3 * count)); + count = data->readUint16BE(); + data->skip(2 * (4 * count)); + + Instrument inst; + // Skip (optional) pointer to data + data->skip(4); + inst.length = data->readUint32BE(); + inst.sampleRate = data->readUint32BE(); + inst.loopStart = data->readUint32BE(); + inst.loopEnd = data->readUint32BE(); + // Skip encoding + data->skip(1); + inst.baseFrequency = data->readByte(); + + inst.data = new byte[inst.length]; + assert(inst.data); + data->read(inst.data, inst.length); + _instruments[idx] = inst; +} + +void MacM68kDriver::setPitch(OutputChannel *out, int frequency) { + out->frequency = frequency; + out->isFinished = false; + + const int pitchIdx = (frequency >> 7) + 60 - out->baseFrequency; + assert(pitchIdx >= 0); + + const int low7Bits = frequency & 0x7F; + if (low7Bits) { + out->pitchModifier = _pitchTable[pitchIdx] + (((_pitchTable[pitchIdx + 1] - _pitchTable[pitchIdx]) * low7Bits) >> 7); + } else { + out->pitchModifier = _pitchTable[pitchIdx]; + } +} + +void MacM68kDriver::VoiceChannel::off() { + if (out.start) { + out.isFinished = true; + } + + part->removeVoice(this); + part = 0; +} + +void MacM68kDriver::MidiChannel_MacM68k::release() { + _allocated = false; + while (_voice) { + _voice->off(); + } +} + +void MacM68kDriver::MidiChannel_MacM68k::send(uint32 b) { + uint8 type = b & 0xF0; + uint8 p1 = (b >> 8) & 0xFF; + uint8 p2 = (b >> 16) & 0xFF; + + switch (type) { + case 0x80: + noteOff(p1); + break; + + case 0x90: + if (p2) { + noteOn(p1, p2); + } else { + noteOff(p1); + } + break; + + case 0xB0: + controlChange(p1, p2); + break; + + case 0xE0: + pitchBend((p1 | (p2 << 7)) - 0x2000); + break; + + default: + break; + } +} + +void MacM68kDriver::MidiChannel_MacM68k::noteOff(byte note) { + for (VoiceChannel *i = _voice; i; i = i->next) { + if (i->note == note) { + if (_sustain) { + i->sustainNoteOff = true; + } else { + i->off(); + } + } + } +} + +void MacM68kDriver::MidiChannel_MacM68k::noteOn(byte note, byte velocity) { + // Do not start a not unless there is an instrument set up + if (!_instrument.data) { + return; + } + + // Allocate a voice channel + VoiceChannel *voice = _owner->allocateVoice(_priority); + if (!voice) { + return; + } + addVoice(voice); + + voice->note = note; + // This completly ignores the note's volume, but is in accordance + // to the original. + voice->out.volume = _volume; + + // Set up the instrument data + voice->out.baseFrequency = _instrument.baseFrequency; + voice->out.soundStart = _instrument.data; + voice->out.soundEnd = _instrument.data + _instrument.length; + if (_instrument.loopEnd && _instrument.loopEnd - 12 > _instrument.loopStart) { + voice->out.loopStart = _instrument.data + _instrument.loopStart; + voice->out.loopEnd = _instrument.data + _instrument.loopEnd; + } else { + voice->out.loopStart = 0; + voice->out.loopEnd = voice->out.soundEnd; + } + + voice->out.start = voice->out.loopStart; + voice->out.end = voice->out.loopEnd; + + // Set up the pitch + _owner->setPitch(&voice->out, (note << 7) + _pitchBend); + + // Set up the sample position + voice->out.instrument = voice->out.soundStart; + voice->out.subPos = 0; +} + +void MacM68kDriver::MidiChannel_MacM68k::programChange(byte program) { + _instrument = _owner->getInstrument(program + kProgramChangeBase); +} + +void MacM68kDriver::MidiChannel_MacM68k::pitchBend(int16 bend) { + _pitchBend = (bend * _pitchBendFactor) >> 6; + for (VoiceChannel *i = _voice; i; i = i->next) { + _owner->setPitch(&i->out, (i->note << 7) + _pitchBend); + } +} + +void MacM68kDriver::MidiChannel_MacM68k::controlChange(byte control, byte value) { + switch (control) { + // volume change + case 7: + _volume = value; + for (VoiceChannel *i = _voice; i; i = i->next) { + i->out.volume = value; + i->out.isFinished = false; + } + break; + + // sustain + case 64: + _sustain = value; + if (!_sustain) { + for (VoiceChannel *i = _voice; i; i = i->next) { + if (i->sustainNoteOff) { + i->off(); + } + } + } + break; + + // all notes off + case 123: + for (VoiceChannel *i = _voice; i; i = i->next) { + i->off(); + } + break; + + default: + break; + } +} + +void MacM68kDriver::MidiChannel_MacM68k::pitchBendFactor(byte value) { + _pitchBendFactor = value; +} + +void MacM68kDriver::MidiChannel_MacM68k::priority(byte value) { + _priority = value; +} + +void MacM68kDriver::MidiChannel_MacM68k::sysEx_customInstrument(uint32 type, const byte *instr) { + assert(instr); + if (type == 'MAC ') { + _instrument = _owner->getInstrument(*instr + kSysExBase); + } +} + +void MacM68kDriver::MidiChannel_MacM68k::init(MacM68kDriver *owner, byte channel) { + _owner = owner; + _number = channel; + _allocated = false; +} + +bool MacM68kDriver::MidiChannel_MacM68k::allocate() { + if (_allocated) { + return false; + } + + _allocated = true; + _voice = 0; + _priority = 0; + memset(&_instrument, 0, sizeof(_instrument)); + _pitchBend = 0; + _pitchBendFactor = 0; + _volume = 0; + return true; +} + +void MacM68kDriver::MidiChannel_MacM68k::addVoice(VoiceChannel *voice) { + voice->next = _voice; + voice->prev = 0; + voice->part = this; + if (_voice) { + _voice->prev = voice; + } + _voice = voice; +} + +void MacM68kDriver::MidiChannel_MacM68k::removeVoice(VoiceChannel *voice) { + VoiceChannel *i = _voice; + while (i && i != voice) { + i = i->next; + } + + if (i) { + if (i->next) { + i->next->prev = i->prev; + } + + if (i->prev) { + i->prev->next = i->next; + } else { + _voice = i->next; + } + } +} + +MacM68kDriver::VoiceChannel *MacM68kDriver::allocateVoice(int priority) { + VoiceChannel *channel = 0; + for (int i = 0; i < kChannelCount; ++i) { + if (++_lastUsedVoiceChannel == kChannelCount) { + _lastUsedVoiceChannel = 0; + } + + VoiceChannel *cur = &_voiceChannels[_lastUsedVoiceChannel]; + if (!cur->part) { + memset(cur, 0, sizeof(*cur)); + return cur; + } else if (!cur->next) { + if (cur->part->_priority <= priority) { + priority = cur->part->_priority; + channel = cur; + } + } + } + + if (channel) { + channel->off(); + memset(channel, 0, sizeof(*channel)); + } + + return channel; +} + +const int MacM68kDriver::_volumeBaseTable[32] = { + 0, 0, 1, 1, 2, 3, 5, 6, + 8, 11, 13, 16, 19, 22, 26, 30, + 34, 38, 43, 48, 53, 58, 64, 70, + 76, 83, 89, 96, 104, 111, 119, 127 +}; + +} // End of namespace Scumm diff --git a/engines/scumm/imuse/mac_m68k.h b/engines/scumm/imuse/mac_m68k.h new file mode 100644 index 0000000000..59e2f68b9b --- /dev/null +++ b/engines/scumm/imuse/mac_m68k.h @@ -0,0 +1,177 @@ +/* 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. + */ + +#ifndef SCUMM_IMUSE_MAC_M68K_H +#define SCUMM_IMUSE_MAC_M68K_H + +#include "audio/softsynth/emumidi.h" + +#include "common/hashmap.h" + +namespace Common { +class SeekableReadStream; +} + +namespace Scumm { + +class MacM68kDriver : public MidiDriver_Emulated { + friend class MidiChannel_MacM68k; +public: + MacM68kDriver(Audio::Mixer *mixer); + ~MacM68kDriver(); + + virtual int open(); + virtual void close(); + + virtual void send(uint32 d); + virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr); + + virtual MidiChannel *allocateChannel(); + virtual MidiChannel *getPercussionChannel() { return 0; } + + virtual bool isStereo() const { return false; } + virtual int getRate() const { + // The original is using a frequency of approx. 22254.54546 here. + // To be precise it uses the 16.16 fixed point value 0x56EE8BA3. + return 22254; + } + +protected: + virtual void generateSamples(int16 *buf, int len); + virtual void onTimer() {} + +private: + int *_mixBuffer; + int _mixBufferLength; + + struct Instrument { + uint length; + uint sampleRate; + uint loopStart; + uint loopEnd; + int baseFrequency; + + byte *data; + }; + + enum { + kDefaultInstrument = 0x3E7, + kProgramChangeBase = 0x3E8, + kSysExBase = 0x7D0 + }; + + Instrument getInstrument(int idx) const; + typedef Common::HashMap<int, Instrument> InstrumentMap; + InstrumentMap _instruments; + Instrument _defaultInstrument; + void loadAllInstruments(); + void addInstrument(int idx, Common::SeekableReadStream *data); + + struct OutputChannel { + int pitchModifier; + + const byte *instrument; + uint subPos; + + const byte *start; + const byte *end; + + const byte *soundStart; + const byte *soundEnd; + const byte *loopStart; + const byte *loopEnd; + + int frequency; + int volume; + + bool isFinished; + + int baseFrequency; + }; + + void setPitch(OutputChannel *out, int frequency); + int _pitchTable[128]; + + byte *_volumeTable; + static const int _volumeBaseTable[32]; + + class MidiChannel_MacM68k; + + struct VoiceChannel { + MidiChannel_MacM68k *part; + VoiceChannel *prev, *next; + int channel; + int note; + bool sustainNoteOff; + OutputChannel out; + + void off(); + }; + + class MidiChannel_MacM68k : public MidiChannel { + friend class MacM68kDriver; + public: + virtual MidiDriver *device() { return _owner; } + virtual byte getNumber() { return _number; } + virtual void release(); + + virtual void send(uint32 b); + virtual void noteOff(byte note); + virtual void noteOn(byte note, byte velocity); + virtual void programChange(byte program); + virtual void pitchBend(int16 bend); + virtual void controlChange(byte control, byte value); + virtual void pitchBendFactor(byte value); + virtual void priority(byte value); + virtual void sysEx_customInstrument(uint32 type, const byte *instr); + + void init(MacM68kDriver *owner, byte channel); + bool allocate(); + + void addVoice(VoiceChannel *voice); + void removeVoice(VoiceChannel *voice); + private: + MacM68kDriver *_owner; + bool _allocated; + int _number; + + VoiceChannel *_voice; + int _priority; + int _sustain; + Instrument _instrument; + int _pitchBend; + int _pitchBendFactor; + int _volume; + }; + + MidiChannel_MacM68k _channels[32]; + + enum { + kChannelCount = 8 + }; + VoiceChannel _voiceChannels[kChannelCount]; + int _lastUsedVoiceChannel; + VoiceChannel *allocateVoice(int priority); +}; + +} // End of namespace Scumm + +#endif diff --git a/engines/scumm/imuse/sysex_scumm.cpp b/engines/scumm/imuse/sysex_scumm.cpp index 85ffc86f47..8f230ebac3 100644 --- a/engines/scumm/imuse/sysex_scumm.cpp +++ b/engines/scumm/imuse/sysex_scumm.cpp @@ -71,7 +71,7 @@ void sysexHandler_Scumm(Player *player, const byte *msg, uint16 len) { part->set_pri(buf[2]); part->volume(buf[3]); part->set_pan(buf[4]); - part->_percussion = player->_isMIDI ? ((buf[5] & 0x80) > 0) : false; + part->_percussion = player->_supportsPercussion ? ((buf[5] & 0x80) > 0) : false; part->set_transpose(buf[5]); part->set_detune(buf[6]); part->pitchBendFactor(buf[7]); diff --git a/engines/scumm/midiparser_ro.cpp b/engines/scumm/midiparser_ro.cpp index 1a31d1ca82..8549a9262d 100644 --- a/engines/scumm/midiparser_ro.cpp +++ b/engines/scumm/midiparser_ro.cpp @@ -62,13 +62,13 @@ void MidiParser_RO::parseNextEvent (EventInfo &info) { info.delta = 0; do { - info.start = _position._play_pos; - info.event = *(_position._play_pos++); + info.start = _position._playPos; + info.event = *(_position._playPos++); if (info.command() == 0xA) { ++_lastMarkerCount; info.event = 0xF0; } else if (info.event == 0xF0 || info.event == 0xF1) { - byte delay = *(_position._play_pos++); + byte delay = *(_position._playPos++); info.delta += delay; if (info.event == 0xF1) { // This event is, as far as we have been able @@ -95,16 +95,16 @@ void MidiParser_RO::parseNextEvent (EventInfo &info) { if (info.event < 0x80) return; - _position._running_status = info.event; + _position._runningStatus = info.event; switch (info.command()) { case 0xC: - info.basic.param1 = *(_position._play_pos++); + info.basic.param1 = *(_position._playPos++); info.basic.param2 = 0; break; case 0x8: case 0x9: case 0xB: - info.basic.param1 = *(_position._play_pos++); - info.basic.param2 = *(_position._play_pos++); + info.basic.param1 = *(_position._playPos++); + info.basic.param2 = *(_position._playPos++); if (info.command() == 0x9 && info.basic.param2 == 0) info.event = info.channel() | 0x80; info.length = 0; @@ -133,7 +133,7 @@ bool MidiParser_RO::loadMusic (byte *data, uint32 size) { return false; } - _num_tracks = 1; + _numTracks = 1; _ppqn = 120; _tracks[0] = pos + 2; _markerCount = _lastMarkerCount = 0; diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk index 1f219f5187..8499c9bad3 100644 --- a/engines/scumm/module.mk +++ b/engines/scumm/module.mk @@ -27,6 +27,7 @@ MODULE_OBJS := \ imuse/imuse_part.o \ imuse/imuse_player.o \ imuse/instrument.o \ + imuse/mac_m68k.o \ imuse/pcspk.o \ imuse/sysex_samnmax.o \ imuse/sysex_scumm.o \ diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp index 399cd91324..77c75c4ad6 100644 --- a/engines/scumm/object.cpp +++ b/engines/scumm/object.cpp @@ -335,7 +335,7 @@ int ScummEngine::whereIsObject(int object) const { return WIO_NOT_FOUND; if ((_game.version != 0 || OBJECT_V0_TYPE(object) == 0) && - _objectOwnerTable[object] != OF_OWNER_ROOM) + _objectOwnerTable[object] != OF_OWNER_ROOM) { for (i = 0; i < _numInventory; i++) if (_inventory[i] == object) @@ -1225,7 +1225,7 @@ byte *ScummEngine::getOBCDFromObject(int obj, bool v0CheckInventory) { byte *ptr; if ((_game.version != 0 || OBJECT_V0_TYPE(obj) == 0) && - _objectOwnerTable[obj] != OF_OWNER_ROOM) + _objectOwnerTable[obj] != OF_OWNER_ROOM) { if (_game.version == 0 && !v0CheckInventory) return 0; diff --git a/engines/scumm/player_apple2.cpp b/engines/scumm/player_apple2.cpp index a8e150caa9..58e4f78a94 100644 --- a/engines/scumm/player_apple2.cpp +++ b/engines/scumm/player_apple2.cpp @@ -61,8 +61,8 @@ public: private: void _update(int interval /*a*/, int count /*y*/) { // D076 - assert(interval > 0); // 0 == 256? - assert(count > 0); // 0 == 256? + assert(interval > 0); // 0 == 256? + assert(count > 0); // 0 == 256? for (; count >= 0; --count) { _player->speakerToggle(); @@ -99,7 +99,7 @@ public: ++_pos; return false; - } + } return true; } @@ -112,7 +112,7 @@ private: assert(interval > 0); // 0 == 256? int a = (interval >> 3) + count; - for (int y = a; y > 0; --y) { + for (int y = a; y > 0; --y) { _player->generateSamples(1292 - 5*interval); _player->speakerToggle(); @@ -206,7 +206,7 @@ private: _bitmask1 = 0x3; _bitmask2 = 0x3; - + _updateInterval2 = param0; if (_updateInterval2 == 0) _bitmask2 = 0x0; @@ -234,9 +234,9 @@ private: if (_updateRemain2 == 0) { _updateRemain2 = _updateInterval2; - // use only first voice's data (bitmask1) if both voices are triggered + // use only first voice's data (bitmask1) if both voices are triggered if (_updateRemain1 != 0) { - _speakerShiftReg ^= _bitmask2; + _speakerShiftReg ^= _bitmask2; } } @@ -256,7 +256,7 @@ private: protected: const byte *_params; - + byte _updateRemain1; byte _updateRemain2; @@ -309,7 +309,7 @@ private: for (int i = count; i > 0; --i) { _player->generateSamples(10 + 5*interval); _player->speakerToggle(); - + _player->generateSamples(5 + 5*interval); _player->speakerToggle(); } @@ -332,20 +332,20 @@ private: // LD000[loc] ^ LD00A[loc] const byte AppleII_SoundFunction5_Noise::_noiseTable[256] = { - 0x65, 0x1b, 0xda, 0x11, 0x61, 0xe5, 0x77, 0x57, 0x92, 0xc8, 0x51, 0x1c, 0xd4, 0x91, 0x62, 0x63, - 0x00, 0x38, 0x57, 0xd5, 0x18, 0xd8, 0xdc, 0x40, 0x03, 0x86, 0xd3, 0x2f, 0x10, 0x11, 0xd8, 0x3c, - 0xbe, 0x00, 0x19, 0xc5, 0xd2, 0xc3, 0xca, 0x34, 0x00, 0x28, 0xbf, 0xb9, 0x18, 0x20, 0x01, 0xcc, - 0xda, 0x08, 0xbc, 0x75, 0x7c, 0xb0, 0x8d, 0xe0, 0x09, 0x18, 0xbf, 0x5d, 0xe9, 0x8c, 0x75, 0x64, + 0x65, 0x1b, 0xda, 0x11, 0x61, 0xe5, 0x77, 0x57, 0x92, 0xc8, 0x51, 0x1c, 0xd4, 0x91, 0x62, 0x63, + 0x00, 0x38, 0x57, 0xd5, 0x18, 0xd8, 0xdc, 0x40, 0x03, 0x86, 0xd3, 0x2f, 0x10, 0x11, 0xd8, 0x3c, + 0xbe, 0x00, 0x19, 0xc5, 0xd2, 0xc3, 0xca, 0x34, 0x00, 0x28, 0xbf, 0xb9, 0x18, 0x20, 0x01, 0xcc, + 0xda, 0x08, 0xbc, 0x75, 0x7c, 0xb0, 0x8d, 0xe0, 0x09, 0x18, 0xbf, 0x5d, 0xe9, 0x8c, 0x75, 0x64, 0xe5, 0xb5, 0x5d, 0xe0, 0xb7, 0x7d, 0xe9, 0x8c, 0x55, 0x65, 0xc5, 0xb5, 0x5d, 0xd8, 0x09, 0x0d, - 0x64, 0xf0, 0xf0, 0x08, 0x63, 0x03, 0x00, 0x55, 0x35, 0xc0, 0x00, 0x20, 0x74, 0xa5, 0x1e, 0xe3, - 0x00, 0x06, 0x3c, 0x52, 0xd1, 0x70, 0xd0, 0x57, 0x02, 0xf0, 0x00, 0xb6, 0xfc, 0x02, 0x11, 0x9a, - 0x3b, 0xc8, 0x38, 0xdf, 0x1a, 0xb0, 0xd1, 0xb8, 0xd0, 0x18, 0x8a, 0x4a, 0xea, 0x1b, 0x12, 0x5d, - 0x29, 0x58, 0xd8, 0x43, 0xb8, 0x2d, 0xd2, 0x61, 0x10, 0x3c, 0x0c, 0x5d, 0x1b, 0x61, 0x10, 0x3c, + 0x64, 0xf0, 0xf0, 0x08, 0x63, 0x03, 0x00, 0x55, 0x35, 0xc0, 0x00, 0x20, 0x74, 0xa5, 0x1e, 0xe3, + 0x00, 0x06, 0x3c, 0x52, 0xd1, 0x70, 0xd0, 0x57, 0x02, 0xf0, 0x00, 0xb6, 0xfc, 0x02, 0x11, 0x9a, + 0x3b, 0xc8, 0x38, 0xdf, 0x1a, 0xb0, 0xd1, 0xb8, 0xd0, 0x18, 0x8a, 0x4a, 0xea, 0x1b, 0x12, 0x5d, + 0x29, 0x58, 0xd8, 0x43, 0xb8, 0x2d, 0xd2, 0x61, 0x10, 0x3c, 0x0c, 0x5d, 0x1b, 0x61, 0x10, 0x3c, 0x0a, 0x5d, 0x1d, 0x61, 0x10, 0x3c, 0x0b, 0x19, 0x88, 0x21, 0xc0, 0x21, 0x07, 0x00, 0x65, 0x62, - 0x08, 0xe9, 0x36, 0x40, 0x20, 0x41, 0x06, 0x00, 0x20, 0x00, 0x00, 0xed, 0xa3, 0x00, 0x88, 0x06, - 0x98, 0x01, 0x5d, 0x7f, 0x02, 0x1d, 0x78, 0x03, 0x60, 0xcb, 0x3a, 0x01, 0xbd, 0x78, 0x02, 0x5d, - 0x7e, 0x03, 0x1d, 0xf5, 0xa6, 0x40, 0x81, 0xb4, 0xd0, 0x8d, 0xd3, 0xd0, 0x6d, 0xd5, 0x61, 0x48, - 0x61, 0x4d, 0xd1, 0xc8, 0xb1, 0xd8, 0x69, 0xff, 0x61, 0xd9, 0xed, 0xa0, 0xfe, 0x19, 0x91, 0x37, + 0x08, 0xe9, 0x36, 0x40, 0x20, 0x41, 0x06, 0x00, 0x20, 0x00, 0x00, 0xed, 0xa3, 0x00, 0x88, 0x06, + 0x98, 0x01, 0x5d, 0x7f, 0x02, 0x1d, 0x78, 0x03, 0x60, 0xcb, 0x3a, 0x01, 0xbd, 0x78, 0x02, 0x5d, + 0x7e, 0x03, 0x1d, 0xf5, 0xa6, 0x40, 0x81, 0xb4, 0xd0, 0x8d, 0xd3, 0xd0, 0x6d, 0xd5, 0x61, 0x48, + 0x61, 0x4d, 0xd1, 0xc8, 0xb1, 0xd8, 0x69, 0xff, 0x61, 0xd9, 0xed, 0xa0, 0xfe, 0x19, 0x91, 0x37, 0x19, 0x37, 0x00, 0xf1, 0x00, 0x01, 0x1f, 0x00, 0xad, 0xc1, 0x01, 0x01, 0x2e, 0x00, 0x40, 0xc6, 0x7a, 0x9b, 0x95, 0x43, 0xfc, 0x18, 0xd2, 0x9e, 0x2a, 0x5a, 0x4b, 0x2a, 0xb6, 0x87, 0x30, 0x6c }; @@ -394,20 +394,20 @@ void Player_AppleII::startSound(int nr) { case 0: // empty (nothing to play) resetState(); return; - case 1: - _soundFunc = new AppleII_SoundFunction1_FreqUpDown(); + case 1: + _soundFunc = new AppleII_SoundFunction1_FreqUpDown(); break; - case 2: - _soundFunc = new AppleII_SoundFunction2_SymmetricWave(); + case 2: + _soundFunc = new AppleII_SoundFunction2_SymmetricWave(); break; - case 3: - _soundFunc = new AppleII_SoundFunction3_AsymmetricWave(); + case 3: + _soundFunc = new AppleII_SoundFunction3_AsymmetricWave(); break; - case 4: - _soundFunc = new AppleII_SoundFunction4_Polyphone(); + case 4: + _soundFunc = new AppleII_SoundFunction4_Polyphone(); break; - case 5: - _soundFunc = new AppleII_SoundFunction5_Noise(); + case 5: + _soundFunc = new AppleII_SoundFunction5_Noise(); break; } _soundFunc->init(this, _params); @@ -484,7 +484,7 @@ int Player_AppleII::readBuffer(int16 *buffer, const int numSamples) { // toggle speaker on/off void Player_AppleII::speakerToggle() { - _speakerState ^= 0x1; + _speakerState ^= 0x1; } void Player_AppleII::generateSamples(int cycles) { @@ -492,8 +492,8 @@ void Player_AppleII::generateSamples(int cycles) { } void Player_AppleII::wait(int interval, int count /*y*/) { - assert(count > 0); // 0 == 256? - assert(interval > 0); // 0 == 256? + assert(count > 0); // 0 == 256? + assert(interval > 0); // 0 == 256? generateSamples(11 + count*(8 + 5 * interval)); } diff --git a/engines/scumm/player_apple2.h b/engines/scumm/player_apple2.h index b4a7d409fb..e1ec9d8946 100644 --- a/engines/scumm/player_apple2.h +++ b/engines/scumm/player_apple2.h @@ -36,7 +36,7 @@ namespace Scumm { class ScummEngine; /* - * Optimized for use with periodical read/write phases when the buffer + * Optimized for use with periodical read/write phases when the buffer * is filled in a write phase and completely read in a read phase. * The growing strategy is optimized for repeated small (e.g. 2 bytes) * single writes resulting in large buffers @@ -133,7 +133,7 @@ static const double APPLEII_CPU_CLOCK = 1020484.5; // ~ 1.02 MHz /* * Converts the 1-bit speaker state values into audio samples. - * This is done by aggregation of the speaker states at each + * This is done by aggregation of the speaker states at each * CPU cycle in a sampling period into an audio sample. */ class SampleConverter { @@ -144,7 +144,7 @@ private: } public: - SampleConverter() : + SampleConverter() : _cyclesPerSampleFP(0), _missingCyclesFP(0), _sampleCyclesSumFP(0), @@ -156,7 +156,7 @@ public: void reset() { _missingCyclesFP = 0; _sampleCyclesSumFP = 0; - _buffer.clear(); + _buffer.clear(); } uint32 availableSize() const { @@ -245,7 +245,7 @@ public: virtual void setMusicVolume(int vol) { _sampleConverter.setMusicVolume(vol); } void setSampleRate(int rate) { _sampleRate = rate; - _sampleConverter.setSampleRate(rate); + _sampleConverter.setSampleRate(rate); } virtual void startSound(int sound); virtual void stopSound(int sound); diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp index 2588026e59..33e3e40e39 100644 --- a/engines/scumm/player_towns.cpp +++ b/engines/scumm/player_towns.cpp @@ -87,7 +87,7 @@ void Player_Towns::restoreAfterLoad() { if (!_v2) restoredSounds.push_back(_pcmCurrentSound[i].index); - + uint8 *ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index); if (!ptr) continue; diff --git a/engines/scumm/player_v2cms.cpp b/engines/scumm/player_v2cms.cpp index d4b21774ed..c1242e0645 100644 --- a/engines/scumm/player_v2cms.cpp +++ b/engines/scumm/player_v2cms.cpp @@ -718,38 +718,38 @@ void Player_V2CMS::playMusicChips(const MusicChip *table) { } const Player_V2CMS::MidiNote Player_V2CMS::_midiNotes[132] = { - { 3, 0 }, { 31, 0 }, { 58, 0 }, { 83, 0 }, - { 107, 0 }, { 130, 0 }, { 151, 0 }, { 172, 0 }, - { 191, 0 }, { 209, 0 }, { 226, 0 }, { 242, 0 }, - { 3, 1 }, { 31, 1 }, { 58, 1 }, { 83, 1 }, - { 107, 1 }, { 130, 1 }, { 151, 1 }, { 172, 1 }, - { 191, 1 }, { 209, 1 }, { 226, 1 }, { 242, 1 }, - { 3, 2 }, { 31, 2 }, { 58, 2 }, { 83, 2 }, - { 107, 2 }, { 130, 2 }, { 151, 2 }, { 172, 2 }, - { 191, 2 }, { 209, 2 }, { 226, 2 }, { 242, 2 }, - { 3, 3 }, { 31, 3 }, { 58, 3 }, { 83, 3 }, - { 107, 3 }, { 130, 3 }, { 151, 3 }, { 172, 3 }, - { 191, 3 }, { 209, 3 }, { 226, 3 }, { 242, 3 }, - { 3, 4 }, { 31, 4 }, { 58, 4 }, { 83, 4 }, - { 107, 4 }, { 130, 4 }, { 151, 4 }, { 172, 4 }, - { 191, 4 }, { 209, 4 }, { 226, 4 }, { 242, 4 }, - { 3, 5 }, { 31, 5 }, { 58, 5 }, { 83, 5 }, - { 107, 5 }, { 130, 5 }, { 151, 5 }, { 172, 5 }, - { 191, 5 }, { 209, 5 }, { 226, 5 }, { 242, 5 }, - { 3, 6 }, { 31, 6 }, { 58, 6 }, { 83, 6 }, - { 107, 6 }, { 130, 6 }, { 151, 6 }, { 172, 6 }, - { 191, 6 }, { 209, 6 }, { 226, 6 }, { 242, 6 }, - { 3, 7 }, { 31, 7 }, { 58, 7 }, { 83, 7 }, - { 107, 7 }, { 130, 7 }, { 151, 7 }, { 172, 7 }, - { 191, 7 }, { 209, 7 }, { 226, 7 }, { 242, 7 }, - { 3, 8 }, { 31, 8 }, { 58, 8 }, { 83, 8 }, - { 107, 8 }, { 130, 8 }, { 151, 8 }, { 172, 8 }, - { 191, 8 }, { 209, 8 }, { 226, 8 }, { 242, 8 }, - { 3, 9 }, { 31, 9 }, { 58, 9 }, { 83, 9 }, - { 107, 9 }, { 130, 9 }, { 151, 9 }, { 172, 9 }, - { 191, 9 }, { 209, 9 }, { 226, 9 }, { 242, 9 }, - { 3, 10 }, { 31, 10 }, { 58, 10 }, { 83, 10 }, - { 107, 10 }, { 130, 10 }, { 151, 10 }, { 172, 10 }, + { 3, 0 }, { 31, 0 }, { 58, 0 }, { 83, 0 }, + { 107, 0 }, { 130, 0 }, { 151, 0 }, { 172, 0 }, + { 191, 0 }, { 209, 0 }, { 226, 0 }, { 242, 0 }, + { 3, 1 }, { 31, 1 }, { 58, 1 }, { 83, 1 }, + { 107, 1 }, { 130, 1 }, { 151, 1 }, { 172, 1 }, + { 191, 1 }, { 209, 1 }, { 226, 1 }, { 242, 1 }, + { 3, 2 }, { 31, 2 }, { 58, 2 }, { 83, 2 }, + { 107, 2 }, { 130, 2 }, { 151, 2 }, { 172, 2 }, + { 191, 2 }, { 209, 2 }, { 226, 2 }, { 242, 2 }, + { 3, 3 }, { 31, 3 }, { 58, 3 }, { 83, 3 }, + { 107, 3 }, { 130, 3 }, { 151, 3 }, { 172, 3 }, + { 191, 3 }, { 209, 3 }, { 226, 3 }, { 242, 3 }, + { 3, 4 }, { 31, 4 }, { 58, 4 }, { 83, 4 }, + { 107, 4 }, { 130, 4 }, { 151, 4 }, { 172, 4 }, + { 191, 4 }, { 209, 4 }, { 226, 4 }, { 242, 4 }, + { 3, 5 }, { 31, 5 }, { 58, 5 }, { 83, 5 }, + { 107, 5 }, { 130, 5 }, { 151, 5 }, { 172, 5 }, + { 191, 5 }, { 209, 5 }, { 226, 5 }, { 242, 5 }, + { 3, 6 }, { 31, 6 }, { 58, 6 }, { 83, 6 }, + { 107, 6 }, { 130, 6 }, { 151, 6 }, { 172, 6 }, + { 191, 6 }, { 209, 6 }, { 226, 6 }, { 242, 6 }, + { 3, 7 }, { 31, 7 }, { 58, 7 }, { 83, 7 }, + { 107, 7 }, { 130, 7 }, { 151, 7 }, { 172, 7 }, + { 191, 7 }, { 209, 7 }, { 226, 7 }, { 242, 7 }, + { 3, 8 }, { 31, 8 }, { 58, 8 }, { 83, 8 }, + { 107, 8 }, { 130, 8 }, { 151, 8 }, { 172, 8 }, + { 191, 8 }, { 209, 8 }, { 226, 8 }, { 242, 8 }, + { 3, 9 }, { 31, 9 }, { 58, 9 }, { 83, 9 }, + { 107, 9 }, { 130, 9 }, { 151, 9 }, { 172, 9 }, + { 191, 9 }, { 209, 9 }, { 226, 9 }, { 242, 9 }, + { 3, 10 }, { 31, 10 }, { 58, 10 }, { 83, 10 }, + { 107, 10 }, { 130, 10 }, { 151, 10 }, { 172, 10 }, { 191, 10 }, { 209, 10 }, { 226, 10 }, { 242, 10 } }; diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index beac077fd1..72896e097a 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -1298,7 +1298,7 @@ void ScummEngine::saveOrLoad(Serializer *s) { s->saveLoadArrayOf(_16BitPalette, 512, sizeof(_16BitPalette[0]), sleUint16); } - + // FM-Towns specific (extra palette data, color cycle data, etc.) // In earlier save game versions (below 87) the FM-Towns specific data would get saved (and loaded) even in non FM-Towns games. // This would cause an unnecessary save file incompatibility between DS (which uses the DISABLE_TOWNS_DUAL_LAYER_MODE setting) diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h index d5f7ea526e..a640bc1e17 100644 --- a/engines/scumm/saveload.h +++ b/engines/scumm/saveload.h @@ -47,7 +47,7 @@ namespace Scumm { * only saves/loads those which are valid for the version of the savegame * which is being loaded/saved currently. */ -#define CURRENT_VER 92 +#define CURRENT_VER 93 /** * An auxillary macro, used to specify savegame versions. We use this instead diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp index 44b77f1d18..361287d29f 100644 --- a/engines/scumm/script_v0.cpp +++ b/engines/scumm/script_v0.cpp @@ -602,7 +602,7 @@ void ScummEngine_v0::o_loadRoomWithEgo() { x = r.x; y = r.y; a->putActor(x, y, _currentRoom); - + camera._dest.x = camera._cur.x = a->getPos().x; setCameraAt(a->getPos().x, a->getPos().y); setCameraFollows(a); @@ -635,18 +635,18 @@ void ScummEngine_v0::setMode(byte mode) { case kModeCutscene: _redrawSentenceLine = false; // Note: do not change freeze state here - state = USERSTATE_SET_IFACE | + state = USERSTATE_SET_IFACE | USERSTATE_SET_CURSOR; break; case kModeKeypad: _redrawSentenceLine = false; - state = USERSTATE_SET_IFACE | + state = USERSTATE_SET_IFACE | USERSTATE_SET_CURSOR | USERSTATE_CURSOR_ON | USERSTATE_SET_FREEZE | USERSTATE_FREEZE_ON; break; case kModeNormal: case kModeNoNewKid: - state = USERSTATE_SET_IFACE | USERSTATE_IFACE_ALL | + state = USERSTATE_SET_IFACE | USERSTATE_IFACE_ALL | USERSTATE_SET_CURSOR | USERSTATE_CURSOR_ON | USERSTATE_SET_FREEZE; break; @@ -688,7 +688,7 @@ void ScummEngine_v0::o_animateActor() { Actor_v0 *a = (Actor_v0*) derefActor(act, "o_animateActor"); a->_animFrameRepeat = repeat; - + switch (anim) { case 0xFE: @@ -700,7 +700,7 @@ void ScummEngine_v0::o_animateActor() { // 0x69A3 a->_speaking = 0x00; return; - + case 0xFF: a->stopActorMoving(); return; diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp index ce162b4a6a..96d422d5bb 100644 --- a/engines/scumm/script_v2.cpp +++ b/engines/scumm/script_v2.cpp @@ -993,7 +993,7 @@ void ScummEngine_v2::o2_drawSentence() { const byte *temp; int slot = getVerbSlot(VAR(VAR_SENTENCE_VERB), 0); - if (!((_userState & USERSTATE_IFACE_SENTENCE) || + if (!((_userState & USERSTATE_IFACE_SENTENCE) || (_game.platform == Common::kPlatformNES && (_userState & USERSTATE_IFACE_ALL)))) return; @@ -1486,8 +1486,8 @@ void ScummEngine_v2::o2_cutscene() { VAR(VAR_CURSORSTATE) = 200; // Hide inventory, freeze scripts, hide cursor - setUserState(USERSTATE_SET_IFACE | - USERSTATE_SET_CURSOR | + setUserState(USERSTATE_SET_IFACE | + USERSTATE_SET_CURSOR | USERSTATE_SET_FREEZE | USERSTATE_FREEZE_ON); _sentenceNum = 0; diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp index a5591b701f..0bf51a2816 100644 --- a/engines/scumm/script_v5.cpp +++ b/engines/scumm/script_v5.cpp @@ -1097,7 +1097,7 @@ void ScummEngine_v5::o5_getDist() { int r; getResultPos(); - + o1 = getVarOrDirectWord(PARAM_1); o2 = getVarOrDirectWord(PARAM_2); diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index d0f46f3e56..2c79fb8de0 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -73,6 +73,7 @@ #include "scumm/util.h" #include "scumm/verbs.h" #include "scumm/imuse/pcspk.h" +#include "scumm/imuse/mac_m68k.h" #include "backends/audiocd/audiocd.h" @@ -1835,17 +1836,31 @@ void ScummEngine::setupMusic(int midi) { } else if (_game.version >= 3 && _game.heversion <= 62) { MidiDriver *nativeMidiDriver = 0; MidiDriver *adlibMidiDriver = 0; - - if (_sound->_musicType != MDT_ADLIB && _sound->_musicType != MDT_TOWNS && _sound->_musicType != MDT_PCSPK) + bool multi_midi = ConfMan.getBool("multi_midi") && _sound->_musicType != MDT_NONE && _sound->_musicType != MDT_PCSPK && (midi & MDT_ADLIB); + bool useOnlyNative = false; + + if (isMacM68kIMuse()) { + // We setup this driver as native MIDI driver to avoid playback + // of the Mac music via a selected MIDI device. + nativeMidiDriver = new MacM68kDriver(_mixer); + // The Mac driver is never MT-32. + _native_mt32 = false; + // Ignore non-native drivers. This also ignores the multi MIDI setting. + useOnlyNative = true; + } else if (_sound->_musicType != MDT_ADLIB && _sound->_musicType != MDT_TOWNS && _sound->_musicType != MDT_PCSPK) { nativeMidiDriver = MidiDriver::createMidi(dev); + } + if (nativeMidiDriver != NULL && _native_mt32) nativeMidiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - bool multi_midi = ConfMan.getBool("multi_midi") && _sound->_musicType != MDT_NONE && _sound->_musicType != MDT_PCSPK && (midi & MDT_ADLIB); - if (_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS || multi_midi) { - adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(_sound->_musicType == MDT_TOWNS ? MDT_TOWNS : MDT_ADLIB)); - adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0); - } else if (_sound->_musicType == MDT_PCSPK) { - adlibMidiDriver = new PcSpkDriver(_mixer); + + if (!useOnlyNative) { + if (_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS || multi_midi) { + adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(_sound->_musicType == MDT_TOWNS ? MDT_TOWNS : MDT_ADLIB)); + adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0); + } else if (_sound->_musicType == MDT_PCSPK) { + adlibMidiDriver = new PcSpkDriver(_mixer); + } } _imuse = IMuse::create(_system, nativeMidiDriver, adlibMidiDriver); @@ -1971,11 +1986,11 @@ Common::Error ScummEngine::go() { if (delta < 1) // Ensure we don't get into an endless loop delta = 1; // by not decreasing sleepers. - // WORKAROUND: walking speed in the original v0/v1 interpreter + // WORKAROUND: walking speed in the original v0/v1 interpreter // is sometimes slower (e.g. during scrolling) than in ScummVM. // This is important for the door-closing action in the dungeon, - // otherwise (delta < 6) a single kid is able to escape. - if ((_game.version == 0 && isScriptRunning(132)) || + // otherwise (delta < 6) a single kid is able to escape. + if ((_game.version == 0 && isScriptRunning(132)) || (_game.version == 1 && isScriptRunning(137))) delta = 6; diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index c8cf096a19..a77c1c0141 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -150,7 +150,13 @@ enum GameFeatures { GF_HE_985 = 1 << 14, /** HE games with 16 bit color */ - GF_16BIT_COLOR = 1 << 15 + GF_16BIT_COLOR = 1 << 15, + + /** + * SCUMM v5-v7 Mac games stored in a container file + * Used to differentiate between m68k and PPC versions of Indy4 + */ + GF_MAC_CONTAINER = 1 << 16 }; /* SCUMM Debug Channels */ @@ -713,6 +719,9 @@ public: bool openFile(BaseScummFile &file, const Common::String &filename, bool resourceFile = false); + /** Is this game a Mac m68k v5 game with iMuse? */ + bool isMacM68kIMuse() const; + protected: int _resourceHeaderSize; byte _resourceMapper[128]; @@ -1363,7 +1372,7 @@ public: public: bool towns_isRectInStringBox(int x1, int y1, int x2, int y2); byte _townsPaletteFlags; - byte _townsCharsetColorMap[16]; + byte _townsCharsetColorMap[16]; protected: void towns_drawStripToScreen(VirtScreen *vs, int dstX, int dstY, int srcX, int srcY, int w, int h); diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index 1dc026ad52..a1cecfa0b3 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -248,7 +248,10 @@ void Sound::playSound(int soundID) { _mixer->playStream(Audio::Mixer::kSFXSoundType, NULL, stream, soundID); } // Support for sampled sound effects in Monkey Island 1 and 2 - else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) { + else if (_vm->_game.platform != Common::kPlatformFMTowns + // The Macintosh m68k versions of MI2/Indy4 just ignore SBL effects. + && !_vm->isMacM68kIMuse() + && READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) { debugC(DEBUG_SOUND, "Using SBL sound effect"); // SBL resources essentially contain VOC sound data. @@ -954,7 +957,7 @@ void Sound::setupSfxFile() { if (file.open(tmp)) _sfxFilename = tmp; - + if (_vm->_game.heversion <= 74) _sfxFileEncByte = 0x69; @@ -1179,7 +1182,7 @@ int ScummEngine::readSoundResource(ResId idx) { // its sound resources, and Amiga games, which feature only ROL // resources, since we are a doing Midi -> AdLib conversion for // these. - if ((_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS) && pri != 16 + if ((_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS) && pri != 16 && pri != 15 && pri != 10 && pri != 2 && _game.platform != Common::kPlatformAmiga) pri = -1; diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp index 567ca31485..0d0f6cdb95 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -84,7 +84,7 @@ int ScummEngine_v0::verbPrepIdType(int verbid) { switch (verbid) { case kVerbUse: // depends on object1 return kVerbPrepObject; - case kVerbGive: + case kVerbGive: return kVerbPrepTo; case kVerbUnlock: case kVerbFix: return kVerbPrepWith; @@ -693,7 +693,7 @@ void ScummEngine_v0::verbExec() { if (_activeVerb == kVerbWhatIs) return; - + if (!(_activeVerb == kVerbWalkTo && _activeObject == 0)) { doSentence(_activeVerb, _activeObject, _activeObject2); if (_activeVerb != kVerbWalkTo) { |