[Scummvm-git-logs] scummvm master -> 43ef42c76405d5854b0d77bb77d3df5d8ae7286b
neuromancer
noreply at scummvm.org
Fri Sep 11 06:11:47 UTC 2026
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
b8abda6f64 EEM: several fixes for animations in EEM2 (mac cd)
43ef42c764 SCUMM: RA1: correctly render special german character in subtitles
Commit: b8abda6f643f011a08fa9ea63a1b247538007297
https://github.com/scummvm/scummvm/commit/b8abda6f643f011a08fa9ea63a1b247538007297
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-09-11T08:11:32+02:00
Commit Message:
EEM: several fixes for animations in EEM2 (mac cd)
Changed paths:
engines/eem/audio.cpp
engines/eem/clues.cpp
engines/eem/eem.cpp
engines/eem/eem.h
engines/eem/graphics.cpp
engines/eem/map_ui.cpp
engines/eem/module.mk
engines/eem/site.cpp
engines/eem/site.h
engines/eem/ui.cpp
diff --git a/engines/eem/audio.cpp b/engines/eem/audio.cpp
index 29c0b6ece2e..2d4b760444a 100644
--- a/engines/eem/audio.cpp
+++ b/engines/eem/audio.cpp
@@ -64,6 +64,7 @@ const MacSndResource kMacSndResources[] = {
{ "M-0107SL", 7011 }, { "M-0113SL", 7013 }, { "M-0115SL", 7014 },
{ "M-0163SL", 7024 }, { "NEWSCAN", 7003 }, { "NEWSSHRT", 7007 },
{ "PHONESL", 7012 }, { "SQUAK2SL", 7019 }, { "THUNDER", 7025 },
+ { "PHONE1", 1399 },
};
Common::String macSndNameFromPath(const Common::Path &path) {
@@ -265,6 +266,9 @@ void AudioPlayer::playMacSnd(uint16 resourceId, Audio::SoundHandle &handle,
if (!stream)
stream = openMacResource(Common::Path("Eagle Eye Mysteries CD"),
MKTAG('s', 'n', 'd', ' '), resourceId);
+ if (!stream && _vm->isLondon())
+ stream = openMacResource(Common::Path("EEM London CD"),
+ MKTAG('s', 'n', 'd', ' '), resourceId);
if (!stream) {
warning("AudioPlayer: Mac snd resource %u missing", resourceId);
return;
diff --git a/engines/eem/clues.cpp b/engines/eem/clues.cpp
index 3d88c85b522..f05194df612 100644
--- a/engines/eem/clues.cpp
+++ b/engines/eem/clues.cpp
@@ -373,22 +373,101 @@ void EEMEngine::doChoosePartner() {
}
}
-// EEM2 case-intro animation â `_DoInitClues` @ 1abf:03b3.
+// Mac London CODE 6:324c.
+void EEMEngine::playMacLondonInitCluesAnim(uint16 caseType, const Picture &bg,
+ bool haveBriefingBg) {
+ const MacSpritePaletteMap palette = getMacSpritePaletteMap();
+ Graphics::ManagedSurface background(screenWidth(), screenHeight(),
+ Graphics::PixelFormat::createFormatCLUT8());
+ background.clear();
+ if (haveBriefingBg)
+ background.simpleBlitFrom(bg.surface);
+ remapMacSurfaceEndpoints(background, palette);
+ Graphics::ManagedSurface base;
+ base.copyFrom(background);
+ byte pal[kPalSize];
+ const bool havePalette = getSitePalette(0x39, pal);
+ byte black[kPalSize] = {};
+ g_system->getPaletteManager()->setPalette(black, 0, 256);
+ const uint16 music[] = { 27, 36, 28, 29, 36 };
+ bool firstFrame = true;
+
+ auto playAnimation = [&](uint id, int x, int y) {
+ Animation anim;
+ if (!_aniArchive.loadAnimation(id, anim) || anim.empty())
+ return;
+ bool skip = false;
+ for (uint i = 0; i < anim.size() && !shouldQuit(); ++i) {
+ Graphics::ManagedSurface frame;
+ frame.copyFrom(base);
+ blitMacAnimFrameAnchored(frame.surfacePtr(), anim[i], x, y, palette);
+ g_system->copyRectToScreen(frame.getPixels(), frame.pitch, 0, 0, frame.w, frame.h);
+ if (firstFrame) {
+ if (havePalette)
+ fadePaletteFromBlack(pal);
+ if (_music && _musicOn && caseType < ARRAYSIZE(music))
+ _music->playMus(music[caseType], true);
+ firstFrame = false;
+ }
+ g_system->updateScreen();
+ if (i + 1 == anim.size())
+ base.copyFrom(frame);
+ const uint32 start = g_system->getMillis();
+ while (!skip && !shouldQuit() &&
+ g_system->getMillis() - start < animationFramePeriodMs()) {
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event)) {
+ if (event.type == Common::EVENT_QUIT ||
+ event.type == Common::EVENT_RETURN_TO_LAUNCHER)
+ return;
+ if (event.type == Common::EVENT_KEYDOWN ||
+ event.type == Common::EVENT_LBUTTONDOWN)
+ skip = true;
+ }
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ }
+ }
+ };
+
+ playAnimation(_partner == kPartnerJake ? 0x18 : 0x1c,
+ 332, _partner == kPartnerJake ? 120 : 118);
+ if (shouldQuit())
+ return;
+ switch (caseType) {
+ case 0: playAnimation(0x24, 0, 94); break;
+ case 2: playAnimation(0x26, 0, 90); break;
+ case 3: playAnimation(0x27, 0, 77); break;
+ default: break;
+ }
+ if (shouldQuit())
+ return;
+ if (caseType == 1 && _audio)
+ _audio->playVoc(Common::Path("phone1.voc"));
+ base.copyRectToSurface(background.getBasePtr(256, 0), background.pitch,
+ 256, 0, 256, screenHeight());
+ const uint partnerAni = caseType == 1
+ ? (_partner == kPartnerJake ? 0x17 : 0x1e)
+ : (_partner == kPartnerJake ? 0x19 : 0x1d);
+ playAnimation(partnerAni, 332, _partner == kPartnerJake ? 120 : 119);
+ if (_audio)
+ _audio->stopVoice();
+}
+
+// EEM2 DOS case-intro animation â `_DoInitClues` @ 1abf:03b3.
void EEMEngine::playLondonInitCluesAnim(uint16 caseType, const Picture &bg,
bool haveBriefingBg) {
- const bool mac = isMacintosh();
- const uint introAni = mac ? (_partner == kPartnerJake ? 0x18 : 0x1c)
- : (_partner == kPartnerJake ? 0x18 : 0x71);
- const uint introScript = mac ? 0x17 : 0x18;
- const int kAnchorX = mac ? 0x14c : 0xd2;
- const int kAnchorY = mac ? (_partner == kPartnerJake ? 0x78 : 0x76)
- : 0x3f;
+ if (isMacintosh()) {
+ playMacLondonInitCluesAnim(caseType, bg, haveBriefingBg);
+ return;
+ }
+ const uint introAni = _partner == kPartnerJake ? 0x18 : 0x71;
+ const uint introScript = 0x18;
+ const int kAnchorX = 0xd2;
+ const int kAnchorY = 0x3f;
Animation anim;
const bool haveAnim =
_aniArchive.loadAnimation(introAni, anim) && !anim.empty();
- MacSpritePaletteMap macPaletteMap = {0x00, 0xFF};
- if (mac)
- macPaletteMap = getMacSpritePaletteMap();
// `_DoInitClues @ 1abf:03b3` registers a SECOND, fixed briefing character
// (Nigel) on the LEFT, gated on caseType (jumptable @ CS:0x720):
@@ -423,22 +502,13 @@ void EEMEngine::playLondonInitCluesAnim(uint16 caseType, const Picture &bg,
const uint cell =
partnerFrameAtTick((uint16)introScript,
(uint)anim.size(), frame * 140);
- if (mac)
- blitMacAnimFrameAnchored(scr, anim[cell],
- kAnchorX, kAnchorY,
- macPaletteMap);
- else
- blitAnimFrameAnchored(scr, anim[cell], kAnchorX, kAnchorY);
+ blitAnimFrameAnchored(scr, anim[cell], kAnchorX, kAnchorY);
}
if (haveNpc) {
// NPC frame script = 0x0e (the `_NewAnimation` animId arg).
const uint ncell =
partnerFrameAtTick(0x0e, (uint)npc.size(), frame * 140);
- if (mac)
- blitMacAnimFrameAnchored(scr, npc[ncell], npcX, npcY,
- macPaletteMap);
- else
- blitAnimFrameAnchored(scr, npc[ncell], npcX, npcY);
+ blitAnimFrameAnchored(scr, npc[ncell], npcX, npcY);
}
g_system->unlockScreen();
}
@@ -751,6 +821,11 @@ void EEMEngine::doInitClues() {
marked);
displayClue(briefingClues);
}
+ if (isMacintosh() && isLondon()) {
+ _mystery._onSites[0] = 1;
+ stopMusic();
+ fadeCurrentPaletteToBlack();
+ }
}
void splitLondonPlayerName(const Common::String &displayName,
@@ -945,7 +1020,7 @@ void EEMEngine::displayClue(const byte *clueBlock, uint maxEntries) {
const uint stride = isLondon() ? 0x54 : 62;
const bool mac = isMacintosh();
- const bool macSolved = isMacCD() && clueBlock == _mystery.solvedClueBlock();
+ const bool macSolved = isMacTalkie() && clueBlock == _mystery.solvedClueBlock();
const int sw = screenWidth();
const int sh = screenHeight();
MacSpritePaletteMap macPaletteMap = {0x00, 0xFF};
@@ -982,7 +1057,7 @@ void EEMEngine::displayClue(const byte *clueBlock, uint maxEntries) {
// 5 notebook entries (-1 terminated)
// EEM1 +0x3a / EEM2 +0x4e: KD-anim number (-1 = none)
for (uint i = 0; i < count && !shouldQuit(); i++) {
- if (isMacCD() && _audio)
+ if (isMacTalkie() && _audio)
_audio->stopSpool();
g_system->copyRectToScreen(bg.getPixels(), bg.pitch, 0, 0, sw, sh);
const byte *c = clueBlock + 4 + i * stride;
@@ -1027,7 +1102,7 @@ void EEMEngine::displayClue(const byte *clueBlock, uint maxEntries) {
// ClueBlock +2; entries N>0 read (entry-1)+0x3c (last word).
const uint16 charX = READ_LE_UINT16(c + (useP1 ? 4 : 0));
// Mac CD adds 7.68 to the portrait Y and rounds to an integer.
- const int charY = READ_LE_UINT16(c + (useP1 ? 6 : 2)) + (isMacCD() ? 8 : 0);
+ const int charY = READ_LE_UINT16(c + (useP1 ? 6 : 2)) + (isMacTalkie() ? 8 : 0);
uint16 charPicId = (i == 0)
? READ_LE_UINT16(clueBlock + 2)
: READ_LE_UINT16(c - 2);
@@ -1105,7 +1180,7 @@ void EEMEngine::displayClue(const byte *clueBlock, uint maxEntries) {
copyY = bubY;
}
- if (isMacCD()) {
+ if (isMacTalkie()) {
dialogFont.drawMacWordWrapped(&scratch, textX, textY,
MAX<int>(8, textW), text, textColor);
} else {
diff --git a/engines/eem/eem.cpp b/engines/eem/eem.cpp
index 2ad0385e342..ccb235c372c 100644
--- a/engines/eem/eem.cpp
+++ b/engines/eem/eem.cpp
@@ -322,7 +322,7 @@ EEMEngine::EEMEngine(OSystem *syst, const ADGameDescription *gameDesc)
if (gameDesc && gameDesc->gameId &&
Common::String(gameDesc->gameId) == "eem2")
_variant = kVariantLondonCD;
- setAnimScripts(isLondon(), isMacCD());
+ setAnimScripts(isLondon(), isMacTalkie());
_language = gameDesc ? gameDesc->language : Common::EN_ANY;
}
@@ -576,7 +576,7 @@ Common::Error EEMEngine::run() {
warning("Mac FONT resource failed to load; text will not render");
if (!loadMacDialogFont(_dialogFont))
warning("Mac dialog FONT resource failed to load");
- if (isMacCD() && !loadMacFontResource(_newspaperFont, kMacSmallFontResource, 9))
+ if (isMacTalkie() && !loadMacFontResource(_newspaperFont, kMacSmallFontResource, 9))
warning("Mac newspaper FONT resource failed to load");
} else if (!_font.load(Common::Path("FONT.FNT"))) {
warning("FONT.FNT failed to load; text will not render");
@@ -2219,17 +2219,25 @@ void EEMEngine::startLondonTravelMusic(uint8 travelKind) {
{ 7, 23, 17 },
{ 10, 21, 24 },
};
+ static const uint16 kMacLondonTravelMusic[4][3] = {
+ { 0, 0, 0 },
+ { 22, 25, 7 },
+ { 23, 17, 10 },
+ { 21, 24, 35 },
+ };
if (!_music || !_musicOn || travelKind == 0 ||
travelKind >= ARRAYSIZE(kLondonTravelMusic))
return;
- const uint track = kLondonTravelMusic[travelKind][_rng.getRandomNumber(2)];
+ const uint choice = _rng.getRandomNumber(2);
+ const uint track = isMacintosh() ? kMacLondonTravelMusic[travelKind][choice]
+ : kLondonTravelMusic[travelKind][choice];
_music->playMus(track, /* loop= */ false);
}
void EEMEngine::finishTravelMusic(bool skipped) {
- // Mac CD fades after the entrance; DOS lets the travel tune finish.
- if (isMacCD()) {
+ // Mac talkies fade after the animation; EEM1 DOS lets the tune finish.
+ if (isMacTalkie()) {
if (_music && _music->isPlaying() && !shouldQuit()) {
_music->fadeOut();
const uint32 startMs = g_system->getMillis();
diff --git a/engines/eem/eem.h b/engines/eem/eem.h
index d293ed3e3af..c263726f307 100644
--- a/engines/eem/eem.h
+++ b/engines/eem/eem.h
@@ -141,6 +141,7 @@ public:
// rather than the single-valued `_variant` (which can only hold one of
// them at a time). This lets EEM2 Mac be both London and Macintosh.
bool isMacintosh() const { return getPlatform() == Common::kPlatformMacintosh; }
+ bool isMacTalkie() const { return isMacCD() || (isMacintosh() && isLondon()); }
bool isDemo() const {
return _gameDescription && (_gameDescription->flags & ADGF_DEMO);
}
@@ -215,6 +216,7 @@ public:
/// EEM2/London `_DoPuzzle @ 2542:1482`. A clue entry can gate the rest of
/// itself behind a "check the manual / a real map" puzzle
bool doPuzzle(uint puzzleId);
+ bool doMacLondonPuzzle(Common::SeekableReadStream &stream);
void displayFloppyHotspotDialog(uint siteNum, uint hotIdx);
@@ -516,6 +518,8 @@ private:
void showLondonCharSelect();
void playLondonInitCluesAnim(uint16 caseType, const Picture &bg,
bool haveBriefingBg);
+ void playMacLondonInitCluesAnim(uint16 caseType, const Picture &bg,
+ bool haveBriefingBg);
void playCdFloppyInitCluesAnim(uint16 caseType, bool floppy,
const Picture &bg, bool haveBriefingBg);
@@ -600,6 +604,7 @@ public:
/// EEM2 `_DoTravel @ 1717:0622` transition music. The matrix entry
/// (1..3) chooses one of three short one-shot MUS tracks at random.
void startLondonTravelMusic(uint8 travelKind);
+ bool playMacLondonTravelAnimation(uint8 travelKind);
private:
static int scaleCoord(int value, int target, int source) {
const bool negative = value < 0;
diff --git a/engines/eem/graphics.cpp b/engines/eem/graphics.cpp
index 2eb36fbd15d..fee4139ff41 100644
--- a/engines/eem/graphics.cpp
+++ b/engines/eem/graphics.cpp
@@ -116,7 +116,7 @@ uint EEMEngine::getBalloonLineCapacity(uint16 balloonId, int lineH) const {
const BalloonInsets &insets = kBalloonInsetTable[idx];
int textHeight = (int)insets.indDY - (int)insets.y;
- if (isMacCD())
+ if (isMacTalkie())
textHeight = insets.indDY * kMacScreenHeight / kScreenHeight -
insets.y * kMacScreenHeight / kScreenHeight;
else if (isMacintosh())
@@ -239,6 +239,9 @@ bool EEMEngine::doPuzzle(uint puzzleId) {
return true;
}
+ if (isMacintosh() && isLondon() && bigEndian)
+ return doMacLondonPuzzle(f);
+
const uint16 type = readPuzzleU16(f, bigEndian);
const int sw = screenWidth();
const int sh = screenHeight();
@@ -813,7 +816,7 @@ uint16 EEMEngine::fitBalloonToText(uint16 bubNum,
return bubNum;
const BalloonInsets &originalInsets = kBalloonInsetTable[originalId];
- const int lineH = isMacCD() ? 16 : _font.getFontHeight();
+ const int lineH = isMacTalkie() ? 16 : _font.getFontHeight();
const uint originalCapacity = getBalloonLineCapacity(originalId, lineH);
if (originalCapacity == 0)
return bubNum;
@@ -821,7 +824,7 @@ uint16 EEMEngine::fitBalloonToText(uint16 bubNum,
Common::Array<Common::String> lines;
uint16 insetX, insetY, wrapWidth;
getBalloonInsets(originalId, insetX, insetY, wrapWidth);
- const int wrapW = wrapWidth - (isMacCD() ? 5 : 0);
+ const int wrapW = wrapWidth - (isMacTalkie() ? 5 : 0);
_font.wordWrapText(text, MAX<int>(8, wrapW), lines);
if (lines.empty())
return bubNum;
@@ -872,8 +875,8 @@ bool EEMEngine::getBalloonInsets(uint16 bubNum, uint16 &xInset,
const uint idx = bubNum & 0x7F;
if (idx >= ARRAYSIZE(kBalloonInsetTable))
return false;
- if (isMacCD()) {
- // CODE 2:1f74 truncates the fixed-point products.
+ if (isMacTalkie()) {
+ // Mac CD truncates the fixed-point products.
xInset = kBalloonInsetTable[idx].x * kMacScreenWidth / kScreenWidth;
yInset = kBalloonInsetTable[idx].y * kMacScreenHeight / kScreenHeight;
textW = kBalloonInsetTable[idx].w * kMacScreenWidth / kScreenWidth;
diff --git a/engines/eem/map_ui.cpp b/engines/eem/map_ui.cpp
index 3a9c9a71a51..dbf48790555 100644
--- a/engines/eem/map_ui.cpp
+++ b/engines/eem/map_ui.cpp
@@ -121,38 +121,6 @@ void blitBigMapMarker(Graphics::ManagedSurface &dstSurface, const Picture &marke
}
}
-void blitMacBigMapPartnerFrame(Graphics::ManagedSurface &dstSurface,
- const Picture &frame, int anchorX,
- int anchorY) {
- const byte transp = (byte)(frame.flags >> 8);
- const int x = anchorX - (int)(int16)frame.miscflags;
- const int y = anchorY - (int)(int16)frame.rowoff;
- for (int row = 0; row < frame.surface.h; row++) {
- const int dstY = y + row;
- if (dstY < 0 || dstY >= dstSurface.h)
- continue;
- const byte *src = (const byte *)frame.surface.getBasePtr(0, row);
- byte *dst = (byte *)dstSurface.getBasePtr(0, dstY);
- for (int col = 0; col < frame.surface.w; col++) {
- const int dstX = x + col;
- if (dstX < 0 || dstX >= dstSurface.w)
- continue;
- const byte color = src[col];
- if (color != transp) {
- // The map partner frames are authored against the overview
- // ColorTable: 0 is white and 0xff is black. The detail-map
- // ColorTable swaps those endpoints.
- if (color == 0x00)
- dst[dstX] = 0xff;
- else if (color == 0xff)
- dst[dstX] = 0x00;
- else
- dst[dstX] = color;
- }
- }
- }
-}
-
struct BigMapEntryInfo {
uint16 overviewX = 0;
uint16 overviewY = 0;
@@ -897,15 +865,17 @@ bool EEMEngine::doLondonApproach(uint16 approachId) {
byte palette[768] = {};
const bool haveVideo =
decodeLondonApproachFirstFrame(data.videoId, base, palette, mac);
+ bool havePalette = haveVideo;
if (!haveVideo)
base.clear();
if (mac) {
+ havePalette = getSitePalette(0x45 + data.videoId, palette) || havePalette;
Picture background;
const uint16 backgroundPic =
kMacLondonApproachBackgroundBasePic + data.videoId;
if (_picsArchive.getPicture(backgroundPic, background) &&
!background.surface.empty()) {
- if (haveVideo) {
+ if (havePalette) {
const byte black =
closestPaletteIndex(palette, 0x00, 0x00, 0x00, 0xfe);
remapSurfaceColor(background.surface, 0xff, black);
@@ -954,7 +924,7 @@ bool EEMEngine::doLondonApproach(uint16 approachId) {
return -1;
};
const byte approachTextColor =
- closestPaletteIndex(haveVideo ? palette : nullptr, 0, 0, 0,
+ closestPaletteIndex(havePalette ? palette : nullptr, 0, 0, 0,
mac ? (byte)0xfe : (byte)1);
auto drawApproachOverlay = [&](Graphics::ManagedSurface &scratch,
@@ -1112,16 +1082,16 @@ bool EEMEngine::doLondonApproach(uint16 approachId) {
fadeCurrentPaletteToBlack();
CursorMan.showMouse(true);
setSiteHotspotCursorId(6);
- if (_music && _voiceOn)
+ if (_music && _musicOn)
_music->playMus(0x27, /* loop= */ true);
uint page = 0;
drawScreen(page);
- if (haveVideo)
+ if (havePalette)
fadePaletteFromBlack(palette);
else
setSitePalette(0x3b);
- if (haveVideo) {
+ if (haveVideo && !mac) {
playVideo(page);
drawScreen(page);
}
@@ -1384,8 +1354,8 @@ void EEMEngine::drawBigMapDetail(int scrollX, int scrollY,
const int anchorX = mac ? scaleX(0x101) : 0x101;
const int anchorY = mac ? scaleY(0x50) : 0x50;
if (mac)
- blitMacBigMapPartnerFrame(scratch, detailAnim[frameIdx],
- anchorX, anchorY);
+ blitMacAnimFrameAnchored(scratch.surfacePtr(), detailAnim[frameIdx],
+ anchorX, anchorY);
else
blitAnimFrameAnchored(scratch.surfacePtr(),
detailAnim[frameIdx],
diff --git a/engines/eem/module.mk b/engines/eem/module.mk
index 0ea400f8c61..04d47310120 100644
--- a/engines/eem/module.mk
+++ b/engines/eem/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS = \
font.o \
graphics.o \
installer.o \
+ mac_ui.o \
map_ui.o \
metaengine.o \
music.o \
diff --git a/engines/eem/site.cpp b/engines/eem/site.cpp
index 93550c31ceb..592dd8eee03 100644
--- a/engines/eem/site.cpp
+++ b/engines/eem/site.cpp
@@ -761,11 +761,7 @@ const uint32 kImpatienceDelayMs = 60 * 1000;
// London variant is active; any seqnum not listed falls through to the shared
// EEM1 scripts below. Only the seqnums that actually differ are listed.
//
-// NOTE: EEM2 scripts 0x27/0x2e/0x30 end with a `0x81 N` jump (loop back to
-// entry N) rather than a 0x80 restart. `frameFromScriptAtTick` has no jump
-// support (EEM1 never used it), so the flat frame list is stored: correct for a
-// one-shot play-through, but a looped play replays the intro instead of just
-// the post-jump tail. Acceptable for these site NPC fidgets; revisit if needed.
+// DOS London scripts 0x27/0x2e/0x30 still use flat loops here.
const uint8 kScript06London[] = {
0,1,2,3,4,5,6,7,8,9,10,11,11,11,5,6,7,8,9,10,
11,11,11,5,6,7,8,9,10,11,11,11,5,4,3,2,1,0,
@@ -859,19 +855,361 @@ const AnimScriptLong kAnimScriptsLondonLong[] = {
// Select the scripts and timing of the original release.
bool g_londonAnimScripts = false;
-bool g_macCDAnimScripts = false;
+bool g_macAnimScripts = false;
-void setAnimScripts(bool london, bool macCD) {
+void setAnimScripts(bool london, bool macTalkie) {
g_londonAnimScripts = london;
- g_macCDAnimScripts = macCD;
+ g_macAnimScripts = macTalkie;
}
struct AnimScriptRef {
const uint8 *frames;
uint16 len;
+ uint16 loopStart;
+
+ constexpr AnimScriptRef(const uint8 *data = nullptr, uint16 count = 0, uint16 start = 0)
+ : frames(data), len(count), loopStart(start) {}
+};
+
+// Mac London animation sequences, including their loop destinations.
+const uint8 kMacLondonScript19[] = {
+ 0, 0, 0, 0
+};
+
+const uint8 kMacLondonScript44[] = {
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 1, 2, 3, 4, 5, 6, 7,
+ 8
+};
+
+const uint8 kMacLondonScript45[] = {
+ 0, 0, 0, 0, 0, 1, 2, 3
+};
+
+const uint8 kMacLondonScript46[] = {
+ 33, 33, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32
+};
+
+const uint8 kMacLondonScript47[] = {
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 19
+};
+
+const uint8 kMacLondonScript48[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 0, 0, 0, 0, 0
+};
+
+const uint8 kMacLondonScript49[] = {
+ 33, 33, 33, 33, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 31, 30, 29,
+ 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9,
+ 8, 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+const uint8 kMacLondonScript4a[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 30, 29, 28, 27, 26, 25, 24, 23,
+ 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3,
+ 2, 1, 0
+};
+
+const uint8 kMacLondonScript4b[] = {
+ 20, 20, 20, 20, 20, 20, 20, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 19
+};
+
+const uint8 kMacLondonScript4c[] = {
+ 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const uint8 kMacLondonScript4d[] = {
+ 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 0, 0, 0
};
+
+const uint8 kMacLondonScript4e[] = {
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 2
+};
+
+const uint8 kMacLondonScript51[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
+};
+
+const uint8 kMacLondonScript53[] = {
+ 24, 24, 24, 25, 26, 27, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
+};
+
+const uint8 kMacLondonScript54[] = {
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 0, 1, 2
+};
+
+const uint8 kMacLondonScript56[] = {
+ 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 20, 20, 20, 20
+};
+
+const uint8 kMacLondonScript57[] = {
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29
+};
+
+const uint8 kMacLondonScript58[] = {
+ 33, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 33
+};
+
+const uint8 kMacLondonScript59[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 25, 25, 25, 25, 25, 24, 23, 22, 21, 21, 22, 23, 24, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25
+};
+
+const uint8 kMacLondonScript5a[] = {
+ 3, 3, 3, 3, 3, 0, 1, 2, 2, 2, 1, 0, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 1, 0
+};
+
+const uint8 kMacLondonScript5b[] = {
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 2, 1, 0
+};
+
+const uint8 kMacLondonScript5d[] = {
+ 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0
+};
+
+const uint8 kMacLondonScript5e[] = {
+ 0, 0, 0, 0, 1, 2, 3, 4, 0
+};
+
+const uint8 kMacLondonScript5f[] = {
+ 6, 6, 6, 6, 6, 6, 6, 0, 1, 2, 0, 6, 3, 4, 5
+};
+
+const uint8 kMacLondonScript64[] = {
+ 12, 12, 12, 12, 12, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6,
+ 6, 6, 6, 5, 5, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11
+};
+
+const uint8 kMacLondonScript65[] = {
+ 7, 7, 7, 7, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
+ 7, 7, 7, 7
+};
+
+const uint8 kMacLondonScript66[] = {
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
+};
+
+const uint8 kMacLondonScript67[] = {
+ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5,
+ 4, 4, 5, 5
+};
+
+const uint8 kMacLondonScript68[] = {
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 1, 0, 1, 0, 1, 0, 1, 2, 1
+};
+
+const uint8 kMacLondonScript6a[] = {
+ 15, 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 15, 15, 15
+};
+
+const uint8 kMacLondonScript6c[] = {
+ 0, 1, 2, 3, 4, 5, 5, 5, 5, 3, 2, 1, 0, 0, 0, 0, 0, 0
+};
+
+const uint8 kMacLondonScript6d[] = {
+ 0, 0, 1, 2, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0
+};
+
+const uint8 kMacLondonScript6e[] = {
+ 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
+};
+
+const uint8 kMacLondonScript70[] = {
+ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1
+};
+
+const uint8 kMacLondonScript71[] = {
+ 0, 1, 2, 3, 4, 5, 6
+};
+
+const uint8 kMacLondonScript74[] = {
+ 0, 1, 1, 0, 1, 0, 2, 3, 4, 5, 6, 0
+};
+
+const uint8 kMacLondonScript75[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
+};
+
+const uint8 kMacLondonScript76[] = {
+ 3, 3, 3, 4, 0, 1, 2, 3, 3, 3, 4, 0, 1, 2, 3, 3, 3, 3
+};
+
+const uint8 kMacLondonScript77[] = {
+ 16, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16
+};
+
+const uint8 kMacLondonScript78[] = {
+ 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1
+};
+
+const uint8 kMacLondonScript79[] = {
+ 28, 28, 29, 29, 30, 30, 31, 31, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5,
+ 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15,
+ 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25,
+ 26, 26, 27, 27
+};
+
+const uint8 kMacLondonScript7a[] = {
+ 14, 0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 14, 14, 14
+};
+
+const uint8 kMacLondonScript7c[] = {
+ 6, 6, 0, 1, 2, 3, 4, 5, 6, 6, 6
+};
+
+const AnimScriptRef kMacLondonAnimScripts[] = {
+ { kAnimScripts[0].frames, 10, 0 }, // 00
+ { kAnimScripts[24].frames, 6, 0 }, // 01
+ { kAnimScripts[2].frames, 26, 0 }, // 02
+ { kAnimScriptsLondon[1].frames, 15, 0 }, // 03
+ { kAnimScriptsLondon[2].frames, 23, 0 }, // 04
+ { kAnimScriptsLondon[3].frames, 11, 0 }, // 05
+ { kScript06London, 38, 0 }, // 06
+ { kAnimScripts[7].frames, 10, 0 }, // 07
+ { kAnimScripts[8].frames, 8, 0 }, // 08
+ { kAnimScripts[9].frames, 9, 0 }, // 09
+ { kAnimScripts[0].frames, 10, 0 }, // 0a
+ { kAnimScripts[24].frames, 6, 0 }, // 0b
+ { kAnimScriptsLondon[1].frames, 15, 0 }, // 0c
+ { kAnimScriptsLondon[2].frames, 23, 0 }, // 0d
+ { kAnimScriptsLondon[7].frames, 22, 0 }, // 0e
+ { kAnimScripts[9].frames, 9, 0 }, // 0f
+ { kAnimScripts[2].frames, 26, 0 }, // 10
+ { kAnimScripts[17].frames, 8, 0 }, // 11
+ { kAnimScripts[18].frames, 9, 0 }, // 12
+ { kAnimScripts[17].frames, 8, 0 }, // 13
+ { kAnimScripts[36].frames, 11, 0 }, // 14
+ { kAnimScripts[0].frames, 10, 0 }, // 15
+ { kAnimScripts[0].frames, 10, 0 }, // 16
+ { kScript17, 30, 0 }, // 17
+ { kAnimScriptsLondon[9].frames, 17, 0 }, // 18
+ { kMacLondonScript19, 4, 0 }, // 19
+ { kScript06London, 38, 0 }, // 1a
+ { kAnimScriptsLondon[3].frames, 11, 0 }, // 1b
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 1c
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 1d
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 1e
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 1f
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 20
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 21
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 22
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 23
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 24
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 25
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 26
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 27
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 28
+ { kMacLondonScript19, 4, 0 }, // 29
+ { kAnimScripts[34].frames, 4, 0 }, // 2a
+ { kAnimScriptsLondon[12].frames, 12, 0 }, // 2b
+ { kAnimScripts[29].frames, 12, 11 }, // 2c
+ { kScript1dLondon, 46, 0 }, // 2d
+ { kScript1eLondon, 33, 0 }, // 2e
+ { kScript1fLondon, 38, 0 }, // 2f
+ { kAnimScriptsLondon[14].frames, 19, 0 }, // 30
+ { kAnimScriptsLondon[10].frames, 2, 0 }, // 31
+ { kAnimScriptsLondon[16].frames, 10, 0 }, // 32
+ { kMacLondonScript19, 4, 0 }, // 33
+ { kAnimScriptsLondon[17].frames, 18, 0 }, // 34
+ { kScript25London, 59, 0 }, // 35
+ { kAnimScriptsLondon[18].frames, 20, 0 }, // 36
+ { kScript27London, 29, 22 }, // 37
+ { kMacLondonScript19, 4, 0 }, // 38
+ { kAnimScriptsLondon[20].frames, 14, 0 }, // 39
+ { kAnimScripts[34].frames, 4, 0 }, // 3a
+ { kScript2bLondon, 39, 0 }, // 3b
+ { kAnimScriptsLondon[22].frames, 22, 0 }, // 3c
+ { kAnimScripts[29].frames, 12, 11 }, // 3d
+ { kAnimScripts[24].frames, 6, 0 }, // 3e
+ { kAnimScriptsLondon[25].frames, 26, 25 }, // 3f
+ { kScript31London, 62, 0 }, // 40
+ { kAnimScriptsLondon[26].frames, 27, 0 }, // 41
+ { kAnimScriptsLondon[27].frames, 27, 0 }, // 42
+ { kAnimScripts[34].frames, 4, 0 }, // 43
+ { kMacLondonScript44, 21, 0 }, // 44
+ { kMacLondonScript45, 8, 0 }, // 45
+ { kMacLondonScript46, 36, 35 }, // 46
+ { kMacLondonScript47, 45, 44 }, // 47
+ { kMacLondonScript48, 25, 0 }, // 48
+ { kMacLondonScript49, 69, 0 }, // 49
+ { kMacLondonScript4a, 63, 0 }, // 4a
+ { kMacLondonScript4b, 29, 28 }, // 4b: hold the last frame; original jumps past it.
+ { kMacLondonScript4c, 35, 0 }, // 4c
+ { kMacLondonScript4d, 26, 24 }, // 4d
+ { kMacLondonScript4e, 28, 0 }, // 4e
+ { kAnimScriptsLondon[1].frames, 15, 0 }, // 4f
+ { kAnimScripts[33].frames, 5, 0 }, // 50
+ { kMacLondonScript51, 20, 0 }, // 51
+ { kAnimScripts[36].frames, 11, 0 }, // 52
+ { kMacLondonScript53, 30, 0 }, // 53
+ { kMacLondonScript54, 28, 0 }, // 54
+ { kAnimScripts[17].frames, 8, 0 }, // 55
+ { kMacLondonScript56, 33, 29 }, // 56
+ { kMacLondonScript57, 42, 0 }, // 57
+ { kMacLondonScript58, 36, 35 }, // 58
+ { kMacLondonScript59, 49, 10 }, // 59
+ { kMacLondonScript5a, 34, 0 }, // 5a
+ { kMacLondonScript5b, 19, 0 }, // 5b
+ { kMacLondonScript19, 4, 0 }, // 5c
+ { kMacLondonScript5d, 12, 0 }, // 5d
+ { kMacLondonScript5e, 9, 0 }, // 5e
+ { kMacLondonScript5f, 15, 0 }, // 5f
+ { kMacLondonScript51, 20, 0 }, // 60
+ { kMacLondonScript51, 20, 0 }, // 61
+ { kMacLondonScript51, 20, 0 }, // 62
+ { kMacLondonScript51, 20, 0 }, // 63
+ { kMacLondonScript64, 35, 0 }, // 64
+ { kMacLondonScript65, 24, 0 }, // 65
+ { kMacLondonScript66, 36, 0 }, // 66
+ { kMacLondonScript67, 24, 0 }, // 67
+ { kMacLondonScript68, 20, 0 }, // 68
+ { kAnimScripts[17].frames, 8, 0 }, // 69
+ { kMacLondonScript6a, 25, 0 }, // 6a
+ { kMacLondonScript19, 4, 0 }, // 6b
+ { kMacLondonScript6c, 18, 0 }, // 6c
+ { kMacLondonScript6d, 19, 0 }, // 6d
+ { kMacLondonScript6e, 20, 0 }, // 6e
+ { kAnimScripts[31].frames, 13, 0 }, // 6f
+ { kMacLondonScript70, 15, 0 }, // 70
+ { kMacLondonScript71, 7, 0 }, // 71
+ { kAnimScripts[24].frames, 6, 0 }, // 72
+ { kAnimScripts[33].frames, 5, 0 }, // 73
+ { kMacLondonScript74, 12, 0 }, // 74
+ { kMacLondonScript75, 14, 0 }, // 75
+ { kMacLondonScript76, 18, 0 }, // 76
+ { kMacLondonScript77, 20, 0 }, // 77
+ { kMacLondonScript78, 20, 0 }, // 78
+ { kMacLondonScript79, 64, 0 }, // 79
+ { kMacLondonScript7a, 23, 0 }, // 7a
+ { kAnimScriptsLondon[12].frames, 12, 0 }, // 7b
+ { kMacLondonScript7c, 11, 0 }, // 7c
+ { kAnimScripts[17].frames, 8, 0 }, // 7d
+};
+
AnimScriptRef findAnimScript(uint16 seqnum) {
- if (g_macCDAnimScripts) {
+ if (g_macAnimScripts && g_londonAnimScripts && seqnum < ARRAYSIZE(kMacLondonAnimScripts))
+ return kMacLondonAnimScripts[seqnum];
+ if (g_macAnimScripts && !g_londonAnimScripts) {
for (uint i = 0; i < ARRAYSIZE(kAnimScriptsMacCD); i++) {
if (kAnimScriptsMacCD[i].seqnum == seqnum) {
AnimScriptRef r;
@@ -922,24 +1260,24 @@ AnimScriptRef findAnimScript(uint16 seqnum) {
}
uint animationFramePeriodMs() {
- // Mac CD CODE 2:21c4 advances after nine 60 Hz ticks.
- return g_macCDAnimScripts ? 150 : 140;
+ // Mac CD CheckFrameRate advances after nine 60 Hz ticks.
+ return g_macAnimScripts ? 150 : 140;
}
uint frameFromScriptAtTick(const uint8 *frames, uint len,
- uint numFrames, uint32 tickMs) {
+ uint numFrames, uint32 tickMs, uint loopStart = 0) {
if (!frames || len == 0)
return numFrames > 0 ? (uint)((tickMs / animationFramePeriodMs()) % numFrames) : 0;
- const uint scriptIdx = (uint)((tickMs / animationFramePeriodMs()) % len);
+ const uint tick = tickMs / animationFramePeriodMs();
+ const uint scriptIdx = tick < len ? tick : loopStart + (tick - len) % (len - loopStart);
const uint frame = frames[scriptIdx];
return (numFrames > 0) ? MIN<uint>(frame, numFrames - 1) : 0;
}
-// Looping path of `_UpdateAnimations`: walk the script one entry per
-// `_CheckFrameRate` tick, wrap on 0x80.
+// Advance one entry per frame tick, then follow the loop destination.
uint partnerFrameAtTick(uint16 seqnum, uint numFrames, uint32 tickMs) {
const AnimScriptRef s = findAnimScript(seqnum);
- return frameFromScriptAtTick(s.frames, s.len, numFrames, tickMs);
+ return frameFromScriptAtTick(s.frames, s.len, numFrames, tickMs, s.loopStart);
}
uint oneShotFrameAtTick(uint16 seqnum, uint numFrames, uint32 tickMs) {
@@ -1032,6 +1370,8 @@ bool SiteScreen::playLondonTravelAnimation(uint fromSite, uint toSite) {
travelKind, fromPic, toPic);
return false;
}
+ if (_vm->isMacintosh())
+ return _vm->playMacLondonTravelAnimation(travelKind);
const uint partnerSuffix = (travelKind == 3) ? 0 : _vm->getPartnerIndex();
const Common::String name = Common::String::format("TRAVEL%u%u.ANM",
@@ -1077,9 +1417,10 @@ void SiteScreen::enter(uint siteNum, bool resetPartnerMood) {
const uint16 approachId = (london && sd) ? READ_LE_UINT16(sd + 2) : 0xffff;
if (london) {
- if (playArrival)
+ const bool playApproach = firstVisit && approachId != 0xffff;
+ if (playArrival && !(_vm->isMacintosh() && playApproach))
playLondonTravelAnimation(_mystery->_lastSite, siteNum);
- if (firstVisit && approachId != 0xffff) {
+ if (playApproach) {
debugC(1, kDebugSite,
"London approach: site %u first visit, approach %u",
siteNum, approachId);
@@ -1656,7 +1997,7 @@ void SiteScreen::renderStaticDrops(uint siteNum) {
Picture pic;
if (!_vm->getPics().getPicture(picId, pic))
continue;
- if (_vm->isMacCD())
+ if (_vm->isMacTalkie())
blitMacMaskedSurface(screen, pic, x, y);
else
blitMaskedSurface(screen, pic, x, y);
@@ -1708,7 +2049,7 @@ void SiteScreen::renderAnimatedDrops(uint siteNum, uint32 tickMs) {
if (!_mystery || !_vm)
return;
- if (_vm->isMacintosh() && !_vm->isMacCD())
+ if (_vm->isMacintosh() && !_vm->isMacTalkie())
return;
if (_vm->isFloppy()) {
@@ -1766,10 +2107,10 @@ void SiteScreen::renderAnimatedDrops(uint siteNum, uint32 tickMs) {
Animation anim;
if (!_vm->getAni().loadAnimation((uint)animId, anim) || anim.empty())
continue;
- const uint32 elapsed = _vm->isMacCD() ? tickMs - _waitPhaseAnchor : tickMs;
+ const uint32 elapsed = _vm->isMacTalkie() ? tickMs - _waitPhaseAnchor : tickMs;
const uint frameIdx = partnerFrameAtTick((uint16)animId,
(uint)anim.size(), elapsed);
- if (_vm->isMacCD())
+ if (_vm->isMacTalkie())
blitMacAnimFrameAnchored(screen, anim[frameIdx], x, y);
else
blitAnimFrameAnchored(screen, anim[frameIdx], x, y);
@@ -2369,8 +2710,8 @@ bool EEMEngine::loadKdAnim(uint16 num, Animation &anim, int &px, int &py,
}
const uint partner = (_partner == kPartnerJake) ? 0 : 1;
animId = kdTable[num][partner];
- px = (int)kdTable[num][2 + partner];
- py = (int)kdTable[num][4 + partner];
+ px = (int16)kdTable[num][2 + partner];
+ py = (int16)kdTable[num][4 + partner];
if (!_aniArchive.loadAnimation(animId, anim) || anim.empty()) {
warning("loadKdAnim(%u): anim %u failed to load", num, animId);
diff --git a/engines/eem/site.h b/engines/eem/site.h
index 3b7b214f770..544e1a0e734 100644
--- a/engines/eem/site.h
+++ b/engines/eem/site.h
@@ -48,7 +48,7 @@ uint oneShotFrameAtTick(uint16 seqnum, uint numFrames, uint32 tickMs);
/// Total time for one full play of a one-shot gesture (frame count * period).
uint32 oneShotDurationMs(uint16 seqnum, uint numFrames);
-void setAnimScripts(bool london, bool macCD);
+void setAnimScripts(bool london, bool macTalkie);
uint animationFramePeriodMs();
/// bigMapPartnerFrameAtTick: overview-map partner walk. EEM1 (11-frame anim):
diff --git a/engines/eem/ui.cpp b/engines/eem/ui.cpp
index de7851710a6..94c5cba287a 100644
--- a/engines/eem/ui.cpp
+++ b/engines/eem/ui.cpp
@@ -152,17 +152,19 @@ int scalePdaAnchor(int value, int target, int source) {
void blitPdaPartner(Graphics::ManagedSurface &dst, DBDArchive &aniArchive,
uint8 partner, const PdaPartnerSpec &spec,
- uint32 tickMs, bool mac = false, bool macCD = false) {
+ uint32 tickMs, bool mac = false, bool macCD = false, bool london = false) {
+ const bool native = macCD || (mac && london);
const PdaPartnerSpec nativeSpec { 0x02, 0x02, 0x10,
- (spec.scriptId == 0x02 && partner == kPartnerJenny) ? 4 : 7, 152 };
- const PdaPartnerSpec &activeSpec = macCD ? nativeSpec : spec;
+ (!london && spec.scriptId == 0x02 && partner == kPartnerJenny) ? 4 : 7,
+ (london && partner == kPartnerJake) ? 150 : 152 };
+ const PdaPartnerSpec &activeSpec = native ? nativeSpec : spec;
Animation ani;
if (const Picture *fr = partnerFrameFor(aniArchive, partner, activeSpec,
tickMs, ani)) {
if (mac) {
- const int anchorX = macCD ? activeSpec.anchorX :
+ const int anchorX = native ? activeSpec.anchorX :
scalePdaAnchor(spec.anchorX, kMacScreenWidth, kScreenWidth);
- const int anchorY = macCD ? activeSpec.anchorY :
+ const int anchorY = native ? activeSpec.anchorY :
scalePdaAnchor(spec.anchorY, kMacScreenHeight, kScreenHeight);
blitMacAnimFrameAnchored(dst.surfacePtr(), *fr, anchorX,
anchorY);
@@ -300,7 +302,7 @@ constexpr int kMacTravisTextInsetX = 5;
constexpr int kMacTravisTextInsetY = 4;
bool usesTravisScrollBar(const EEMEngine *vm) {
- return vm && (vm->isMacCD() || (vm->isMacintosh() && vm->isLondon()));
+ return vm && vm->isMacTalkie();
}
class TravisScrollBar {
@@ -1757,7 +1759,7 @@ int EEMEngine::doShowEnding(uint num, bool firstPage) {
CursorMan.showMouse(true);
const bool floppyEnding = isFloppy();
- const bool macCDEnding = isMacCD() && macLooseEnding;
+ const bool macCDEnding = isMacTalkie() && macLooseEnding;
const int sw = screenWidth();
const int sh = screenHeight();
const Common::Rect endingPrevRect = macCDEnding ? Common::Rect(0, 20, 43, 384) :
@@ -1826,7 +1828,7 @@ int EEMEngine::doShowEnding(uint num, bool firstPage) {
return 0;
const bool showFirstTryBadge =
- num < sizeof(_mysteriesSolved) && _mysteriesSolved[num] == 2 &&
+ !isLondon() && num < sizeof(_mysteriesSolved) && _mysteriesSolved[num] == 2 &&
(floppyEnding || ConfMan.getBool("restored_content"));
Picture firstTryBadge;
const bool haveFirstTryBadge =
@@ -1908,13 +1910,13 @@ int EEMEngine::doShowEnding(uint num, bool firstPage) {
x2 = textRect.right;
Picture bg;
- if (macCDEnding) {
+ if (isMacCD() && macCDEnding) {
if (_picsArchive.getPicture(kFloppyEndingBackgroundPic, bg))
blitTravisBackground(scratch, bg, true);
if (_picsArchive.getPicture(picNum, bg))
blitMacMaskedSurface(scratch.surfacePtr(), bg, 92, 34);
} else if (_picsArchive.getPicture(picNum, bg)) {
- scratch.simpleBlitFrom(bg.surface);
+ blitTravisBackground(scratch, bg, macEnding);
}
raw = (const char *)buf.data() + off + 10;
}
@@ -2045,7 +2047,7 @@ void EEMEngine::doShowScrapbook(uint stage) {
return;
const bool currentTier = (stage == _chainStage);
- if (isLondon() && _music && _voiceOn)
+ if (isLondon() && _music && _musicOn)
_music->playMus(0x5d, /* loop= */ true);
int mystery = lo;
@@ -2829,7 +2831,7 @@ void EEMEngine::doCaseSelection() {
return;
}
- if (isLondon() && _music && _voiceOn)
+ if (isLondon() && _music && _musicOn)
_music->playMus(2, /* loop= */ true);
const uint listLen = MIN<uint>((uint)names.size(), stageHi - stageLo + 1);
@@ -3079,7 +3081,7 @@ void EEMEngine::doNotebook() {
Common::Point mouse = g_system->getEventManager()->getMousePos();
setInteractiveMouseCursor(notebookButtonAt(this, mouse.x, mouse.y));
- if (isLondon() && _music && _voiceOn) {
+ if (isLondon() && _music && _musicOn) {
while (notebookFromSite && _music->isPlaying() && !shouldQuit()) {
Common::Event drain;
while (g_system->getEventManager()->pollEvent(drain)) {}
@@ -3290,7 +3292,7 @@ void EEMEngine::drawNotebookFrame(int &page, TravisScrollBar *scrollBar) {
blitTravisBackground(scratch, frame, isMacintosh());
blitPdaPartner(scratch, _aniArchive, _partner, kPdaNotebookPartner,
- g_system->getMillis(), isMacintosh(), isMacCD());
+ g_system->getMillis(), isMacintosh(), isMacCD(), isLondon());
// `_DrawNotes` walks `_NoteIndex` for current page; word-wraps each
// found clue in `_NotebookRect`. Selected = color 0x3c.
@@ -3413,7 +3415,7 @@ void EEMEngine::doGallery() {
Picture galBg;
const bool haveBg = _picsArchive.getPicture(0x3f, galBg);
- if (isLondon() && _music && _voiceOn)
+ if (isLondon() && _music && _musicOn)
_music->playMus(5, /* loop= */ true);
const uint8 num = _mystery.numSuspects();
@@ -3645,7 +3647,7 @@ bool EEMEngine::moreInfo(const byte *gd, uint suspectIdx,
blitTravisBackground(ms, galBg, mac);
blitPdaPartner(ms, _aniArchive, _partner, kPdaGalleryPartner,
- g_system->getMillis(), mac, isMacCD());
+ g_system->getMillis(), mac, isMacCD(), isLondon());
Picture detail;
if (_picsArchive.getPicture(detailPic, detail)) {
const Common::Point detailPos =
@@ -3919,7 +3921,7 @@ void EEMEngine::drawGalleryFrame(const byte *gd, uint8 numSuspects,
blitTravisBackground(scratch, galBg, mac);
blitPdaPartner(scratch, _aniArchive, _partner, kPdaGalleryPartner,
- g_system->getMillis(), mac, isMacCD());
+ g_system->getMillis(), mac, isMacCD(), isLondon());
const bool floppy = isFloppy();
const bool compactGallery = floppy || _mystery.usesCompactMacData();
@@ -3948,7 +3950,7 @@ void EEMEngine::drawGalleryFrame(const byte *gd, uint8 numSuspects,
continue;
const int placeX = s.x;
- const int placeY = isMacCD() ? s.y + 138 - portrait.surface.h :
+ const int placeY = isMacTalkie() ? s.y + 138 - portrait.surface.h :
(mac ? s.y : s.y + (0x48 - portrait.surface.h));
const int w = MIN<int>(portrait.surface.w, sw - placeX);
const int h = MIN<int>(portrait.surface.h, sh - placeY);
@@ -3964,7 +3966,7 @@ void EEMEngine::drawGalleryFrame(const byte *gd, uint8 numSuspects,
slotRects[i] = Common::Rect(placeX, placeY,
placeX + w, placeY + h);
slotSuspect[i] = (int)i;
- } else if (!isMacCD()) {
+ } else if (!isMacTalkie()) {
// Undiscovered placeholder â small framed "?" box.
const int phW = mac ? 0x72 : 0x40;
const int phH = mac ? 0x90 : 0x48;
@@ -4072,7 +4074,7 @@ void EEMEngine::accuseDrawScreen(const AccuseNotesCtx &ctx) {
blitPdaPartner(scratch, _aniArchive, _partner,
isMacCD() ? kPdaNotebookPartner : kPdaGalleryPartner,
- g_system->getMillis(), mac, isMacCD());
+ g_system->getMillis(), mac, isMacCD(), isLondon());
Common::Array<Common::Rect> &slotRects = *ctx.slotRects;
Common::Array<uint> &slotClues = *ctx.slotClues;
@@ -4127,7 +4129,7 @@ void EEMEngine::accuseDrawScreen(const AccuseNotesCtx &ctx) {
: (remaining == 1 ? "clue" : "clues");
const Common::String counter =
Common::String::format("%u %s", remaining, clueWord);
- if (isMacCD()) {
+ if (isMacTalkie()) {
_font.drawString(&scratch, Common::String::format("%u", remaining), 334, 23, 16, 0x23);
_font.drawString(&scratch, clueWord, 350, 23, 120, 0x0f);
} else {
@@ -4376,7 +4378,7 @@ bool EEMEngine::doAccuseNotes() {
break;
_mystery._noteSelected[clueId] =
_mystery._noteSelected[clueId] ? 0 : 1;
- if (isMacCD() && _mystery._noteSelected[clueId] && selected + 1 == expected) {
+ if (isMacTalkie() && _mystery._noteSelected[clueId] && selected + 1 == expected) {
accuseDrawScreen(ctx);
return true;
}
@@ -4428,10 +4430,10 @@ void EEMEngine::drawKDBalloonOverCurrentScreen(Common::String text) {
_balloonArchive.size() > (bubNum & 0x7F) &&
_balloonArchive.loadEntry(bubNum & 0x7F, balloon);
- const int balloonX = isMacCD() ? 100 : scaleX(0x21);
- const int topBandH = isMacCD() ? 155 : scaleY(0x50);
- const int centeredMaxH = isMacCD() ? 155 : scaleY(0x4e);
- int balloonY = isMacCD() ? 1 : scaleY(1);
+ const int balloonX = isMacTalkie() ? 100 : scaleX(0x21);
+ const int topBandH = isMacTalkie() ? 155 : scaleY(0x50);
+ const int centeredMaxH = isMacTalkie() ? 155 : scaleY(0x4e);
+ int balloonY = isMacTalkie() ? 1 : scaleY(1);
if (haveBalloon && balloon.surface.h < centeredMaxH)
balloonY = (topBandH - balloon.surface.h) / 2;
@@ -4457,7 +4459,7 @@ void EEMEngine::drawKDBalloonOverCurrentScreen(Common::String text) {
if (dialogFont.isLoaded()) {
const byte textColor =
mac ? macPaletteMap.black : (haveBalloon ? 0 : 0xF);
- if (isMacCD())
+ if (isMacTalkie())
dialogFont.drawMacWordWrapped(&ms, balloonX + tx, balloonY + ty,
tw, text, textColor);
else
@@ -4545,8 +4547,8 @@ void EEMEngine::doAccuse() {
else
_audio->sayKDDigital(entryKdIdx, entryKDSpeak, _partner);
}
- waitForInput(isMacCD() ? 0xFFFFFFFFu : 60000);
- if (isMacCD())
+ waitForInput(isMacTalkie() ? 0xFFFFFFFFu : 60000);
+ if (isMacTalkie())
interruptAudio();
}
if (shouldQuit())
@@ -4569,7 +4571,7 @@ void EEMEngine::doAccuse() {
const byte *gd = _mystery.galleryData();
- if (isLondon() && _music && _voiceOn)
+ if (isLondon() && _music && _musicOn)
_music->playMus(4, /* loop= */ true);
// `_DoAccuse @ 1df2:0c11` outer loop; ESC â NextScreen=3.
@@ -4623,8 +4625,8 @@ void EEMEngine::doAccuse() {
if (_audio && kdIdx)
_audio->sayKDDigital(kdIdx, 3, _partner);
- waitForInput(isMacCD() ? 0xFFFFFFFFu : 20000);
- if (isMacCD() && _audio)
+ waitForInput(isMacTalkie() ? 0xFFFFFFFFu : 20000);
+ if (isMacTalkie() && _audio)
_audio->stopSpool();
_nextScreen = _lastScreen != kScreenInvalid
? (ScreenId)_lastScreen : kScreenSite;
@@ -4648,7 +4650,7 @@ void EEMEngine::doAccuse() {
Common::String hint =
parseString(raw ? raw : "", _playerName, _partner);
if (!hint.empty()) {
- if (isMacCD()) {
+ if (isMacTalkie()) {
Picture background;
Graphics::ManagedSurface scratch(screenWidth(), screenHeight(),
Graphics::PixelFormat::createFormatCLUT8());
@@ -4656,7 +4658,7 @@ void EEMEngine::doAccuse() {
if (_picsArchive.getPicture(0x1a7, background))
blitTravisBackground(scratch, background, true);
blitPdaPartner(scratch, _aniArchive, _partner, kPdaNotebookPartner,
- g_system->getMillis(), true, true);
+ g_system->getMillis(), true, true, isLondon());
copyToScreen(scratch);
} else {
drawAccuseGallery(num, gd, /* highlighted= */ -1,
@@ -4665,8 +4667,8 @@ void EEMEngine::doAccuse() {
drawKDBalloonOverCurrentScreen(hint);
if (_audio)
_audio->sayKDDigital(kdIdx, 4, _partner);
- waitForInput(isMacCD() ? 0xFFFFFFFFu : 8000);
- if (isMacCD() && _audio)
+ waitForInput(isMacTalkie() ? 0xFFFFFFFFu : 8000);
+ if (isMacTalkie() && _audio)
_audio->stopSpool();
}
}
@@ -4674,7 +4676,7 @@ void EEMEngine::doAccuse() {
if (shouldQuit())
return;
- if (isLondon() && _music && _voiceOn)
+ if (isLondon() && _music && _musicOn)
_music->playMus(33, /* loop= */ true);
drawAccuseGallery(num, gd, highlighted, slotRects, slotSuspect);
@@ -4691,7 +4693,7 @@ void EEMEngine::doAccuse() {
while (picked < 0 && !shouldQuit()) {
Common::Event ev;
while (g_system->getEventManager()->pollEvent(ev)) {
- if (isMacCD()) {
+ if (isMacTalkie()) {
if (ev.type == Common::EVENT_KEYDOWN &&
(ev.kbd.keycode == Common::KEYCODE_LEFT || ev.kbd.keycode == Common::KEYCODE_RIGHT)) {
ev.kbd.flags = ev.kbd.keycode == Common::KEYCODE_LEFT ? Common::KBD_SHIFT : 0;
@@ -4778,10 +4780,10 @@ void EEMEngine::doAccuse() {
// DisplayAlibi: DOS 1df2:0145, Mac CD CODE 7:043e.
if (!guessedRight) {
- const bool macCD = isMacCD();
- const int sw = macCD ? screenWidth() : kScreenWidth;
- const int sh = macCD ? screenHeight() : kScreenHeight;
- const MacSpritePaletteMap palette = macCD ? getMacSpritePaletteMap() :
+ const bool macTalkie = isMacTalkie();
+ const int sw = macTalkie ? screenWidth() : kScreenWidth;
+ const int sh = macTalkie ? screenHeight() : kScreenHeight;
+ const MacSpritePaletteMap palette = macTalkie ? getMacSpritePaletteMap() :
MacSpritePaletteMap{0x00, 0xFF};
static const uint16 kAlibiBubbles[16] = {
0x002B, 0x002C, 0x002D, 0x002E,
@@ -4822,9 +4824,9 @@ void EEMEngine::doAccuse() {
_balloonArchive.size() > (bubNum & 0x7F) &&
_balloonArchive.loadEntry(bubNum & 0x7F, balloon);
- int balloonX = macCD ? 100 : 0x21;
+ int balloonX = macTalkie ? 100 : 0x21;
int balloonY = 1;
- int py = macCD ? 173 : 0x5a;
+ int py = macTalkie ? 173 : 0x5a;
if (bindx < 8) {
const int bw = haveBalloon ? balloon.surface.w : 0;
const int bh = haveBalloon ? balloon.surface.h : 0;
@@ -4833,12 +4835,12 @@ void EEMEngine::doAccuse() {
balloonY = (py - bh) / 2;
} else {
balloonY = 1;
- if (!macCD)
+ if (!macTalkie)
py = bh;
}
} else {
const int bh = haveBalloon ? balloon.surface.h : 0;
- balloonY = macCD ? MAX(1, (155 - bh) / 2) :
+ balloonY = macTalkie ? MAX(1, (155 - bh) / 2) :
((bh < 0x4f) ? (0x50 - bh) / 2 : 1);
}
@@ -4846,9 +4848,9 @@ void EEMEngine::doAccuse() {
Graphics::PixelFormat::createFormatCLUT8());
base.clear();
if (haveAlibiBg)
- blitTravisBackground(base, alibiBg, macCD);
+ blitTravisBackground(base, alibiBg, macTalkie);
if (haveSuspect) {
- if (macCD)
+ if (macTalkie)
blitMacMaskedSurface(base.surfacePtr(), suspect, 208, py);
else
base.transBlitFrom(suspect.surface, Common::Point(0x82, py),
@@ -4859,9 +4861,9 @@ void EEMEngine::doAccuse() {
Graphics::PixelFormat::createFormatCLUT8());
scratch.simpleBlitFrom(base);
if (haveBalloon) {
- if (macCD)
+ if (macTalkie)
blitMacMaskedSurface(scratch.surfacePtr(), balloon, balloonX, balloonY,
- (bubNum & 0x80) != 0, palette);
+ !isLondon() && (bubNum & 0x80) != 0, palette);
else
scratch.transBlitFrom(balloon.surface, Common::Point(balloonX, balloonY),
(uint32)(byte)(balloon.flags >> 8));
@@ -4870,7 +4872,7 @@ void EEMEngine::doAccuse() {
uint16 tx = 5, ty = 4, tw = 155;
getBalloonInsets(bubNum, tx, ty, tw);
if (_font.isLoaded() && !alibi.empty()) {
- if (macCD)
+ if (macTalkie)
_font.drawMacWordWrapped(&scratch, balloonX + tx, balloonY + ty,
tw, alibi, palette.black);
else
@@ -4879,10 +4881,10 @@ void EEMEngine::doAccuse() {
haveBalloon ? 0 : 0xF);
}
blitPdaPartner(scratch, _aniArchive, _partner,
- macCD ? kPdaNotebookPartner : kPdaGalleryPartner,
- g_system->getMillis(), macCD, macCD);
+ macTalkie ? kPdaNotebookPartner : kPdaGalleryPartner,
+ g_system->getMillis(), macTalkie, macTalkie, isLondon());
- if (!macCD && _music && _voiceOn) {
+ if (!macTalkie && _music && _voiceOn) {
_music->playMus(6, /* loop= */ false);
const uint32 musStart = g_system->getMillis();
bool aborted = false;
@@ -4909,9 +4911,11 @@ void EEMEngine::doAccuse() {
}
copyToScreen(scratch);
- if (_audio && gd && (!isMacintosh() || macCD)) {
+ if (macTalkie && isLondon() && _music && _musicOn)
+ _music->playMus(32, false);
+ if (_audio && gd && (!isMacintosh() || macTalkie)) {
const uint16 alibiVoice =
- READ_LE_UINT16(gd + (uint)picked * 0x46 + (macCD ? 4 : 0));
+ READ_LE_UINT16(gd + (uint)picked * 0x46 + (macTalkie ? 4 : 0));
const uint16 jakeVoice =
READ_LE_UINT16(gd + (uint)picked * 0x46 + 0x06);
const uint16 talk =
@@ -4919,9 +4923,11 @@ void EEMEngine::doAccuse() {
if (talk != 0 && talk != 0xFFFF)
_audio->spoolSound((uint)(talk - 1));
}
- waitForInput(macCD ? 0xFFFFFFFFu : 60000);
- if (macCD && _audio)
+ waitForInput(macTalkie ? 0xFFFFFFFFu : 60000);
+ if (macTalkie && _audio)
_audio->stopSpool();
+ if (macTalkie && isLondon())
+ stopMusic();
if (shouldQuit())
return;
@@ -4944,14 +4950,14 @@ void EEMEngine::doAccuse() {
const bool haveR =
_balloonArchive.size() > (rBub & 0x7F) &&
_balloonArchive.loadEntry(rBub & 0x7F, rBalloon);
- const int rX = macCD ? 100 : 0x21;
+ const int rX = macTalkie ? 100 : 0x21;
int rY = 1;
- if (haveR && rBalloon.surface.h < (macCD ? 155 : 0x4e))
- rY = ((macCD ? 155 : 0x50) - rBalloon.surface.h) / 2;
+ if (haveR && rBalloon.surface.h < (macTalkie ? 155 : 0x4e))
+ rY = ((macTalkie ? 155 : 0x50) - rBalloon.surface.h) / 2;
scratch.simpleBlitFrom(base);
if (haveR) {
- if (macCD)
+ if (macTalkie)
blitMacMaskedSurface(scratch.surfacePtr(), rBalloon, rX, rY);
else
scratch.transBlitFrom(rBalloon.surface, Common::Point(rX, rY),
@@ -4960,7 +4966,7 @@ void EEMEngine::doAccuse() {
uint16 rtx = 5, rty = 4, rtw = 155;
getBalloonInsets(rBub, rtx, rty, rtw);
if (_font.isLoaded()) {
- if (macCD)
+ if (macTalkie)
_font.drawMacWordWrapped(&scratch, rX + rtx, rY + rty,
rtw, react, palette.black);
else
@@ -4969,15 +4975,15 @@ void EEMEngine::doAccuse() {
haveR ? 0 : 0xF);
}
blitPdaPartner(scratch, _aniArchive, _partner,
- macCD ? kPdaNotebookPartner : kPdaGalleryPartner,
- g_system->getMillis(), macCD, macCD);
+ macTalkie ? kPdaNotebookPartner : kPdaGalleryPartner,
+ g_system->getMillis(), macTalkie, macTalkie, isLondon());
copyToScreen(scratch);
if (_audio)
_audio->sayKDDigital(reactIdx, 5, _partner);
}
}
- waitForInput(macCD ? 0xFFFFFFFFu : 60000);
- if (macCD && _audio)
+ waitForInput(macTalkie ? 0xFFFFFFFFu : 60000);
+ if (macTalkie && _audio)
_audio->stopSpool();
_mystery._firstTry = false;
@@ -4990,7 +4996,7 @@ void EEMEngine::doAccuse() {
const uint mn = _mystery.number();
const bool macRestored = isMacCD() && ConfMan.getBool("restored_content") &&
(mn == 0 || _restoredContentDataLoaded);
- if (!isMacCD()) {
+ if (!isMacTalkie()) {
if (mn < sizeof(_mysteriesSolved))
_mysteriesSolved[mn] = _mystery._firstTry ? 2 : 1;
advanceChainStageAfterSolve(mn);
@@ -5011,8 +5017,8 @@ void EEMEngine::doAccuse() {
scratch.simpleBlitFrom(frame.surface);
if (winScene < _sitesArchive.size() &&
_sitesArchive.loadEntry(winScene, scene)) {
- const int sx = isMacCD() ? 106 : scaleX(0x42);
- const int sy = isMacCD() ? 38 : scaleY(0x14);
+ const int sx = isMacTalkie() ? 106 : scaleX(0x42);
+ const int sy = isMacTalkie() ? 38 : scaleY(0x14);
const int sw = MIN<int>(scene.surface.w, screenW - sx);
const int sh = MIN<int>(scene.surface.h, screenH - sy);
if (sw > 0 && sh > 0)
@@ -5020,22 +5026,25 @@ void EEMEngine::doAccuse() {
scene.surface.pitch, sx, sy,
sw, sh);
}
- if (isMacCD()) {
+ if (isMacTalkie()) {
remapMacSurfaceEndpoints(scratch, getMacSpritePaletteMap());
setPartnerEraseBg(&scratch);
- setPartnerIdleAnim(true, _partner == kPartnerJake ? 0x02 : 0x10, 7, 152);
+ setPartnerIdleAnim(true, _partner == kPartnerJake ? 0x02 : 0x10,
+ 7, isLondon() && _partner == kPartnerJake ? 150 : 152);
}
blitPdaPartner(scratch, _aniArchive, _partner,
- isMacCD() ? kPdaNotebookPartner : kPdaGalleryPartner,
- g_system->getMillis(), isMacintosh(), isMacCD());
+ isMacTalkie() ? kPdaNotebookPartner : kPdaGalleryPartner,
+ g_system->getMillis(), isMacintosh(), isMacTalkie(), isLondon());
g_system->copyRectToScreen(scratch.getPixels(), scratch.pitch,
0, 0, screenW, screenH);
g_system->updateScreen();
- if (_music && (isMacCD() ? _musicOn : _voiceOn))
- _music->playMus(5, /* loop= */ false);
- if (isMacCD())
+ if (_music && (isMacTalkie() ? _musicOn : _voiceOn))
+ _music->playMus(isMacintosh() && isLondon() ? 31 : 5, false);
+ if (isMacTalkie())
waitForMusicDone();
+ if (isMacintosh() && isLondon() && _music && _musicOn && !shouldQuit())
+ _music->playMus(33, true);
const byte *solved = _mystery.solvedClueBlock();
if (isMacintosh() && _mystery.usesCompactMacData() && solved) {
@@ -5067,7 +5076,7 @@ void EEMEngine::doAccuse() {
// The practice CD script already includes the three scrapbook lines.
displayClue(solved, macRestored && mn == 0 && count > 3 ? count - 3 : count);
}
- if (isMacCD()) {
+ if (isMacTalkie()) {
setPartnerIdleAnim(false, 0, 0, 0);
setPartnerEraseBg(nullptr);
if (shouldQuit())
@@ -5076,8 +5085,7 @@ void EEMEngine::doAccuse() {
_mysteriesSolved[mn] = _mystery._firstTry ? 2 : 1;
advanceChainStageAfterSolve(mn);
}
- if (_music && _voiceOn)
- _music->stop();
+ stopMusic();
if (!isMacintosh()) {
playAnm(Common::Path(isLondon() ? "SCRAP.ANM" : "SCRAPBK.ANI"),
@@ -5090,10 +5098,17 @@ void EEMEngine::doAccuse() {
displayScrapbookExtra(mn);
fadeCurrentPaletteToBlack();
}
+ } else if (isMacintosh() && isLondon()) {
+ fadeCurrentPaletteToBlack();
+ showStillPicture(0xa1, 0x43, 4000);
+ if (_music && _musicOn && !shouldQuit())
+ _music->playMus(93, true);
}
if (!shouldQuit())
doShowEnding(mn);
+ if (isMacintosh() && isLondon())
+ stopMusic();
_mystery.clear();
const Common::Error err = saveProfile(_playerName);
@@ -5778,7 +5793,7 @@ void EEMEngine::drawAccuseGallery(uint8 numSuspects, const byte *gd,
// Partner drawn first; defensive (no slot overlap).
blitPdaPartner(scratch, _aniArchive, _partner,
isMacCD() ? kPdaNotebookPartner : kPdaGalleryPartner,
- g_system->getMillis(), mac, isMacCD());
+ g_system->getMillis(), mac, isMacCD(), isLondon());
const GallerySlot * const slots = mac ? kMacGallerySlots : kGallerySlots;
for (uint i = 0; i < numSuspects && i < Mystery::kGalleryCap; i++) {
@@ -5806,7 +5821,7 @@ void EEMEngine::drawAccuseGallery(uint8 numSuspects, const byte *gd,
continue;
const int placeX = s.x;
- const int placeY = isMacCD() ? s.y + 138 - portrait.surface.h :
+ const int placeY = isMacTalkie() ? s.y + 138 - portrait.surface.h :
(mac ? s.y : s.y + (0x48 - portrait.surface.h));
const int w = MIN<int>(portrait.surface.w, sw - placeX);
const int h = MIN<int>(portrait.surface.h, sh - placeY);
@@ -5825,7 +5840,7 @@ void EEMEngine::drawAccuseGallery(uint8 numSuspects, const byte *gd,
}
// Highlight outline (original uses `_PutMouseInRect` @ 1df2:0b8e).
- if (!isMacCD() && highlighted >= 0 && highlighted < (int)slotRects.size() &&
+ if (!isMacTalkie() && highlighted >= 0 && highlighted < (int)slotRects.size() &&
!slotRects[highlighted].isEmpty()) {
Common::Rect r = slotRects[highlighted];
r.grow(1);
Commit: 43ef42c76405d5854b0d77bb77d3df5d8ae7286b
https://github.com/scummvm/scummvm/commit/43ef42c76405d5854b0d77bb77d3df5d8ae7286b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-09-11T08:11:32+02:00
Commit Message:
SCUMM: RA1: correctly render special german character in subtitles
Changed paths:
engines/scumm/insane/rebel1/render.cpp
diff --git a/engines/scumm/insane/rebel1/render.cpp b/engines/scumm/insane/rebel1/render.cpp
index d10ba45825e..d5acbc79fc2 100644
--- a/engines/scumm/insane/rebel1/render.cpp
+++ b/engines/scumm/insane/rebel1/render.cpp
@@ -75,6 +75,11 @@ int ra1GameplayWindowOffsetY(const InsaneRebel1 *rebel1) {
}
}
+int getBankGlyphIndex(byte ch) {
+ // Localized RA1 fonts store the DOS sharp-s glyph at 0x7F.
+ return (ch == 0xE1 ? 0x7F : ch) - 0x21;
+}
+
void drawBankString(const RA1SpriteBank &bank, byte *dst, int pitch, int width, int height,
int x, int y, const char *text) {
if (!dst || !text || bank.numSprites <= 0)
@@ -93,7 +98,7 @@ void drawBankString(const RA1SpriteBank &bank, byte *dst, int pitch, int width,
x += 4;
continue;
}
- const int fontIdx = (int)ch - 0x21;
+ const int fontIdx = getBankGlyphIndex(ch);
if (fontIdx < 0 || fontIdx >= bank.numSprites) {
x += 4;
continue;
@@ -144,7 +149,7 @@ const RA1Sprite *lookupBankGlyph(const RA1SpriteBank &bank, char ch) {
if ((byte)ch < 0x21)
return nullptr;
- const int fontIdx = (int)(byte)ch - 0x21;
+ const int fontIdx = getBankGlyphIndex((byte)ch);
if (fontIdx < 0 || fontIdx >= bank.numSprites)
return nullptr;
@@ -186,7 +191,7 @@ int getBankStringWidth(const RA1SpriteBank &bank, const char *text) {
w += 4;
continue;
}
- const int fontIdx = (int)ch - 0x21;
+ const int fontIdx = getBankGlyphIndex(ch);
if (fontIdx < 0 || fontIdx >= bank.numSprites) {
w += 4;
continue;
More information about the Scummvm-git-logs
mailing list