[Scummvm-git-logs] scummvm master -> d3a293128524b5cfc1680c026f43dec4be3a3ddf
sev-
noreply at scummvm.org
Mon Sep 12 13:52:35 UTC 2022
This automated email contains information about 28 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
fcfa9652e3 DIRECTOR: Add Lost Mind of Dr. Brain demo detection entry
0e847c42bd DIRECTOR: LINGO: Limit sound updates in b_updateStage()
671d3116ea DIRECTOR: Add palette shifting code for transitions
7d4a89367e DIRECTOR: Improve transitions layer
9163b939c4 DIRECTOR: Improve Frame::readChannels() logging
756cfdd27d DIRECTOR: Make DirectorEngine copy palettes on use
7fc407bc4b DIRECTOR: Plug more memory leaks
076423de8a DIRECTOR: Implement color cycling
7de1d320a0 DIRECTOR: Add more palette transition modes
8f88c8a19a DIRECTOR: Make Lingo::setTheSprite coerce sprite IDs
59fbdf7558 DIRECTOR: Don't override sprite parameters for shapes
b572de94a4 DIRECTOR: Hardcode white and black in Channel::getPlotData()
7e412f1278 DIRECTOR: Use default palette in Score::startPlay()
f1db87e6d4 DIRECTOR: Improve dissolvePatternsTrans playback speed
54ff429191 DIRECTOR: Improve playback speed for all dissolve transitions
e750f05fe4 DIRECTOR: Don't erase _composeSurface after movie change
c7efa10493 DIRECTOR: Fix loading defaultPalette from config block
9e17e5aa85 DIRECTOR: Plug memory leak
af0dd7abe1 DIRECTOR: Pass mutable reference to Cast::loadPaletteData()
533dd7c78f DIRECTOR: Fix searching for files in subdirectories
cb0455e34d DIRECTOR: Fix audio loop use-after-free
e460102c77 DIRECTOR: Simplify D3 palette-loading code
3a096e60c3 DIRECTOR: Add version function to debugger
05c8119220 DIRECTOR: Start implementing Lingo debugger console
6876849f97 DIRECTOR: Add step, finish and next commands for debugger
c8ccf0e688 DIRECTOR: Add scriptframe command for debugger
b8155408f2 DIRECTOR: Add warning for unhandled Datum::reset()
d3a2931285 DIRECTOR: Tidy up debugger based on feedback
Commit: fcfa9652e33843d825df72121eeda8d93c96c1bd
https://github.com/scummvm/scummvm/commit/fcfa9652e33843d825df72121eeda8d93c96c1bd
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Add Lost Mind of Dr. Brain demo detection entry
Changed paths:
engines/director/detection_tables.h
diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index 4e4e61713a9..b57c968add5 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -1375,6 +1375,7 @@ static const PlainGameDescriptor directorGames[] = {
{ "mavisbeacon", "Mavis Beacon Teaches Typing" },
{ "mechwarrior2", "MechWarrior 2" },
{ "meetingmaker", "Meeting Maker" },
+ { "mindbrain", "The Lost Mind of Dr. Brain" },
{ "mothergoosehires", "Mixed-Up Mother Goose Deluxe" },
{ "msaccess", "Microsoft Access" },
{ "msarcade", "Microsoft Arcade" },
@@ -2291,6 +2292,8 @@ static const DirectorGameDescription gameDescriptions[] = {
MACDEMO1("meetingmaker", "Demo", "Meeting Maker Demo", "19fe54e0b5c60405c7a88d9e4e032965", 721976, 300),
+ WINDEMO1("mindbrain", "Demo", "INSTALL.EXE", "54fbe8edce6731ba6e89c16fd3be8e6d", 2558723, 404),
+
// Original filename is ãã¼ã¿ã¼ã¨ç¼
// One gameplay mode supports General MIDI
MACDEMO1_l("mipeterwolf", "Demo", "Peter and the Wolf", "f5277c53bacd27936158dd3867e587e2", 394653, Common::JA_JPN, 311),
Commit: 0e847c42bdaf0c9b2c917c1d97ffa9d6f7f21707
https://github.com/scummvm/scummvm/commit/0e847c42bdaf0c9b2c917c1d97ffa9d6f7f21707
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: LINGO: Limit sound updates in b_updateStage()
Previously it was possible for a Lingo script to stop a score sound channel,
then call updateStage, which would immediately start it again. To fix
this, updateStage() will now only update puppet sounds.
Fixes the sound playback when going from the map to the exit screen in
Chop Suey.
Changed paths:
engines/director/lingo/lingo-builtins.cpp
engines/director/score.cpp
engines/director/score.h
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index b866fae79ae..9087e68a88c 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -2594,7 +2594,7 @@ void LB::b_updateStage(int nargs) {
movie->getWindow()->render();
// play any puppet sounds that have been queued
- score->playSoundChannel(score->getCurrentFrame());
+ score->playSoundChannel(score->getCurrentFrame(), true);
if (score->_cursorDirty) {
score->renderCursor(movie->getWindow()->getMousePos());
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 01fc48f8792..ad04e02945d 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -510,7 +510,7 @@ void Score::renderFrame(uint16 frameId, RenderMode mode) {
_window->render();
- playSoundChannel(frameId);
+ playSoundChannel(frameId, false);
playQueuedSound(); // this is currently only used in FPlayXObj
if (_cursorDirty) {
@@ -747,7 +747,7 @@ Channel *Score::getChannelById(uint16 id) {
return _channels[id];
}
-void Score::playSoundChannel(uint16 frameId) {
+void Score::playSoundChannel(uint16 frameId, bool puppetOnly) {
Frame *frame = _frames[frameId];
debugC(5, kDebugLoading, "playSoundChannel(): Sound1 %s Sound2 %s", frame->_sound1.asString().c_str(), frame->_sound2.asString().c_str());
@@ -755,18 +755,22 @@ void Score::playSoundChannel(uint16 frameId) {
if (sound->isChannelPuppet(1)) {
sound->playPuppetSound(1);
- } else if (frame->_soundType1 >= kMinSampledMenu && frame->_soundType1 <= kMaxSampledMenu) {
- sound->playExternalSound(frame->_soundType1, frame->_sound1.member, 1);
- } else {
- sound->playCastMember(frame->_sound1, 1);
+ } else if (!puppetOnly) {
+ if (frame->_soundType1 >= kMinSampledMenu && frame->_soundType1 <= kMaxSampledMenu) {
+ sound->playExternalSound(frame->_soundType1, frame->_sound1.member, 1);
+ } else {
+ sound->playCastMember(frame->_sound1, 1);
+ }
}
if (sound->isChannelPuppet(2)) {
sound->playPuppetSound(2);
- } else if (frame->_soundType2 >= kMinSampledMenu && frame->_soundType2 <= kMaxSampledMenu) {
- sound->playExternalSound(frame->_soundType2, frame->_sound2.member, 2);
- } else {
- sound->playCastMember(frame->_sound2, 2);
+ } else if (!puppetOnly) {
+ if (frame->_soundType2 >= kMinSampledMenu && frame->_soundType2 <= kMaxSampledMenu) {
+ sound->playExternalSound(frame->_soundType2, frame->_sound2.member, 2);
+ } else {
+ sound->playCastMember(frame->_sound2, 2);
+ }
}
// Channels above 2 are only usable by Lingo.
diff --git a/engines/director/score.h b/engines/director/score.h
index bfab42e189e..fbda318183d 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -116,7 +116,7 @@ public:
void invalidateRectsForMember(CastMember *member);
- void playSoundChannel(uint16 frameId);
+ void playSoundChannel(uint16 frameId, bool puppetOnly);
private:
void update();
Commit: 671d3116ea9b9398bc892e5344bd32e44cb6145d
https://github.com/scummvm/scummvm/commit/671d3116ea9b9398bc892e5344bd32e44cb6145d
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Add palette shifting code for transitions
Fixes transitions in Lost Mind of Dr. Brain demo.
Changed paths:
engines/director/graphics.cpp
engines/director/score.cpp
engines/director/transitions.cpp
engines/director/window.h
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index d9113d00f21..28cc8e05aaf 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -121,7 +121,7 @@ void DirectorEngine::loadDefaultPalettes() {
PaletteV4 *DirectorEngine::getPalette(int id) {
if (!_loadedPalettes.contains(id)) {
- warning("DirectorEngine::addPalette(): Palette %d not found", id);
+ warning("DirectorEngine::getPalette(): Palette %d not found", id);
return nullptr;
}
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index ad04e02945d..6f50bb8660d 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -524,13 +524,13 @@ bool Score::renderTransition(uint16 frameId) {
TransParams *tp = _window->_puppetTransition;
if (tp) {
- _window->playTransition(tp->duration, tp->area, tp->chunkSize, tp->type, frameId);
+ _window->playTransition(frameId, tp->duration, tp->area, tp->chunkSize, tp->type, 0);
delete _window->_puppetTransition;
_window->_puppetTransition = nullptr;
return true;
} else if (currentFrame->_transType) {
- _window->playTransition(currentFrame->_transDuration, currentFrame->_transArea, currentFrame->_transChunkSize, currentFrame->_transType, frameId);
+ _window->playTransition(frameId, currentFrame->_transDuration, currentFrame->_transArea, currentFrame->_transChunkSize, currentFrame->_transType, resolvePaletteId(currentFrame->_palette.paletteId));
return true;
} else {
return false;
diff --git a/engines/director/transitions.cpp b/engines/director/transitions.cpp
index 234cdbe0bbb..4731de7ac61 100644
--- a/engines/director/transitions.cpp
+++ b/engines/director/transitions.cpp
@@ -130,17 +130,26 @@ struct {
TRANS(kTransDissolveBits, kTransAlgoDissolve, kTransDirNone)
};
-void Window::exitTransition(Graphics::ManagedSurface *nextFrame, Common::Rect clipRect) {
+void Window::exitTransition(TransParams &t, int step, Graphics::ManagedSurface *nextFrame, Common::Rect clipRect) {
_composeSurface->blitFrom(*nextFrame, clipRect, Common::Point(clipRect.left, clipRect.top));
- stepTransition();
+ stepTransition(t, step);
}
-void Window::stepTransition() {
+void Window::stepTransition(TransParams &t, int step) {
_contentIsDirty = true;
+
+ if (t.sourcePal != t.targetPal) {
+ for (int i = 0; i < 768; i++) {
+ int sourceCol = (i < t.sourcePalLength * 3 ? t.sourcePal[i] : 0);
+ int targetCol = (i < t.targetPalLength * 3 ? t.targetPal[i] : 0);
+ t.tempPal[i] = static_cast<byte>((targetCol * step + sourceCol * (t.steps - step)) / t.steps);
+ }
+ g_director->setPalette(t.tempPal, 256);
+ }
g_director->draw();
}
-void Window::playTransition(uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType, uint frame) {
+void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType, int paletteId) {
// Play a transition and return the number of subframes rendered
TransParams t;
@@ -154,6 +163,20 @@ void Window::playTransition(uint16 transDuration, uint8 transArea, uint8 transCh
if (debugChannelSet(-1, kDebugFast))
t.duration = 250;
+ // Copy palette information
+ t.sourcePal = g_director->getPalette();
+ t.sourcePalLength = g_director->getPaletteColorCount();
+ t.targetPal = g_director->getPalette();
+ t.targetPalLength = g_director->getPaletteColorCount();
+
+ if (paletteId) {
+ PaletteV4 *target = g_director->getPalette(paletteId);
+ if (target) {
+ t.targetPal = target->palette;
+ t.targetPalLength = target->length;
+ }
+ }
+
// Cache a copy of the frame before the transition.
Graphics::ManagedSurface currentFrame(Graphics::ManagedSurface(_composeSurface->w, _composeSurface->h, g_director->_pixelformat));
currentFrame.copyFrom(*_composeSurface);
@@ -515,17 +538,17 @@ void Window::playTransition(uint16 transDuration, uint8 transArea, uint8 transCh
_composeSurface->blitFrom(*blitFrom, rfrom, Common::Point(rto.left, rto.top));
if (_vm->processEvents(true)) {
- exitTransition(&nextFrame, clipRect);
+ exitTransition(t, i, &nextFrame, clipRect);
break;
}
if (fullredraw) {
- stepTransition();
+ stepTransition(t, i);
} else {
rto.clip(clipRect);
if (rto.height() > 0 && rto.width() > 0)
- stepTransition();
+ stepTransition(t, i);
}
uint32 endTime = g_system->getMillis();
@@ -714,12 +737,12 @@ void Window::dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::Man
}
} while (rnd != seed);
- stepTransition();
+ stepTransition(t, i);
g_lingo->executePerFrameHook(t.frame, i + 1);
if (_vm->processEvents(true)) {
- exitTransition(nextFrame, clipRect);
+ exitTransition(t, i, nextFrame, clipRect);
break;
}
@@ -820,12 +843,12 @@ void Window::dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graph
}
}
- stepTransition();
+ stepTransition(t, i);
g_lingo->executePerFrameHook(t.frame, i + 1);
if (_vm->processEvents(true)) {
- exitTransition(nextFrame, clipRect);
+ exitTransition(t, i, nextFrame, clipRect);
break;
}
@@ -845,6 +868,7 @@ void Window::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::Ma
for (uint16 i = 1; i < t.steps; i++) {
uint32 startTime = g_system->getMillis();
+
bool stop = false;
rto = clipRect;
@@ -993,7 +1017,7 @@ void Window::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::Ma
if (rto.height() > 0 && rto.width() > 0) {
_composeSurface->blitFrom(*nextFrame, rto, Common::Point(rto.left, rto.top));
- stepTransition();
+ stepTransition(t, i);
}
}
rects.clear();
@@ -1005,7 +1029,7 @@ void Window::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::Ma
g_system->delayMillis(MAX(0, diff));
if (_vm->processEvents(true)) {
- exitTransition(nextFrame, clipRect);
+ exitTransition(t, i, nextFrame, clipRect);
break;
}
@@ -1054,7 +1078,7 @@ void Window::transZoom(TransParams &t, Common::Rect &clipRect, Graphics::Managed
g_system->delayMillis(MAX(0, diff));
if (_vm->processEvents(true)) {
- exitTransition(nextFrame, clipRect);
+ exitTransition(t, i, nextFrame, clipRect);
break;
}
}
diff --git a/engines/director/window.h b/engines/director/window.h
index bc93580c987..839b2d63136 100644
--- a/engines/director/window.h
+++ b/engines/director/window.h
@@ -58,7 +58,13 @@ struct TransParams {
int stripSize;
- TransParams() {
+ const byte *sourcePal;
+ uint16 sourcePalLength;
+ const byte *targetPal;
+ uint16 targetPalLength;
+ byte tempPal[768];
+
+ TransParams() : tempPal() {
type = kTransNone;
frame = 0;
duration = 250;
@@ -70,10 +76,15 @@ struct TransParams {
xStepSize = yStepSize = 0;
xpos = ypos = 0;
+
+ sourcePal = nullptr;
+ sourcePalLength = 0;
+ targetPal = nullptr;
+ targetPalLength = 0;
}
TransParams(uint16 d, uint16 a, uint16 c, TransitionType t) :
- duration(d), area(a), chunkSize(c), type(t) {
+ duration(d), area(a), chunkSize(c), type(t), tempPal() {
frame = 0;
steps = 0;
stepDuration = 0;
@@ -81,6 +92,11 @@ struct TransParams {
xStepSize = yStepSize = 0;
xpos = ypos = 0;
+
+ sourcePal = nullptr;
+ sourcePalLength = 0;
+ targetPal = nullptr;
+ targetPalLength = 0;
}
};
@@ -99,9 +115,9 @@ public:
void reset();
// transitions.cpp
- void exitTransition(Graphics::ManagedSurface *nextFrame, Common::Rect clipRect);
- void stepTransition();
- void playTransition(uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType, uint frame);
+ void exitTransition(TransParams &t, int step, Graphics::ManagedSurface *nextFrame, Common::Rect clipRect);
+ void stepTransition(TransParams &t, int step);
+ void playTransition(uint frame, uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType, int paletteId);
void initTransParams(TransParams &t, Common::Rect &clipRect);
void dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
void dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
Commit: 7d4a89367e525ed143be4eb1a0f170a6acfc10cd
https://github.com/scummvm/scummvm/commit/7d4a89367e525ed143be4eb1a0f170a6acfc10cd
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Improve transitions layer
- Transitions now appear in the debug log, including parameters and
timing.
- Most transitions would calculate a fixed number of steps, then work
backwards to figure out the framerate required to fit the duration.
This approach didn't work for shorter durations, as the delay required
for the number of steps would drag out the duration. This has been
fixed by introducing a floor to the number of steps, so that the
framerate is no higher than 60fps.
- Multi-pass transitions were previously calling stepTransition() on
every blit; this would effectively redraw the entire screen ~96 times
a step and blow out the draw time to ~44 seconds. stepTransition() is
now called once per step.
- Blind transitions now cover the full range.
- kTransDissolveBoxySquares and kTransDissolveBoxyRects were swapped.
- kTransDissolveBoxyRects now adjusts for the viewport aspect ratio.
Changed paths:
engines/director/transitions.cpp
diff --git a/engines/director/transitions.cpp b/engines/director/transitions.cpp
index 4731de7ac61..823becb2f8a 100644
--- a/engines/director/transitions.cpp
+++ b/engines/director/transitions.cpp
@@ -69,6 +69,9 @@ enum {
#define TRANS(t,a,d) {t,#t,a,d}
+// cap transition framerate to 60fps
+#define MAX_STEPS(duration) ((duration)*60/1000)
+
struct {
TransitionType type;
const char *name;
@@ -222,6 +225,9 @@ void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, u
Common::Rect rfrom, rto;
+ uint32 transStartTime = g_system->getMillis();
+ debugC(2, kDebugLoading, "Window::playTransition(): Playing transition %d", t.type);
+
initTransParams(t, clipRect);
Graphics::ManagedSurface *blitFrom;
@@ -233,16 +239,22 @@ void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, u
dissolvePatternsTrans(t, clipRect, &nextFrame);
else
dissolveTrans(t, clipRect, &nextFrame);
+ debugC(2, kDebugLoading, "Window::playTransition(): type: %d, duration: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
+ debugC(2, kDebugLoading, "Window::playTransition(): Transition %d finished in %d ms", t.type, g_system->getMillis() - transStartTime);
return;
case kTransAlgoChecker:
case kTransAlgoStrips:
case kTransAlgoBlinds:
transMultiPass(t, clipRect, &nextFrame);
+ debugC(2, kDebugLoading, "Window::playTransition(): type: %d, duration: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
+ debugC(2, kDebugLoading, "Window::playTransition(): Transition %d finished in %d ms", t.type, g_system->getMillis() - transStartTime);
return;
case kTransAlgoZoom:
transZoom(t, clipRect, &nextFrame);
+ debugC(2, kDebugLoading, "Window::playTransition(): type: %d, duration: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
+ debugC(2, kDebugLoading, "Window::playTransition(): Transition %d finished in %d ms", t.type, g_system->getMillis() - transStartTime);
return;
case kTransAlgoCenterOut:
@@ -527,7 +539,7 @@ void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, u
break;
default:
- warning("Score::playTransition(): Unhandled transition type %s %d %d", transProps[t.type].name, t.duration, t.chunkSize);
+ warning("Window::playTransition(): Unhandled transition type %s %d %d", transProps[t.type].name, t.duration, t.chunkSize);
stop = true;
break;
}
@@ -562,6 +574,9 @@ void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, u
render(true, _composeSurface);
_contentIsDirty = true;
g_director->draw();
+
+ debugC(2, kDebugLoading, "Window::playTransition(): type: %d, duration: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
+ debugC(2, kDebugLoading, "Window::playTransition(): Transition %d finished in %d ms", t.type, g_system->getMillis() - transStartTime);
}
static int getLog2(int n) {
@@ -641,16 +656,21 @@ void Window::dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::Man
h = 1;
break;
- case kTransDissolveBoxyRects:
+ case kTransDissolveBoxySquares:
t.xStepSize = t.chunkSize;
t.yStepSize = t.chunkSize;
w = (w + t.chunkSize - 1) / t.chunkSize;
h = (h + t.chunkSize - 1) / t.chunkSize;
break;
- case kTransDissolveBoxySquares:
- t.xStepSize = MAX(w * t.chunkSize / h, (uint)1);
- t.yStepSize = MAX(h * t.chunkSize / w, (uint)1);
+ case kTransDissolveBoxyRects:
+ if (w > h) {
+ t.xStepSize = MAX(w * t.chunkSize / h, (uint)1);
+ t.yStepSize = t.chunkSize;
+ } else {
+ t.xStepSize = t.chunkSize;
+ t.yStepSize = MAX(h * t.chunkSize / w, (uint)1);
+ }
w = (w + t.xStepSize - 1) / t.xStepSize;
h = (h + t.yStepSize - 1) / t.yStepSize;
@@ -865,8 +885,9 @@ void Window::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::Ma
bool flag = false;
Common::Array<Common::Rect> rects;
+ rects.reserve(128);
- for (uint16 i = 1; i < t.steps; i++) {
+ for (uint16 i = 0; i < t.steps; i++) {
uint32 startTime = g_system->getMillis();
bool stop = false;
@@ -874,7 +895,7 @@ void Window::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::Ma
switch (t.type) {
case kTransVenetianBlind: // 37
- rto.setHeight(t.yStepSize * i);
+ rto.setHeight(t.yStepSize * (i + 1));
for (int r = 0; r < kNumBlinds; r++) {
rto.moveTo(0, r * t.stripSize);
rects.push_back(rto);
@@ -994,7 +1015,7 @@ void Window::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::Ma
break;
case kTransVerticalBinds: // 49
- rto.setWidth(t.xStepSize * i);
+ rto.setWidth(t.xStepSize * (i + 1));
for (int r = 0; r < kNumBlinds; r++) {
rto.moveTo(r * t.stripSize, 0);
rects.push_back(rto);
@@ -1002,7 +1023,7 @@ void Window::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::Ma
break;
default:
- warning("Score::transMultiPass(): Unhandled transition type %s %d %d", transProps[t.type].name, t.duration, t.chunkSize);
+ warning("Window::transMultiPass(): Unhandled transition type %s %d %d", transProps[t.type].name, t.duration, t.chunkSize);
stop = true;
break;
}
@@ -1017,9 +1038,9 @@ void Window::transMultiPass(TransParams &t, Common::Rect &clipRect, Graphics::Ma
if (rto.height() > 0 && rto.width() > 0) {
_composeSurface->blitFrom(*nextFrame, rto, Common::Point(rto.left, rto.top));
- stepTransition(t, i);
}
}
+ stepTransition(t, i);
rects.clear();
g_lingo->executePerFrameHook(t.frame, i);
@@ -1100,21 +1121,23 @@ void Window::initTransParams(TransParams &t, Common::Rect &clipRect) {
if (debugChannelSet(-1, kDebugFast))
t.chunkSize = MIN((uint) m, t.chunkSize*16);
+ uint maxSteps = MAX_STEPS(t.duration);
+
switch (transProps[t.type].dir) {
case kTransDirHorizontal:
- t.steps = MAX(w / t.chunkSize, (uint)1);
+ t.steps = MIN(MAX(w / t.chunkSize, (uint)1), maxSteps);
t.xStepSize = w / t.steps;
t.xpos = w % t.steps;
break;
case kTransDirVertical:
- t.steps = MAX(h / t.chunkSize, (uint)1);
+ t.steps = MIN(MAX(h / t.chunkSize, (uint)1), maxSteps);
t.yStepSize = h / t.steps;
t.ypos = h % t.steps;
break;
case kTransDirBoth:
- t.steps = MAX(m / t.chunkSize, (uint)1);
+ t.steps = MIN(MAX(m / t.chunkSize, (uint)1), maxSteps);
t.xStepSize = w / t.steps;
t.xpos = w % t.steps;
@@ -1123,17 +1146,23 @@ void Window::initTransParams(TransParams &t, Common::Rect &clipRect) {
break;
case kTransDirStepsH:
- t.xStepSize = t.chunkSize;
- t.yStepSize = (h + kNumStrips - 1) / kNumStrips;
- t.stripSize = (w + kNumStrips - 1) / kNumStrips;
- t.steps = ((w + t.xStepSize - 1) / t.xStepSize) * 2;
+ {
+ uint minChunkSize = (w - 1)/((maxSteps/2) - 1);
+ t.xStepSize = MAX(t.chunkSize, minChunkSize);
+ t.yStepSize = (h + kNumStrips - 1) / kNumStrips;
+ t.stripSize = (w + kNumStrips - 1) / kNumStrips;
+ t.steps = ((w + t.xStepSize - 1) / t.xStepSize) * 2;
+ }
break;
case kTransDirStepsV:
- t.xStepSize = (w + kNumStrips - 1) / kNumStrips;
- t.yStepSize = t.chunkSize;
- t.stripSize = (h + kNumStrips - 1) / kNumStrips;
- t.steps = ((h + t.yStepSize - 1) / t.yStepSize) * 2;
+ {
+ uint minChunkSize = (h - 1)/((maxSteps/2) - 1);
+ t.xStepSize = (w + kNumStrips - 1) / kNumStrips;
+ t.yStepSize = MAX(t.chunkSize, minChunkSize);
+ t.stripSize = (h + kNumStrips - 1) / kNumStrips;
+ t.steps = ((h + t.yStepSize - 1) / t.yStepSize) * 2;
+ }
break;
case kTransDirCheckers:
@@ -1149,16 +1178,14 @@ void Window::initTransParams(TransParams &t, Common::Rect &clipRect) {
case kTransDirBlindsV:
t.xStepSize = t.chunkSize;
- t.yStepSize = t.chunkSize;
t.stripSize = (w + kNumBlinds - 1) / kNumBlinds;
- t.steps = (w + t.stripSize - 1) / t.stripSize;
+ t.steps = (t.stripSize + t.xStepSize - 1) / t.xStepSize;
break;
case kTransDirBlindsH:
- t.xStepSize = t.chunkSize;
t.yStepSize = t.chunkSize;
t.stripSize = (h + kNumBlinds - 1) / kNumBlinds;
- t.steps = (h + t.stripSize - 1) / t.stripSize;
+ t.steps = (t.stripSize + t.yStepSize - 1) / t.yStepSize;
break;
default:
@@ -1166,6 +1193,7 @@ void Window::initTransParams(TransParams &t, Common::Rect &clipRect) {
}
t.stepDuration = t.duration / t.steps;
+
}
} // End of namespace Director
Commit: 9163b939c488801de667873c3d95911e79274dc4
https://github.com/scummvm/scummvm/commit/9163b939c488801de667873c3d95911e79274dc4
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Improve Frame::readChannels() logging
Changed paths:
engines/director/frame.cpp
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 5015fdf6d86..9afa93fba1c 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -155,8 +155,6 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
_soundType2 = stream->readByte();
}
- debugC(8, kDebugLoading, "Frame::readChannels(): actId: %d soundType: %d transDur: %d transChunk: %d tempo: %d transType: %d sound1: %d skipFrame: %d blend: %d sound2: %d soundType2: %d", _actionId.member, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1.member, _skipFrameFlag, _blend, _sound2.member, _soundType2);
-
// palette
if (_vm->getPlatform() == Common::kPlatformWindows) {
_palette.paletteId = stream->readUint16();
@@ -188,10 +186,6 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
debugC(8, kDebugLoading, "Frame::readChannels(): STUB: unk2: %02x %02x %02x %02x", unk[0], unk[1], unk[2], unk[3]);
}
- debugC(8, kDebugLoading, "Frame::readChannels(): palId: %d palFirst: %d palLast: %d palFlags: %d palCycles: %d palSpeed: %d palFrame: %d palLength: %d",
- _palette.paletteId, _palette.firstColor, _palette.lastColor, _palette.flags, _palette.cycleCount,
- _palette.speed, _palette.frameCount, _palette.cycleLength);
-
if (_vm->getPlatform() == Common::kPlatformMacintosh || _vm->getPlatform() == Common::kPlatformMacintoshII) {
stream->read(unk, 3);
debugC(8, kDebugLoading, "Frame::readChannels(): STUB: unk3: %02x %02x %02x", unk[0], unk[1], unk[2]);
@@ -243,6 +237,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
_palette.delay = stream->readByte();
_palette.style = stream->readByte();
+
unk1 = stream->readByte();
if (unk1)
warning("Frame::readChannels(): STUB: unk2: %d 0x%x", unk1, unk1);
@@ -259,7 +254,6 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
if (unk1)
warning("Frame::readChannels(): STUB: unk5: %d 0x%x", unk1, unk1);
- debugC(8, kDebugLoading, "Frame::readChannels(): %d %d %d %d %d %d %d %d %d %d %d", _actionId.member, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1.member, _skipFrameFlag, _blend, _sound2.member, _soundType2);
} else if (version >= kFileVer500 && version < kFileVer600) {
// Sound/Tempo/Transition channel
stream->read(unk, 24);
@@ -274,6 +268,22 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
// Script
}
+ debugC(4, kDebugLoading, "TMPO: tempo: %d, skipFrameFlag: %d, blend: %d",
+ _tempo, _skipFrameFlag, _blend);
+ if (_palette.paletteId) {
+ debugC(4, kDebugLoading, "PAL: paletteId: %d, firstColor: %d, lastColor: %d, flags: %d, cycleCount: %d, cycleLength: %d, speed: %d, frameCount: %d, fade: %d, delay: %d, style: %d",
+ _palette.paletteId, _palette.firstColor, _palette.lastColor, _palette.flags,
+ _palette.cycleCount, _palette.cycleLength, _palette.speed, _palette.frameCount,
+ _palette.fade, _palette.delay, _palette.style);
+ } else {
+ debugC(4, kDebugLoading, "PAL: paletteId: 000");
+ }
+ debugC(4, kDebugLoading, "TRAN: transType: %d, transDuration: %d, transChunkSize: %d",
+ _transType, _transDuration, _transChunkSize);
+ debugC(4, kDebugLoading, "SND: 1 sound1: %d, soundType1: %d", _sound1.member, _soundType1);
+ debugC(4, kDebugLoading, "SND: 2 sound2: %d, soundType2: %d", _sound2.member, _soundType2);
+ debugC(4, kDebugLoading, "LSCR: actionId: %d", _actionId.member);
+
_transChunkSize = CLIP<byte>(_transChunkSize, 0, 128);
_transDuration = CLIP<uint16>(_transDuration, 0, 32000); // restrict to 32 secs
Commit: 756cfdd27db52c80a735d8c996011a2bc4ac4b73
https://github.com/scummvm/scummvm/commit/756cfdd27db52c80a735d8c996011a2bc4ac4b73
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Make DirectorEngine copy palettes on use
This is going to be the basis for the palette-cycling effects.
Changed paths:
engines/director/director.cpp
engines/director/director.h
engines/director/graphics.cpp
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index 1677aaf7e74..1fe0546bab5 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -72,7 +72,7 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam
// Load key codes
loadKeyCodes();
- _currentPalette = nullptr;
+ memset(_currentPalette, 0, 768);
_currentPaletteLength = 0;
_stage = nullptr;
_windowList = new Datum;
@@ -175,7 +175,7 @@ Common::Error DirectorEngine::run() {
return Common::kAudioDeviceInitFailed;
}
- _currentPalette = nullptr;
+ memset(_currentPalette, 0, 768);
// we run mac-style menus | and we will redraw all widgets
_wmMode = Graphics::kWMModalMenuMode | Graphics::kWMModeManualDrawWidgets;
diff --git a/engines/director/director.h b/engines/director/director.h
index 38e49f56a1f..bd39eacaeb7 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -246,7 +246,7 @@ public:
uint16 _wmHeight;
private:
- byte *_currentPalette;
+ byte _currentPalette[768];
uint16 _currentPaletteLength;
Lingo *_lingo;
uint16 _version;
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index 28cc8e05aaf..1372fe43ab4 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -159,7 +159,8 @@ void DirectorEngine::setPalette(byte *palette, uint16 count) {
if (_pixelformat.bytesPerPixel == 1)
_system->getPaletteManager()->setPalette(palette, 0, count);
- _currentPalette = palette;
+ memset(_currentPalette, 0, 768);
+ memcpy(_currentPalette, palette, count * 3);
_currentPaletteLength = count;
_wm->passPalette(palette, count);
Commit: 7fc407bc4b8597c602b11a88d56337f590466450
https://github.com/scummvm/scummvm/commit/7fc407bc4b8597c602b11a88d56337f590466450
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Plug more memory leaks
Changed paths:
engines/director/cast.cpp
engines/director/castmember.cpp
engines/director/director.h
engines/director/lingo/lingo.cpp
engines/director/sound.cpp
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index f956981966b..6164010bfd6 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -646,6 +646,7 @@ void Cast::loadFilmLoopData(FilmLoopCastMember *member) {
Common::SeekableReadStreamEndian *loop = _castArchive->getResource(tag, filmLoopId);
debugC(2, kDebugLoading, "****** Loading '%s' id: %d, %d bytes", tag2str(tag), filmLoopId, (int)loop->size());
member->loadFilmLoopData(*loop);
+ delete loop;
} else {
warning("Cast::loadFilmLoopData(): Film loop not found");
}
diff --git a/engines/director/castmember.cpp b/engines/director/castmember.cpp
index f1b89381583..51708915411 100644
--- a/engines/director/castmember.cpp
+++ b/engines/director/castmember.cpp
@@ -1380,9 +1380,9 @@ void TextCastMember::importStxt(const Stxt *stxt) {
_ptext = stxt->_ptext;
// Rectifying _fontId in case of a fallback font
- Graphics::MacFont *macFont = new Graphics::MacFont(_fontId, _fontSize, _textSlant);
- g_director->_wm->_fontMan->getFont(macFont);
- _fontId = macFont->getId();
+ Graphics::MacFont macFont(_fontId, _fontSize, _textSlant);
+ g_director->_wm->_fontMan->getFont(&macFont);
+ _fontId = macFont.getId();
}
Graphics::MacWidget *TextCastMember::createWidget(Common::Rect &bbox, Channel *channel, SpriteType spriteType) {
diff --git a/engines/director/director.h b/engines/director/director.h
index bd39eacaeb7..297313141ea 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -134,8 +134,13 @@ struct MacShape {
};
struct PatternTile {
- Image::ImageDecoder *img;
+ Image::ImageDecoder *img = 0;
Common::Rect rect;
+
+ ~PatternTile() {
+ if (img)
+ delete img;
+ }
};
const int SCALE_THRESHOLD = 0x100;
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 83b70ac7ea7..cadb91a09f0 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -743,6 +743,9 @@ void Datum::reset() {
case FIELDREF:
delete u.cast;
break;
+ case MENUREF:
+ delete u.menu;
+ break;
default:
break;
}
diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index 3ba1212fee6..2f66eb95ff2 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -784,7 +784,7 @@ bool SNDDecoder::hasLoopBounds() {
AudioFileDecoder::AudioFileDecoder(Common::String &path)
: AudioDecoder() {
_path = path;
- _macresman = nullptr;
+ _macresman = new Common::MacResManager();
}
AudioFileDecoder::~AudioFileDecoder() {
@@ -795,7 +795,6 @@ Audio::AudioStream *AudioFileDecoder::getAudioStream(bool looping, bool forPuppe
if (_path.empty())
return nullptr;
- _macresman = new Common::MacResManager();
_macresman->open(Common::Path(pathMakeRelative(_path), g_director->_dirSeparator));
Common::SeekableReadStream *file = _macresman->getDataFork();
Commit: 076423de8a7068f8a755342384de11e2f0dd980f
https://github.com/scummvm/scummvm/commit/076423de8a7068f8a755342384de11e2f0dd980f
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Implement color cycling
Changed paths:
engines/director/director.h
engines/director/frame.cpp
engines/director/frame.h
engines/director/graphics.cpp
engines/director/score.cpp
engines/director/score.h
diff --git a/engines/director/director.h b/engines/director/director.h
index 297313141ea..7291a3ef73a 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -183,6 +183,7 @@ public:
void addPalette(int id, byte *palette, int length);
bool setPalette(int id);
void setPalette(byte *palette, uint16 count);
+ void shiftPalette(int startIndex, int endIndex, bool reverse);
void clearPalettes();
PaletteV4 *getPalette(int id);
void loadDefaultPalettes();
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 9afa93fba1c..80bbdb685d9 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -158,9 +158,16 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
// palette
if (_vm->getPlatform() == Common::kPlatformWindows) {
_palette.paletteId = stream->readUint16();
- _palette.firstColor = stream->readByte(); // for cycles. note: these start at 0x80 (for pal entry 0)!
- _palette.lastColor = stream->readByte();
+ // loop points for color cycling
+ _palette.firstColor = g_director->transformColor(stream->readByte() ^ 0x80);
+ _palette.lastColor = g_director->transformColor(stream->readByte() ^ 0x80);
_palette.flags = stream->readByte();
+ _palette.colorCycling = (_palette.flags & 0x80) != 0;
+ _palette.normal = (_palette.flags & 0x60) == 0x00;
+ _palette.fadeToWhite = (_palette.flags & 0x60) == 0x60;
+ _palette.fadeToBlack = (_palette.flags & 0x60) == 0x40;
+ _palette.autoReverse = (_palette.flags & 0x10) != 0;
+ _palette.overTime = (_palette.flags & 0x04) != 0;
_palette.speed = stream->readByte();
_palette.frameCount = stream->readUint16();
_palette.cycleCount = stream->readUint16();
@@ -174,9 +181,16 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
debugC(8, kDebugLoading, "Frame::readChannels(): STUB: unk1: %02x %02x %02x", unk[0], unk[1], unk[2]);
_palette.paletteId = stream->readSint16();
- _palette.firstColor = stream->readByte(); // for cycles. note: these start at 0x80 (for pal entry 0)!
- _palette.lastColor = stream->readByte();
+ // loop points for color cycling
+ _palette.firstColor = g_director->transformColor(stream->readByte() ^ 0x80);
+ _palette.lastColor = g_director->transformColor(stream->readByte() ^ 0x80);
_palette.flags = stream->readByte();
+ _palette.colorCycling = (_palette.flags & 0x80) != 0;
+ _palette.normal = (_palette.flags & 0x60) == 0x00;
+ _palette.fadeToWhite = (_palette.flags & 0x60) == 0x60;
+ _palette.fadeToBlack = (_palette.flags & 0x60) == 0x40;
+ _palette.autoReverse = (_palette.flags & 0x10) != 0;
+ _palette.overTime = (_palette.flags & 0x04) != 0;
_palette.cycleCount = stream->readByte();
_palette.speed = stream->readByte();
_palette.frameCount = stream->readByte();
@@ -227,9 +241,16 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
// palette
_palette.paletteId = stream->readSint16();
- _palette.firstColor = stream->readByte(); // for cycles. note: these start at 0x80 (for pal entry 0)!
- _palette.lastColor = stream->readByte();
+ // loop points for color cycling
+ _palette.firstColor = g_director->transformColor(stream->readByte() + 0x80);
+ _palette.lastColor = g_director->transformColor(stream->readByte() + 0x80);
_palette.flags = stream->readByte();
+ _palette.colorCycling = (_palette.flags & 0x80) != 0;
+ _palette.normal = (_palette.flags & 0x60) == 0x00;
+ _palette.fadeToWhite = (_palette.flags & 0x60) == 0x60;
+ _palette.fadeToBlack = (_palette.flags & 0x60) == 0x40;
+ _palette.autoReverse = (_palette.flags & 0x10) != 0;
+ _palette.overTime = (_palette.flags & 0x04) != 0;
_palette.speed = stream->readByte();
_palette.frameCount = stream->readUint16();
_palette.cycleCount = stream->readUint16();
diff --git a/engines/director/frame.h b/engines/director/frame.h
index da9d80ab6b1..7fda871da23 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -51,6 +51,12 @@ struct PaletteInfo {
byte firstColor;
byte lastColor;
byte flags;
+ bool colorCycling;
+ bool normal;
+ bool fadeToWhite;
+ bool fadeToBlack;
+ bool autoReverse;
+ bool overTime;
byte speed;
uint16 frameCount;
uint16 cycleCount;
@@ -63,7 +69,10 @@ struct PaletteInfo {
PaletteInfo() {
paletteId = 0;
firstColor = lastColor = 0;
- flags = 0; speed = 0;
+ flags = 0; colorCycling = false;
+ normal = false; fadeToWhite = false;
+ fadeToBlack = false; autoReverse = false;
+ overTime = false; speed = 0;
frameCount = cycleCount = cycleLength = 0;
fade = delay = style = colorCode = 0;
}
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index 1372fe43ab4..9cd25276e2a 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -155,15 +155,47 @@ bool DirectorEngine::setPalette(int id) {
}
void DirectorEngine::setPalette(byte *palette, uint16 count) {
- // Pass the palette to OSystem only for 8bpp mode
- if (_pixelformat.bytesPerPixel == 1)
- _system->getPaletteManager()->setPalette(palette, 0, count);
memset(_currentPalette, 0, 768);
- memcpy(_currentPalette, palette, count * 3);
+ memmove(_currentPalette, palette, count * 3);
_currentPaletteLength = count;
- _wm->passPalette(palette, count);
+ // Pass the palette to OSystem only for 8bpp mode
+ if (_pixelformat.bytesPerPixel == 1)
+ _system->getPaletteManager()->setPalette(_currentPalette, 0, _currentPaletteLength);
+
+ _wm->passPalette(_currentPalette, _currentPaletteLength);
+}
+
+void DirectorEngine::shiftPalette(int startIndex, int endIndex, bool reverse) {
+ if (startIndex == endIndex)
+ return;
+
+ if (endIndex > startIndex)
+ return;
+
+ // Palette indexes are in reverse order thanks to transformColor
+ byte temp[3] = { 0, 0, 0 };
+ int span = startIndex - endIndex + 1;
+ if (reverse) {
+ memcpy(temp, _currentPalette + 3 * endIndex, 3);
+ memmove(_currentPalette + 3 * endIndex,
+ _currentPalette + 3 * endIndex + 3,
+ (span - 1) * 3);
+ memcpy(_currentPalette + 3 * startIndex, temp, 3);
+ } else {
+ memcpy(temp, _currentPalette + 3 * startIndex, 3);
+ memmove(_currentPalette + 3 * endIndex + 3,
+ _currentPalette + 3 * endIndex,
+ (span - 1) * 3);
+ memcpy(_currentPalette + 3 * endIndex, temp, 3);
+ }
+
+ // Pass the palette to OSystem only for 8bpp mode
+ if (_pixelformat.bytesPerPixel == 1)
+ _system->getPaletteManager()->setPalette(_currentPalette, 0, _currentPaletteLength);
+
+ _wm->passPalette(_currentPalette, _currentPaletteLength);
}
void DirectorEngine::clearPalettes() {
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 6f50bb8660d..f23431a09cb 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -499,16 +499,12 @@ void Score::renderFrame(uint16 frameId, RenderMode mode) {
if (_window->_newMovieStarted)
renderCursor(_movie->getWindow()->getMousePos(), true);
- if (!renderTransition(frameId))
+ if (!renderTransition(frameId)) {
renderSprites(frameId, mode);
-
- int currentPalette = _frames[frameId]->_palette.paletteId;
- if (!_puppetPalette && currentPalette != _lastPalette && currentPalette) {
- _lastPalette = currentPalette;
- g_director->setPalette(resolvePaletteId(currentPalette));
+ _window->render();
+ renderPaletteCycle(frameId, mode);
}
- _window->render();
playSoundChannel(frameId, false);
playQueuedSound(); // this is currently only used in FPlayXObj
@@ -587,6 +583,55 @@ void Score::renderSprites(uint16 frameId, RenderMode mode) {
}
}
+void Score::renderPaletteCycle(uint16 frameId, RenderMode mode) {
+ int currentPalette = _frames[frameId]->_palette.paletteId;
+ if (!_puppetPalette && currentPalette != _lastPalette && currentPalette) {
+ _lastPalette = currentPalette;
+ g_director->setPalette(resolvePaletteId(currentPalette));
+ }
+
+ // Cycle speed in FPS
+ int speed = _frames[frameId]->_palette.speed;
+ if (speed == 0)
+ return;
+ // 30 (the maximum) is actually unbounded
+ int delay = speed == 30 ? 10 : 1000 / speed;
+ // Palette indexes are in reverse order thanks to transformColor
+ int firstColor = _frames[frameId]->_palette.firstColor;
+ int lastColor = _frames[frameId]->_palette.lastColor;
+ if (_frames[frameId]->_palette.colorCycling) {
+ if (_frames[frameId]->_palette.overTime) {
+ // do a single color step in one frame transition
+ } else {
+ // do a full color cycle in one frame transition
+ int steps = firstColor - lastColor + 1;
+ for (int i = 0; i < _frames[frameId]->_palette.cycleCount; i++) {
+ for (int j = 0; j < steps; j++) {
+ g_director->shiftPalette(firstColor, lastColor, false);
+ g_director->draw();
+ if (_vm->processEvents(true)) {
+ g_director->setPalette(resolvePaletteId(currentPalette));
+ return;
+ }
+ g_system->delayMillis(delay);
+ }
+ if (_frames[frameId]->_palette.autoReverse) {
+ for (int j = 0; j < steps; j++) {
+ g_director->shiftPalette(firstColor, lastColor, true);
+ g_director->draw();
+ if (_vm->processEvents(true)) {
+ g_director->setPalette(resolvePaletteId(currentPalette));
+ return;
+ }
+ g_system->delayMillis(delay);
+ }
+ }
+ }
+ }
+ }
+
+}
+
void Score::renderCursor(Common::Point pos, bool forceUpdate) {
if (_window != _vm->getCursorWindow()) {
// The cursor is outside of this window.
diff --git a/engines/director/score.h b/engines/director/score.h
index fbda318183d..95906293fb4 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -111,6 +111,7 @@ public:
bool renderTransition(uint16 frameId);
void renderFrame(uint16 frameId, RenderMode mode = kRenderModeNormal);
void renderSprites(uint16 frameId, RenderMode mode = kRenderModeNormal);
+ void renderPaletteCycle(uint16 frameId, RenderMode mode = kRenderModeNormal);
void renderCursor(Common::Point pos, bool forceUpdate = false);
void updateWidgets(bool hasVideoPlayback);
Commit: 7de1d320a0e566a1ae7d87dca247e9b85174118b
https://github.com/scummvm/scummvm/commit/7de1d320a0e566a1ae7d87dca247e9b85174118b
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Add more palette transition modes
Changed paths:
A engines/director/palette-fade.h
engines/director/frame.cpp
engines/director/score.cpp
engines/director/score.h
engines/director/transitions.cpp
engines/director/util.h
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 80bbdb685d9..1421e4101a8 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -164,8 +164,8 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
_palette.flags = stream->readByte();
_palette.colorCycling = (_palette.flags & 0x80) != 0;
_palette.normal = (_palette.flags & 0x60) == 0x00;
- _palette.fadeToWhite = (_palette.flags & 0x60) == 0x60;
- _palette.fadeToBlack = (_palette.flags & 0x60) == 0x40;
+ _palette.fadeToBlack = (_palette.flags & 0x60) == 0x60;
+ _palette.fadeToWhite = (_palette.flags & 0x60) == 0x40;
_palette.autoReverse = (_palette.flags & 0x10) != 0;
_palette.overTime = (_palette.flags & 0x04) != 0;
_palette.speed = stream->readByte();
@@ -187,8 +187,8 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
_palette.flags = stream->readByte();
_palette.colorCycling = (_palette.flags & 0x80) != 0;
_palette.normal = (_palette.flags & 0x60) == 0x00;
- _palette.fadeToWhite = (_palette.flags & 0x60) == 0x60;
- _palette.fadeToBlack = (_palette.flags & 0x60) == 0x40;
+ _palette.fadeToBlack = (_palette.flags & 0x60) == 0x60;
+ _palette.fadeToWhite = (_palette.flags & 0x60) == 0x40;
_palette.autoReverse = (_palette.flags & 0x10) != 0;
_palette.overTime = (_palette.flags & 0x04) != 0;
_palette.cycleCount = stream->readByte();
@@ -247,8 +247,8 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
_palette.flags = stream->readByte();
_palette.colorCycling = (_palette.flags & 0x80) != 0;
_palette.normal = (_palette.flags & 0x60) == 0x00;
- _palette.fadeToWhite = (_palette.flags & 0x60) == 0x60;
- _palette.fadeToBlack = (_palette.flags & 0x60) == 0x40;
+ _palette.fadeToBlack = (_palette.flags & 0x60) == 0x60;
+ _palette.fadeToWhite = (_palette.flags & 0x60) == 0x40;
_palette.autoReverse = (_palette.flags & 0x10) != 0;
_palette.overTime = (_palette.flags & 0x04) != 0;
_palette.speed = stream->readByte();
diff --git a/engines/director/palette-fade.h b/engines/director/palette-fade.h
new file mode 100644
index 00000000000..8964d8f6697
--- /dev/null
+++ b/engines/director/palette-fade.h
@@ -0,0 +1,166 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+static byte whitePalette[768] = {
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 0 (0x00)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 4 (0x04)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 8 (0x08)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 12 (0x0c)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 16 (0x10)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 20 (0x14)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 24 (0x18)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 28 (0x1c)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 32 (0x20)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 36 (0x24)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 40 (0x28)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 44 (0x2c)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 48 (0x30)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 52 (0x34)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 56 (0x38)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 60 (0x3c)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 64 (0x40)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 68 (0x44)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 72 (0x48)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 76 (0x4c)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 80 (0x50)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 84 (0x54)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 88 (0x58)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 92 (0x5c)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 96 (0x60)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 100 (0x64)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 104 (0x68)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 108 (0x6c)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 112 (0x70)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 116 (0x74)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 120 (0x78)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 124 (0x7c)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 128 (0x80)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 132 (0x84)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 136 (0x88)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 140 (0x8c)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 144 (0x90)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 148 (0x94)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 152 (0x98)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 156 (0x9c)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 160 (0xa0)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 164 (0xa4)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 168 (0xa8)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 172 (0xac)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 176 (0xb0)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 180 (0xb4)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 184 (0xb8)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 188 (0xbc)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 192 (0xc0)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 196 (0xc4)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 200 (0xc8)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 204 (0xcc)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 208 (0xd0)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 212 (0xd4)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 216 (0xd8)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 220 (0xdc)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 224 (0xe0)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 228 (0xe4)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 232 (0xe8)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 236 (0xec)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 240 (0xf0)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 244 (0xf4)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 248 (0xf8)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // 252 (0xfc)
+};
+
+static byte blackPalette[768] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 (0x00)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 4 (0x04)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 (0x08)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 12 (0x0c)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 16 (0x10)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20 (0x14)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 24 (0x18)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 28 (0x1c)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 32 (0x20)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 36 (0x24)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 40 (0x28)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 44 (0x2c)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 48 (0x30)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 52 (0x34)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 56 (0x38)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 60 (0x3c)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 64 (0x40)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 68 (0x44)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 72 (0x48)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 76 (0x4c)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 80 (0x50)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 84 (0x54)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 88 (0x58)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 92 (0x5c)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 96 (0x60)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 100 (0x64)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 104 (0x68)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 108 (0x6c)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 112 (0x70)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 116 (0x74)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 120 (0x78)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 124 (0x7c)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 128 (0x80)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 132 (0x84)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 136 (0x88)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 140 (0x8c)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 144 (0x90)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 148 (0x94)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 152 (0x98)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 156 (0x9c)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 160 (0xa0)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 164 (0xa4)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 168 (0xa8)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 172 (0xac)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 176 (0xb0)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 180 (0xb4)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 184 (0xb8)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 188 (0xbc)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 192 (0xc0)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 196 (0xc4)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 200 (0xc8)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 204 (0xcc)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 208 (0xd0)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 212 (0xd4)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 216 (0xd8)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 220 (0xdc)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 224 (0xe0)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 228 (0xe4)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 232 (0xe8)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 236 (0xec)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 240 (0xf0)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 244 (0xf4)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 248 (0xf8)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff // 252 (0xfc)
+};
+
+// TODO: Timing here is measured empirically from DOSBox,
+// accuracy could be improved.
+// Regression formula used:
+// [round(31.78738613 + -1.934614248*i + 0.03033348561*i*i) for i in range(1, 31)]
+static int fadeColorFrames[30] = {
+ 30, 28, 26, 25, 23, 21, 20, 18, 17, 15, 14,
+ 13, 12, 11, 10, 9, 8, 7, 6, 5,
+ 5, 4, 3, 3, 2, 2, 2, 1, 1, 1
+};
+
+static int fadeColorWait = 30;
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index f23431a09cb..fc8849a1eb0 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -48,6 +48,8 @@
namespace Director {
+#include "director/palette-fade.h"
+
Score::Score(Movie *movie) {
_movie = movie;
_window = movie->getWindow();
@@ -59,6 +61,8 @@ Score::Score(Movie *movie) {
_puppetTempo = 0x00;
_puppetPalette = false;
_lastPalette = 0;
+ _paletteTransitionIndex = 0;
+ memset(_paletteSnapshotBuffer, 0, 768);
_labels = nullptr;
@@ -500,9 +504,11 @@ void Score::renderFrame(uint16 frameId, RenderMode mode) {
renderCursor(_movie->getWindow()->getMousePos(), true);
if (!renderTransition(frameId)) {
+ bool skip = renderPrePaletteCycle(frameId, mode);
renderSprites(frameId, mode);
_window->render();
- renderPaletteCycle(frameId, mode);
+ if (!skip)
+ renderPaletteCycle(frameId, mode);
}
@@ -583,13 +589,112 @@ void Score::renderSprites(uint16 frameId, RenderMode mode) {
}
}
+bool Score::renderPrePaletteCycle(uint16 frameId, RenderMode mode) {
+ if (_puppetPalette)
+ return false;
+
+ // If the palette is defined in the frame and doesn't match
+ // the current one, set it
+ int currentPalette = _frames[frameId]->_palette.paletteId;
+ if (!currentPalette || !resolvePaletteId(currentPalette))
+ return false;
+
+ if (!_frames[frameId]->_palette.colorCycling &&
+ !_frames[frameId]->_palette.overTime) {
+
+ // Copy the current palette into the snapshot buffer
+ memset(_paletteSnapshotBuffer, 0, 768);
+ memcpy(_paletteSnapshotBuffer, g_director->getPalette(), g_director->getPaletteColorCount() * 3);
+ PaletteV4 *destPal = g_director->getPalette(resolvePaletteId(currentPalette));
+
+ int frameRate = CLIP<int>(_frames[frameId]->_palette.speed, 1, 30);
+ int frameDelay = 1000/60;
+ int fadeFrames = fadeColorFrames[frameRate - 1];
+ byte calcPal[768];
+
+ if (_frames[frameId]->_palette.normal) {
+ // For fade palette transitions, the whole fade happens with
+ // the previous frame's layout.
+ for (int i = 0; i < fadeFrames; i++) {
+ lerpPalette(
+ calcPal,
+ _paletteSnapshotBuffer, 256,
+ destPal->palette, destPal->length,
+ i + 1,
+ fadeFrames
+ );
+ g_director->setPalette(calcPal, 256);
+ g_director->draw();
+ // On click, stop loop and reset palette
+ if (_vm->processEvents(true)) {
+ g_director->setPalette(resolvePaletteId(currentPalette));
+ return true;
+ }
+ g_system->delayMillis(frameDelay);
+ }
+
+ } else {
+ // For fade to black and fade to white palette transitions,
+ // the first half happens with the previous frame's layout.
+
+ byte *fadePal = nullptr;
+ if (_frames[frameId]->_palette.fadeToBlack) {
+ // Fade everything except color index 0 to black
+ fadePal = blackPalette;
+ } else if (_frames[frameId]->_palette.fadeToWhite) {
+ // Fade everything except color index 255 to white
+ fadePal = whitePalette;
+ } else {
+ // Shouldn't reach here
+ return false;
+ }
+
+ for (int i = 0; i < fadeFrames; i++) {
+ lerpPalette(
+ calcPal,
+ _paletteSnapshotBuffer, 256,
+ fadePal, 256,
+ i + 1,
+ fadeFrames
+ );
+ g_director->setPalette(calcPal, 256);
+ g_director->draw();
+ // On click, stop loop and reset palette
+ if (_vm->processEvents(true)) {
+ g_director->setPalette(resolvePaletteId(currentPalette));
+ return true;
+ }
+ g_system->delayMillis(frameDelay);
+ }
+ }
+ }
+ return false;
+}
+
void Score::renderPaletteCycle(uint16 frameId, RenderMode mode) {
+ if (_puppetPalette)
+ return;
+
+ // If the palette is defined in the frame and doesn't match
+ // the current one, set it
int currentPalette = _frames[frameId]->_palette.paletteId;
- if (!_puppetPalette && currentPalette != _lastPalette && currentPalette) {
+ if (!currentPalette || !resolvePaletteId(currentPalette))
+ return;
+
+ bool paletteChanged = currentPalette != _lastPalette && currentPalette;
+ if (paletteChanged) {
_lastPalette = currentPalette;
- g_director->setPalette(resolvePaletteId(currentPalette));
+ _paletteTransitionIndex = 0;
}
+ // For palette cycling, the only thing that is checked is if
+ // the palette ID is the same. Different cycling configs with
+ // the same palette ID will persist any mutated state.
+ // e.g. if you use overTime to cycle the palette partially
+ // through a cycle, then switch to doing a full color cycle
+ // on the same palette, it will not reset and the weird
+ // offset will remain.
+
// Cycle speed in FPS
int speed = _frames[frameId]->_palette.speed;
if (speed == 0)
@@ -597,18 +702,27 @@ void Score::renderPaletteCycle(uint16 frameId, RenderMode mode) {
// 30 (the maximum) is actually unbounded
int delay = speed == 30 ? 10 : 1000 / speed;
// Palette indexes are in reverse order thanks to transformColor
- int firstColor = _frames[frameId]->_palette.firstColor;
- int lastColor = _frames[frameId]->_palette.lastColor;
if (_frames[frameId]->_palette.colorCycling) {
+ // Cycle the colors of a chosen palette
+ int firstColor = _frames[frameId]->_palette.firstColor;
+ int lastColor = _frames[frameId]->_palette.lastColor;
+
+ // If we've just chosen this palette, set it immediately
+ if (paletteChanged)
+ g_director->setPalette(resolvePaletteId(currentPalette));
+
if (_frames[frameId]->_palette.overTime) {
- // do a single color step in one frame transition
+ // Do a single color step in one frame transition
+ g_director->shiftPalette(firstColor, lastColor, false);
+ g_director->draw();
} else {
- // do a full color cycle in one frame transition
+ // Do a full color cycle in one frame transition
int steps = firstColor - lastColor + 1;
for (int i = 0; i < _frames[frameId]->_palette.cycleCount; i++) {
for (int j = 0; j < steps; j++) {
g_director->shiftPalette(firstColor, lastColor, false);
g_director->draw();
+ // On click, stop loop and reset palette
if (_vm->processEvents(true)) {
g_director->setPalette(resolvePaletteId(currentPalette));
return;
@@ -619,6 +733,7 @@ void Score::renderPaletteCycle(uint16 frameId, RenderMode mode) {
for (int j = 0; j < steps; j++) {
g_director->shiftPalette(firstColor, lastColor, true);
g_director->draw();
+ // On click, stop loop and reset palette
if (_vm->processEvents(true)) {
g_director->setPalette(resolvePaletteId(currentPalette));
return;
@@ -628,8 +743,120 @@ void Score::renderPaletteCycle(uint16 frameId, RenderMode mode) {
}
}
}
- }
+ } else {
+ // Transition from the current palette to a new palette
+ PaletteV4 *destPal = g_director->getPalette(resolvePaletteId(currentPalette));
+ int frameCount = _frames[frameId]->_palette.frameCount;
+ byte calcPal[768];
+ if (_frames[frameId]->_palette.overTime) {
+ // Transition over a series of frames
+ if (_paletteTransitionIndex == 0) {
+ // Copy the current palette into the snapshot buffer
+ memset(_paletteSnapshotBuffer, 0, 768);
+ memcpy(_paletteSnapshotBuffer, g_director->getPalette(), g_director->getPaletteColorCount() * 3);
+ }
+
+ if (_frames[frameId]->_palette.normal) {
+ // Fade the palette directly to the new palette
+ lerpPalette(
+ calcPal,
+ _paletteSnapshotBuffer, 256,
+ destPal->palette, destPal->length,
+ _paletteTransitionIndex + 1,
+ frameCount
+ );
+ } else {
+ // Fade the palette to an intermediary color (black or white),
+ // then to the new palette
+ int halfway = frameCount / 2;
+
+ byte *fadePal = nullptr;
+ if (_frames[frameId]->_palette.fadeToBlack) {
+ // Fade everything except color index 0 to black
+ fadePal = blackPalette;
+ } else if (_frames[frameId]->_palette.fadeToWhite) {
+ // Fade everything except color index 255 to white
+ fadePal = whitePalette;
+ } else {
+ // Shouldn't reach here
+ return;
+ }
+
+ if (_paletteTransitionIndex < halfway) {
+ lerpPalette(
+ calcPal,
+ _paletteSnapshotBuffer, 256,
+ fadePal, 256,
+ _paletteTransitionIndex + 1,
+ halfway
+ );
+ } else {
+ lerpPalette(
+ calcPal,
+ fadePal, 256,
+ destPal->palette, destPal->length,
+ _paletteTransitionIndex - halfway + 1,
+ frameCount - halfway
+ );
+ }
+ }
+ g_director->setPalette(calcPal, 256);
+ _paletteTransitionIndex++;
+ _paletteTransitionIndex %= frameCount;
+ } else {
+ // Do a full cycle in one frame transition
+
+ // For normal mode, we've already faded the palette in renderPrePaletteCycle
+ if (!_frames[frameId]->_palette.normal) {
+ byte *fadePal = nullptr;
+ if (_frames[frameId]->_palette.fadeToBlack) {
+ // Fade everything except color index 0 to black
+ fadePal = blackPalette;
+ } else if (_frames[frameId]->_palette.fadeToWhite) {
+ // Fade everything except color index 255 to white
+ fadePal = whitePalette;
+ } else {
+ // Shouldn't reach here
+ return;
+ }
+ int frameRate = CLIP<int>(_frames[frameId]->_palette.speed, 1, 30);
+ int frameDelay = 1000/60;
+ int fadeFrames = fadeColorFrames[frameRate - 1];
+
+ // Wait for a fixed time
+ g_director->setPalette(fadePal, 256);
+ g_director->draw();
+ for (int i = 0; i < fadeColorWait; i++) {
+ // On click, stop loop and reset palette
+ if (_vm->processEvents(true)) {
+ g_director->setPalette(resolvePaletteId(currentPalette));
+ return;
+ }
+ g_system->delayMillis(frameDelay);
+ }
+
+ for (int i = 0; i < fadeFrames; i++) {
+ lerpPalette(
+ calcPal,
+ fadePal, 256,
+ destPal->palette, destPal->length,
+ i + 1,
+ fadeFrames
+ );
+ g_director->setPalette(calcPal, 256);
+ g_director->draw();
+ // On click, stop loop and reset palette
+ if (_vm->processEvents(true)) {
+ g_director->setPalette(resolvePaletteId(currentPalette));
+ return;
+ }
+ g_system->delayMillis(frameDelay);
+ }
+
+ }
+ }
+ }
}
void Score::renderCursor(Common::Point pos, bool forceUpdate) {
diff --git a/engines/director/score.h b/engines/director/score.h
index 95906293fb4..63f1e5a2877 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -111,6 +111,7 @@ public:
bool renderTransition(uint16 frameId);
void renderFrame(uint16 frameId, RenderMode mode = kRenderModeNormal);
void renderSprites(uint16 frameId, RenderMode mode = kRenderModeNormal);
+ bool renderPrePaletteCycle(uint16 frameId, RenderMode mode = kRenderModeNormal);
void renderPaletteCycle(uint16 frameId, RenderMode mode = kRenderModeNormal);
void renderCursor(Common::Point pos, bool forceUpdate = false);
void updateWidgets(bool hasVideoPlayback);
@@ -139,6 +140,8 @@ public:
byte _puppetTempo;
bool _puppetPalette;
int _lastPalette;
+ int _paletteTransitionIndex;
+ byte _paletteSnapshotBuffer[768];
PlayState _playState;
uint32 _nextFrameTime;
diff --git a/engines/director/transitions.cpp b/engines/director/transitions.cpp
index 823becb2f8a..e34c4a8a71d 100644
--- a/engines/director/transitions.cpp
+++ b/engines/director/transitions.cpp
@@ -143,9 +143,10 @@ void Window::stepTransition(TransParams &t, int step) {
if (t.sourcePal != t.targetPal) {
for (int i = 0; i < 768; i++) {
- int sourceCol = (i < t.sourcePalLength * 3 ? t.sourcePal[i] : 0);
- int targetCol = (i < t.targetPalLength * 3 ? t.targetPal[i] : 0);
- t.tempPal[i] = static_cast<byte>((targetCol * step + sourceCol * (t.steps - step)) / t.steps);
+ t.tempPal[i] = lerpByte(
+ (i < t.sourcePalLength * 3 ? t.sourcePal[i] : 0),
+ (i < t.targetPalLength * 3 ? t.targetPal[i] : 0),
+ step, t.steps);
}
g_director->setPalette(t.tempPal, 256);
}
diff --git a/engines/director/util.h b/engines/director/util.h
index 97238f76002..a7261fccb18 100644
--- a/engines/director/util.h
+++ b/engines/director/util.h
@@ -101,6 +101,25 @@ Common::String utf8ToPrintable(const Common::String &str);
Common::String decodePlatformEncoding(Common::String input);
+inline byte lerpByte(byte a, byte b, int alpha, int span) {
+ int ai = static_cast<int>(a);
+ int bi = static_cast<int>(b);
+ span = CLIP<int>(span, 1, span);
+ alpha = CLIP<int>(alpha, 0, span);
+ return static_cast<byte>((bi * alpha + ai * (span - alpha)) / span);
+}
+
+inline void lerpPalette(byte *target, byte *palA, int palALength, byte *palB, int palBLength, int alpha, int span) {
+ for (int i = 0; i < 768; i++) {
+ target[i] = lerpByte(
+ i < palALength * 3 ? palA[i] : 0,
+ i < palBLength * 3 ? palB[i] : 0,
+ alpha,
+ span
+ );
+ }
+}
+
} // End of namespace Director
#endif
Commit: 8f88c8a19ad02b3dcc28ced30e8cd227570335e5
https://github.com/scummvm/scummvm/commit/8f88c8a19ad02b3dcc28ced30e8cd227570335e5
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Make Lingo::setTheSprite coerce sprite IDs
Fixes parts not hiding after being selected on the face
selection screen in Eastern Mind.
Changed paths:
engines/director/lingo/lingo-the.cpp
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 110c0b8f876..353b7b513e8 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -1466,7 +1466,7 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
}
void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
- int id = 0;
+ int id = id1.asInt();
Score *score = _vm->getCurrentMovie()->getScore();
if (!score) {
@@ -1474,13 +1474,6 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
return;
}
- if (id1.type == INT) {
- id = id1.u.i;
- } else {
- warning("Lingo::setTheSprite(): Unknown the sprite id type: %s", id1.type2str());
- return;
- }
-
Channel *channel = score->getChannelById(id);
if (!channel)
return;
Commit: 59fbdf75580dad4122b2ba8f3b10b3013d15cd53
https://github.com/scummvm/scummvm/commit/59fbdf75580dad4122b2ba8f3b10b3013d15cd53
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Don't override sprite parameters for shapes
Fixes various blue rectangles in Eastern Mind and Total Distortion.
Changed paths:
engines/director/sprite.cpp
diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp
index bbc0f062370..3a9ba29a5cf 100644
--- a/engines/director/sprite.cpp
+++ b/engines/director/sprite.cpp
@@ -244,13 +244,6 @@ MacShape *Sprite::getShape() {
default:
break;
}
-
- if (g_director->getVersion() >= 400) {
- shape->foreColor = sc->getForeColor();
- shape->backColor = sc->getBackColor();
- shape->lineSize = sc->_lineThickness;
- shape->ink = sc->_ink;
- }
}
// for outlined shapes, line thickness of 1 means invisible.
@@ -265,8 +258,7 @@ uint32 Sprite::getBackColor() {
switch (_cast->_type) {
case kCastText:
- case kCastButton:
- case kCastShape: {
+ case kCastButton: {
return _cast->getBackColor();
}
default:
@@ -280,8 +272,7 @@ uint32 Sprite::getForeColor() {
switch (_cast->_type) {
case kCastText:
- case kCastButton:
- case kCastShape: {
+ case kCastButton: {
return _cast->getForeColor();
}
default:
Commit: b572de94a41d44742f562d1960c98cc77dcffdbe
https://github.com/scummvm/scummvm/commit/b572de94a41d44742f562d1960c98cc77dcffdbe
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Hardcode white and black in Channel::getPlotData()
Blit operations in Director expect that the "white" and "black" color
indexes are at 255 and 0, respectively. Fetching these values from
the window manager is not reliable when the palette has multiple
indexes sharing a color (e.g. blackPalette and whitePalette), which will
mean the applyColor flag is incorrectly set to true when foreColor and
backColor are the correct values.
Fixes fade from white when entering the door to the Land of Desire in
Eastern Mind.
Changed paths:
engines/director/channel.cpp
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 2cf2ec12e73..77fcf91cf98 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -107,8 +107,8 @@ Channel::~Channel() {
DirectorPlotData Channel::getPlotData() {
DirectorPlotData pd(g_director, _sprite->_spriteType, _sprite->_ink, _sprite->_blend, _sprite->getBackColor(), _sprite->getForeColor());
- pd.colorWhite = pd.d->_wm->_colorWhite;
- pd.colorBlack = pd.d->_wm->_colorBlack;
+ pd.colorWhite = 255;
+ pd.colorBlack = 0;
pd.dst = nullptr;
pd.srf = getSurface();
Commit: 7e412f1278f487bbef52078cbd496aca42868431
https://github.com/scummvm/scummvm/commit/7e412f1278f487bbef52078cbd496aca42868431
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Use default palette in Score::startPlay()
Switching to a new movie should force a switch to the default palette if
required, and not assume the palette in use is correct.
Fixes the palette tinting after being reincarnated in Eastern Mind.
Changed paths:
engines/director/score.cpp
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index fc8849a1eb0..923c97f0cba 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -268,6 +268,8 @@ void Score::startPlay() {
}
_lastPalette = _frames[_currentFrame]->_palette.paletteId;
+ if (!_lastPalette)
+ _lastPalette = _movie->getCast()->_defaultPalette;
_vm->setPalette(resolvePaletteId(_lastPalette));
// All frames in the same movie have the same number of channels
Commit: f1db87e6d4ebb372a7a32295f9086248044efdbe
https://github.com/scummvm/scummvm/commit/f1db87e6d4ebb372a7a32295f9086248044efdbe
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Improve dissolvePatternsTrans playback speed
Changed paths:
engines/director/transitions.cpp
diff --git a/engines/director/transitions.cpp b/engines/director/transitions.cpp
index e34c4a8a71d..f681148c85c 100644
--- a/engines/director/transitions.cpp
+++ b/engines/director/transitions.cpp
@@ -58,7 +58,8 @@ enum TransitionDirection {
kTransDirStepsV,
kTransDirCheckers,
kTransDirBlindsV,
- kTransDirBlindsH
+ kTransDirBlindsH,
+ kTransDirDissolve
};
enum {
@@ -104,7 +105,7 @@ struct {
TRANS(kTransDissolvePixelsFast, kTransAlgoDissolve, kTransDirNone),
TRANS(kTransDissolveBoxyRects, kTransAlgoDissolve, kTransDirNone),
TRANS(kTransDissolveBoxySquares, kTransAlgoDissolve, kTransDirNone), // 25
- TRANS(kTransDissolvePatterns, kTransAlgoDissolve, kTransDirNone),
+ TRANS(kTransDissolvePatterns, kTransAlgoDissolve, kTransDirDissolve),
TRANS(kTransRandomRows, kTransAlgoDissolve, kTransDirNone),
TRANS(kTransRandomColumns, kTransAlgoDissolve, kTransDirNone),
TRANS(kTransCoverDown, kTransAlgoCover, kTransDirVertical),
@@ -841,13 +842,13 @@ static byte dissolvePatterns[][8] = {
};
void Window::dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *nextFrame) {
- t.steps = 64;
- t.stepDuration = t.duration / t.steps;
+ int patternSteps = 64;
for (int i = 0; i < t.steps; i++) {
+ int patternIndex = (patternSteps - 1) * (i + 1) / t.steps;
uint32 startTime = g_system->getMillis();
for (int y = clipRect.top; y < clipRect.bottom; y++) {
- byte pat = dissolvePatterns[i][y % 8];
+ byte pat = dissolvePatterns[patternIndex][y % 8];
byte *dst = (byte *)_composeSurface->getBasePtr(clipRect.left, y);
byte *src = (byte *)nextFrame->getBasePtr(clipRect.left, y);
@@ -1189,6 +1190,11 @@ void Window::initTransParams(TransParams &t, Common::Rect &clipRect) {
t.steps = (t.stripSize + t.yStepSize - 1) / t.yStepSize;
break;
+ case kTransDirDissolve:
+ t.steps = MIN<int>(MAX_STEPS(t.duration), 64);
+ t.stepDuration = t.duration / t.steps;
+ break;
+
default:
t.steps = 1;
}
Commit: 54ff42919170631e5f277c96aab73e806c9da2eb
https://github.com/scummvm/scummvm/commit/54ff42919170631e5f277c96aab73e806c9da2eb
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Improve playback speed for all dissolve transitions
Changed paths:
engines/director/transitions.cpp
diff --git a/engines/director/transitions.cpp b/engines/director/transitions.cpp
index f681148c85c..04732801343 100644
--- a/engines/director/transitions.cpp
+++ b/engines/director/transitions.cpp
@@ -102,12 +102,12 @@ struct {
TRANS(kTransRevealDownLeft, kTransAlgoReveal, kTransDirBoth), // 20
TRANS(kTransRevealLeft, kTransAlgoReveal, kTransDirHorizontal),
TRANS(kTransRevealUpLeft, kTransAlgoReveal, kTransDirBoth),
- TRANS(kTransDissolvePixelsFast, kTransAlgoDissolve, kTransDirNone),
- TRANS(kTransDissolveBoxyRects, kTransAlgoDissolve, kTransDirNone),
- TRANS(kTransDissolveBoxySquares, kTransAlgoDissolve, kTransDirNone), // 25
+ TRANS(kTransDissolvePixelsFast, kTransAlgoDissolve, kTransDirDissolve),
+ TRANS(kTransDissolveBoxyRects, kTransAlgoDissolve, kTransDirDissolve),
+ TRANS(kTransDissolveBoxySquares, kTransAlgoDissolve, kTransDirDissolve), // 25
TRANS(kTransDissolvePatterns, kTransAlgoDissolve, kTransDirDissolve),
- TRANS(kTransRandomRows, kTransAlgoDissolve, kTransDirNone),
- TRANS(kTransRandomColumns, kTransAlgoDissolve, kTransDirNone),
+ TRANS(kTransRandomRows, kTransAlgoDissolve, kTransDirDissolve),
+ TRANS(kTransRandomColumns, kTransAlgoDissolve, kTransDirDissolve),
TRANS(kTransCoverDown, kTransAlgoCover, kTransDirVertical),
TRANS(kTransCoverDownLeft, kTransAlgoCover, kTransDirBoth), // 30
TRANS(kTransCoverDownRight, kTransAlgoCover, kTransDirBoth),
@@ -129,9 +129,9 @@ struct {
TRANS(kTransZoomOpen, kTransAlgoZoom, kTransDirBoth),
TRANS(kTransZoomClose, kTransAlgoZoom, kTransDirBoth),
TRANS(kTransVerticalBinds, kTransAlgoBlinds, kTransDirBlindsV),
- TRANS(kTransDissolveBitsFast, kTransAlgoDissolve, kTransDirNone), // 50
- TRANS(kTransDissolvePixels, kTransAlgoDissolve, kTransDirNone),
- TRANS(kTransDissolveBits, kTransAlgoDissolve, kTransDirNone)
+ TRANS(kTransDissolveBitsFast, kTransAlgoDissolve, kTransDirDissolve), // 50
+ TRANS(kTransDissolvePixels, kTransAlgoDissolve, kTransDirDissolve),
+ TRANS(kTransDissolveBits, kTransAlgoDissolve, kTransDirDissolve)
};
void Window::exitTransition(TransParams &t, int step, Graphics::ManagedSurface *nextFrame, Common::Rect clipRect) {
@@ -695,70 +695,69 @@ void Window::dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::Man
// Calculate steps
uint32 pixPerStepInit = 1;
- t.steps = (1 << (hBits + vBits)) - 1;
+ int bitSteps = (1 << (hBits + vBits)) - 1;
- while (t.steps > 64) {
+ while (bitSteps > 64) {
pixPerStepInit <<= 1;
- t.steps >>= 1;
+ bitSteps >>= 1;
}
- t.steps++;
-
- t.stepDuration = t.duration / t.steps;
-
- if (t.type == kTransDissolvePixelsFast ||
- t.type == kTransDissolveBitsFast)
- t.stepDuration = 0; // No delay
+ bitSteps++;
Common::Rect r(MAX(1, t.xStepSize), t.yStepSize);
+ int bitIndex = -1;
for (int i = 0; i < t.steps; i++) {
uint32 startTime = g_system->getMillis();
- uint32 pixPerStep = pixPerStepInit;
- do {
- uint32 x = (rnd - 1) >> vShift;
- uint32 y = (rnd - 1) & hMask;
- byte mask = 0;
+ int bitEndIndex = (bitSteps - 1) * (i + 1) / t.steps;
+
+ while (bitIndex < bitEndIndex) {
+ bitIndex++;
+ uint32 pixPerStep = pixPerStepInit;
+ do {
+ uint32 x = (rnd - 1) >> vShift;
+ uint32 y = (rnd - 1) & hMask;
+ byte mask = 0;
+
+ r.setWidth(MAX(1, t.xStepSize));
+ r.setHeight(t.yStepSize);
+
+ if (x < w && y < h) {
+ if (t.xStepSize >= 1) {
+ x = x * t.xStepSize;
+ y = y * t.yStepSize;
+
+ if (x < realw && y < realh) {
+ x += clipRect.left;
+ y += clipRect.top;
+ r.moveTo(x, y);
+ r.clip(clipRect);
+
+ if (!r.isEmpty())
+ _composeSurface->copyRectToSurface(*nextFrame, x, y, r);
+ }
+ } else {
+ mask = pixmask[x % -t.xStepSize];
+ x = x / -t.xStepSize;
- r.setWidth(MAX(1, t.xStepSize));
- r.setHeight(t.yStepSize);
-
- if (x < w && y < h) {
- if (t.xStepSize >= 1) {
- x = x * t.xStepSize;
- y = y * t.yStepSize;
-
- if (x < realw && y < realh) {
x += clipRect.left;
y += clipRect.top;
- r.moveTo(x, y);
- r.clip(clipRect);
-
- if (!r.isEmpty())
- _composeSurface->copyRectToSurface(*nextFrame, x, y, r);
- }
- } else {
- mask = pixmask[x % -t.xStepSize];
- x = x / -t.xStepSize;
- x += clipRect.left;
- y += clipRect.top;
+ byte *dst = (byte *)_composeSurface->getBasePtr(x, y);
+ byte *src = (byte *)nextFrame->getBasePtr(x, y);
- byte *dst = (byte *)_composeSurface->getBasePtr(x, y);
- byte *src = (byte *)nextFrame->getBasePtr(x, y);
-
- *dst = ((*dst & ~mask) | (*src & mask)) & 0xff;
+ *dst = ((*dst & ~mask) | (*src & mask)) & 0xff;
+ }
}
- }
- rnd = (rnd & 1) ? (rnd >> 1) ^ seed : rnd >> 1;
+ rnd = (rnd & 1) ? (rnd >> 1) ^ seed : rnd >> 1;
- if (pixPerStep > 0) {
- if (--pixPerStep == 0) {
- break;
+ if (pixPerStep > 0) {
+ if (--pixPerStep == 0) {
+ break;
+ }
}
- }
- } while (rnd != seed);
-
+ } while (rnd != seed);
+ }
stepTransition(t, i);
g_lingo->executePerFrameHook(t.frame, i + 1);
@@ -1191,6 +1190,9 @@ void Window::initTransParams(TransParams &t, Common::Rect &clipRect) {
break;
case kTransDirDissolve:
+ if (t.type == kTransDissolvePixelsFast ||
+ t.type == kTransDissolveBitsFast)
+ t.duration = 250; // Smallest possible delay
t.steps = MIN<int>(MAX_STEPS(t.duration), 64);
t.stepDuration = t.duration / t.steps;
break;
Commit: e750f05fe4086d41eeb830be4185c77e4534ce23
https://github.com/scummvm/scummvm/commit/e750f05fe4086d41eeb830be4185c77e4534ce23
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Don't erase _composeSurface after movie change
Fixes the scene transitions in the Spaceship Warlock trailer.
Changed paths:
engines/director/window.cpp
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index bc7a864d6ca..f4b54ac9e56 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -203,7 +203,6 @@ Datum Window::getStageRect() {
void Window::reset() {
resize(_composeSurface->w, _composeSurface->h, true);
- _composeSurface->clear(_stageColor);
_contentIsDirty = true;
}
Commit: c7efa104937196f0592865de05b7fb92adda8c4b
https://github.com/scummvm/scummvm/commit/c7efa104937196f0592865de05b7fb92adda8c4b
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Fix loading defaultPalette from config block
Fixes regression introduced in e4f1471aa9bb384650bdc0d598f93ab9b3f97ccc
Changed paths:
engines/director/cast.cpp
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 6164010bfd6..f3bebe944bb 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -424,6 +424,8 @@ bool Cast::loadConfig() {
if (check != checksum)
warning("BUILDBOT: The checksum for this VWCF resource is incorrect. Got %04x, but expected %04x", check, checksum);
+ /* int16 field30 = */ stream->readSint16();
+
_defaultPalette = stream->readSint16();
// In this header value, the first builtin palette starts at 0 and
// continues down into negative numbers.
Commit: 9e17e5aa8506adf39d15ffc27a7dafdb8cd46cbf
https://github.com/scummvm/scummvm/commit/9e17e5aa8506adf39d15ffc27a7dafdb8cd46cbf
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Plug memory leak
Changed paths:
engines/director/archive.cpp
diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index 7adcfadc3cc..6aa8c182643 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -316,9 +316,11 @@ void MacArchive::readTags() {
for (uint32 j = 0; j < idArray.size(); j++) {
// Avoid assigning invalid entries to _types, because other
// functions will assume they exist and are valid if listed.
- if (_resFork->getResource(tagArray[i], idArray[j]) == nullptr) {
+ Common::SeekableReadStream *readStream = _resFork->getResource(tagArray[i], idArray[j]);
+ if (readStream == nullptr) {
continue;
}
+ delete readStream;
Resource &res = resMap[idArray[j]];
Commit: af0dd7abe165d8b896f7bbd10a623b06bad2ec90
https://github.com/scummvm/scummvm/commit/af0dd7abe165d8b896f7bbd10a623b06bad2ec90
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Pass mutable reference to Cast::loadPaletteData()
Fixes regression introduced in 411395565bc2405204ed4f44768deb08adbe5561
Changed paths:
engines/director/cast.cpp
engines/director/cast.h
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index f3bebe944bb..22e2a295e56 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -624,7 +624,7 @@ void Cast::loadStxtData(int key, TextCastMember *member) {
}
}
-void Cast::loadPaletteData(PaletteCastMember *member, Common::HashMap<int, PaletteV4>::iterator p) {
+void Cast::loadPaletteData(PaletteCastMember *member, Common::HashMap<int, PaletteV4>::iterator &p) {
// TODO: Verify how palettes work in >D4 versions
if (_version >= kFileVer400 && _version < kFileVer500 && member->_children.size() == 1) {
member->_palette = g_director->getPalette(member->_children[0].index);
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 0185e950681..ba5db9b3b65 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -95,7 +95,7 @@ public:
void loadCastMemberData();
void loadStxtData(int key, TextCastMember *member);
- void loadPaletteData(PaletteCastMember *member, Common::HashMap<int, PaletteV4>::iterator p);
+ void loadPaletteData(PaletteCastMember *member, Common::HashMap<int, PaletteV4>::iterator &p);
void loadFilmLoopData(FilmLoopCastMember *member);
void loadBitmapData(int key, BitmapCastMember *bitmapCast);
void loadSoundData(int key, SoundCastMember *soundCast);
Commit: 533dd7c78f4dd536ffa6c25298a426ef4aea0636
https://github.com/scummvm/scummvm/commit/533dd7c78f4dd536ffa6c25298a426ef4aea0636
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Fix searching for files in subdirectories
Fixes regression introduced in 0c09bba0f61d3a435112c517c9ff7b1054bdf07e
Fixes resource detection in Total Distortion.
Changed paths:
engines/director/util.cpp
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index 55126c28127..632acebac8b 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -427,9 +427,9 @@ bool testPath(Common::String &path, bool directory) {
// for each element in the path, choose the first FSNode
// with a case-insensitive matcing name
if (i->getName().equalsIgnoreCase(token)) {
- // If this is a directory, it's not a valid candidate
+ // If this the final path component, check if we're allowed to match with a directory
node = Common::FSNode(*i);
- if (node.isDirectory()) {
+ if (directory_list.empty() && !directory && node.isDirectory()) {
continue;
}
Commit: cb0455e34d9db59bd4d6802d7679e94ad2f381a9
https://github.com/scummvm/scummvm/commit/cb0455e34d9db59bd4d6802d7679e94ad2f381a9
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Fix audio loop use-after-free
Changed paths:
engines/director/sound.cpp
diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index 2f66eb95ff2..51d5d481927 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -106,6 +106,8 @@ void DirectorSound::playStream(Audio::AudioStream &stream, uint8 soundChannel) {
return;
cancelFade(soundChannel);
+ if (_channels[soundChannel - 1].loopPtr)
+ _channels[soundChannel - 1].loopPtr = nullptr;
_mixer->stopHandle(_channels[soundChannel - 1].handle);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_channels[soundChannel - 1].handle, &stream, -1, getChannelVolume(soundChannel));
}
Commit: e460102c77bea146b126c8d552688595101357fa
https://github.com/scummvm/scummvm/commit/e460102c77bea146b126c8d552688595101357fa
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Simplify D3 palette-loading code
Fixes Invictus logo animation in Alice: An Interactive Museum.
Changed paths:
engines/director/frame.cpp
engines/director/frame.h
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 1421e4101a8..2304945f9de 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -153,57 +153,31 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
if (_vm->getPlatform() == Common::kPlatformWindows) {
_sound2 = CastMemberID(stream->readUint16(), 0);
_soundType2 = stream->readByte();
- }
-
- // palette
- if (_vm->getPlatform() == Common::kPlatformWindows) {
- _palette.paletteId = stream->readUint16();
- // loop points for color cycling
- _palette.firstColor = g_director->transformColor(stream->readByte() ^ 0x80);
- _palette.lastColor = g_director->transformColor(stream->readByte() ^ 0x80);
- _palette.flags = stream->readByte();
- _palette.colorCycling = (_palette.flags & 0x80) != 0;
- _palette.normal = (_palette.flags & 0x60) == 0x00;
- _palette.fadeToBlack = (_palette.flags & 0x60) == 0x60;
- _palette.fadeToWhite = (_palette.flags & 0x60) == 0x40;
- _palette.autoReverse = (_palette.flags & 0x10) != 0;
- _palette.overTime = (_palette.flags & 0x04) != 0;
- _palette.speed = stream->readByte();
- _palette.frameCount = stream->readUint16();
- _palette.cycleCount = stream->readUint16();
-
- stream->read(unk, 6);
-
- debugC(8, kDebugLoading, "Frame::readChannels(): STUB: unk1: %02x %02x %02x %02x %02x %02x", unk[0],
- unk[1], unk[2], unk[3], unk[4], unk[5]);
} else {
stream->read(unk, 3);
debugC(8, kDebugLoading, "Frame::readChannels(): STUB: unk1: %02x %02x %02x", unk[0], unk[1], unk[2]);
-
- _palette.paletteId = stream->readSint16();
- // loop points for color cycling
- _palette.firstColor = g_director->transformColor(stream->readByte() ^ 0x80);
- _palette.lastColor = g_director->transformColor(stream->readByte() ^ 0x80);
- _palette.flags = stream->readByte();
- _palette.colorCycling = (_palette.flags & 0x80) != 0;
- _palette.normal = (_palette.flags & 0x60) == 0x00;
- _palette.fadeToBlack = (_palette.flags & 0x60) == 0x60;
- _palette.fadeToWhite = (_palette.flags & 0x60) == 0x40;
- _palette.autoReverse = (_palette.flags & 0x10) != 0;
- _palette.overTime = (_palette.flags & 0x04) != 0;
- _palette.cycleCount = stream->readByte();
- _palette.speed = stream->readByte();
- _palette.frameCount = stream->readByte();
- _palette.cycleLength = stream->readByte();
-
- stream->read(unk, 4);
- debugC(8, kDebugLoading, "Frame::readChannels(): STUB: unk2: %02x %02x %02x %02x", unk[0], unk[1], unk[2], unk[3]);
}
- if (_vm->getPlatform() == Common::kPlatformMacintosh || _vm->getPlatform() == Common::kPlatformMacintoshII) {
- stream->read(unk, 3);
- debugC(8, kDebugLoading, "Frame::readChannels(): STUB: unk3: %02x %02x %02x", unk[0], unk[1], unk[2]);
- }
+ // palette
+ _palette.paletteId = stream->readUint16();
+ // loop points for color cycling
+ _palette.firstColor = g_director->transformColor(stream->readByte() ^ 0x80);
+ _palette.lastColor = g_director->transformColor(stream->readByte() ^ 0x80);
+ _palette.flags = stream->readByte();
+ _palette.colorCycling = (_palette.flags & 0x80) != 0;
+ _palette.normal = (_palette.flags & 0x60) == 0x00;
+ _palette.fadeToBlack = (_palette.flags & 0x60) == 0x60;
+ _palette.fadeToWhite = (_palette.flags & 0x60) == 0x40;
+ _palette.autoReverse = (_palette.flags & 0x10) != 0;
+ _palette.overTime = (_palette.flags & 0x04) != 0;
+ _palette.speed = stream->readByte();
+ _palette.frameCount = stream->readUint16();
+ _palette.cycleCount = stream->readUint16();
+
+ stream->read(unk, 6);
+
+ debugC(8, kDebugLoading, "Frame::readChannels(): STUB: unk1: %02x %02x %02x %02x %02x %02x", unk[0],
+ unk[1], unk[2], unk[3], unk[4], unk[5]);
} else if (version >= kFileVer400 && version < kFileVer500) {
// Sound/Tempo/Transition
int unk1 = stream->readByte();
@@ -292,9 +266,9 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
debugC(4, kDebugLoading, "TMPO: tempo: %d, skipFrameFlag: %d, blend: %d",
_tempo, _skipFrameFlag, _blend);
if (_palette.paletteId) {
- debugC(4, kDebugLoading, "PAL: paletteId: %d, firstColor: %d, lastColor: %d, flags: %d, cycleCount: %d, cycleLength: %d, speed: %d, frameCount: %d, fade: %d, delay: %d, style: %d",
+ debugC(4, kDebugLoading, "PAL: paletteId: %d, firstColor: %d, lastColor: %d, flags: %d, cycleCount: %d, speed: %d, frameCount: %d, fade: %d, delay: %d, style: %d",
_palette.paletteId, _palette.firstColor, _palette.lastColor, _palette.flags,
- _palette.cycleCount, _palette.cycleLength, _palette.speed, _palette.frameCount,
+ _palette.cycleCount, _palette.speed, _palette.frameCount,
_palette.fade, _palette.delay, _palette.style);
} else {
debugC(4, kDebugLoading, "PAL: paletteId: 000");
diff --git a/engines/director/frame.h b/engines/director/frame.h
index 7fda871da23..c4d262744f6 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -60,7 +60,6 @@ struct PaletteInfo {
byte speed;
uint16 frameCount;
uint16 cycleCount;
- uint16 cycleLength;
byte fade;
byte delay;
byte style;
@@ -73,7 +72,7 @@ struct PaletteInfo {
normal = false; fadeToWhite = false;
fadeToBlack = false; autoReverse = false;
overTime = false; speed = 0;
- frameCount = cycleCount = cycleLength = 0;
+ frameCount = cycleCount = 0;
fade = delay = style = colorCode = 0;
}
};
Commit: 3a096e60c3223b5891ea6655c3dd3dac2692dcb7
https://github.com/scummvm/scummvm/commit/3a096e60c3223b5891ea6655c3dd3dac2692dcb7
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Add version function to debugger
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/detection.cpp
engines/director/detection.h
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 7aebfe6e2b5..c74ecdc79ac 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -19,12 +19,15 @@
*
*/
+#include "common/language.h"
+#include "director/detection.h"
#include "director/director.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-code.h"
#include "director/lingo/lingo-object.h"
#include "director/lingo/lingo-codegen.h"
#include "director/debugger.h"
+#include "game.h"
namespace Director {
@@ -34,7 +37,9 @@ Debugger *g_debugger;
Debugger::Debugger(): GUI::Debugger() {
g_debugger = this;
- registerCmd("lingo", WRAP_METHOD(Debugger, cmd_lingo));
+ registerCmd("help", WRAP_METHOD(Debugger, cmdHelp));
+ registerCmd("version", WRAP_METHOD(Debugger, cmdVersion));
+ registerCmd("repl", WRAP_METHOD(Debugger, cmdRepl));
}
Debugger::~Debugger() {
@@ -42,16 +47,68 @@ Debugger::~Debugger() {
_out.close();
}
-bool Debugger::cmd_lingo(int argc, const char **argv) {
- if (argc == 2 && !strcmp(argv[1], "on")) {
- registerDefaultCmd(WRAP_DEFAULTCOMMAND(Debugger, lingoCommandProcessor));
- debugPrintf(PROMPT);
- }
+bool Debugger::cmdHelp(int argc, const char **argv) {
+ debugPrintf("\n");
+ debugPrintf("Debug flags\n");
+ debugPrintf("-----------\n");
+ debugPrintf("debugflag_list - Lists the available debug flags and their status\n");
+ debugPrintf("debugflag_enable - Enables a debug flag\n");
+ debugPrintf("debugflag_disable - Disables a debug flag\n");
+ debugPrintf("debuglevel - Shows or sets debug level\n");
+ debugPrintf("\n");
+ debugPrintf("Commands\n");
+ debugPrintf("--------\n");
+ debugPrintf("Player:\n");
+ debugPrintf(" version - Shows the Director version\n");
+ //debugPrintf(" movie [moviePath] - Get or sets the current movie\n");
+ //debugPrintf(" movieinfo - Show information for the current movie\n");
+ //debugPrintf(" scoreframe [frameNum] - Gets or sets the current score frame\n");
+ //debugPrintf(" channels [frameNum] - Shows channel information for a score frame\n");
+ //debugPrintf(" cast - Shows the cast list for the current movie\n");
+ debugPrintf("\n");
+ debugPrintf("Lingo execution:\n");
+ //debugPrintf(" eval [statement] - Evaluates a single Lingo statement\n");
+ debugPrintf(" repl - Switches to a REPL interface for evaluating Lingo code\n");
+ //debugPrintf(" backtrace / bt - Prints a backtrace of all stack frames\n");
+ //debugPrintf(" disasm [function] - Lists the bytecode disassembly for a script function\n");
+ //debugPrintf(" stack / st - Lists the elements on the stack\n");
+ //debugPrintf(" frame / f - Prints the current script frame\n");
+ //debugPrintf(" vars - Lists all of the variables available in the current script frame\n");
+ //debugPrintf(" step / s [n] - Steps forward one or more operations\n");
+ //debugPrintf(" next / n [n] - Steps forward one or more operations, skips over calls\n");
+ //debugPrintf(" finish / fin - Steps until the current stack frame returns/n");
+ debugPrintf("\n");
+ debugPrintf("Breakpoints:\n");
+ debugPrintf("\n");
+ //debugPrintf(" bpset [funcname:n] - Creates a breakpoint on a Lingo script/n");
+ //debugPrintf(" bpdel [n] - Deletes a specific breakpoint /n");
+ return true;
+}
+
+bool Debugger::cmdVersion(int argc, const char **argv) {
+ debugPrintf("Director version: %d\n", g_director->getVersion());
+ debugPrintf("Director platform: %s\n", Common::getPlatformCode(g_director->getPlatform()));
+ debugPrintf("Game ID: %s\n", g_director->getGameId());
+ debugPrintf("Game name: %s\n", getDescriptionFromGameId(g_director->getGameId()));
+ debugPrintf("Game variant: %s\n", g_director->getExtra());
+ debugPrintf("Language: %s\n", Common::getLanguageCode(g_director->getLanguage()));
+ debugPrintf("Expected Director version: %d\n", g_director->getDescriptionVersion());
+ debugPrintf("Executable name: %s\n", g_director->getEXEName().c_str());
+ debugPrintf("Startup file name: %s\n", g_director->_gameDescription->desc.filesDescriptions[0].fileName);
+ debugPrintf("Startup file MD5: %s\n", g_director->_gameDescription->desc.filesDescriptions[0].md5);
+ debugPrintf("\n");
+ return true;
+}
+
+bool Debugger::cmdRepl(int argc, const char **argv) {
+ debugPrintf("Switching to Lingo REPL mode, type 'exit' to return to the debug console.\n");
+ registerDefaultCmd(WRAP_DEFAULTCOMMAND(Debugger, lingoCommandProcessor));
+ debugPrintf(PROMPT);
return true;
}
bool Debugger::lingoCommandProcessor(const char *inputOrig) {
- if (!strcmp(inputOrig, "lingo off")) {
+ if (!strcmp(inputOrig, "exit")) {
registerDefaultCmd(nullptr);
return true;
}
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index b61fc737253..c469ed57b9b 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -34,7 +34,10 @@ public:
void debugLogFile(Common::String logs, bool prompt);
private:
- bool cmd_lingo(int argc, const char **argv);
+ bool cmdHelp(int argc, const char **argv);
+
+ bool cmdVersion(int argc, const char **argv);
+ bool cmdRepl(int argc, const char **argv);
bool lingoCommandProcessor(const char *inputOrig);
diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp
index 8eac0465b35..697e490e6aa 100644
--- a/engines/director/detection.cpp
+++ b/engines/director/detection.cpp
@@ -70,6 +70,17 @@ static const DebugChannelDef debugFlagList[] = {
DEBUG_CHANNEL_END
};
+namespace Director {
+
+const char *getDescriptionFromGameId(const char *gameId) {
+ const PlainGameDescriptor *g = findPlainGameDescriptor(gameId, directorGames);
+ if (!g)
+ return nullptr;
+ return g->description;
+}
+
+} // End of namespace Director
+
class DirectorMetaEngineDetection : public AdvancedMetaEngineDetection {
private:
Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _customTarget;
diff --git a/engines/director/detection.h b/engines/director/detection.h
index 99b67cc6bb3..1b558964ee2 100644
--- a/engines/director/detection.h
+++ b/engines/director/detection.h
@@ -41,6 +41,8 @@ struct DirectorGameDescription {
extern const char *directoryGlobs[];
+const char *getDescriptionFromGameId(const char *gameId);
+
} // End of namespace Director
#endif // DIRECTOR_DETECTION_H
Commit: 05c811922048b88fd37b11637ae4a5a6b4968248
https://github.com/scummvm/scummvm/commit/05c811922048b88fd37b11637ae4a5a6b4968248
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Start implementing Lingo debugger console
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index c74ecdc79ac..9d723685f9c 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -38,8 +38,15 @@ Debugger *g_debugger;
Debugger::Debugger(): GUI::Debugger() {
g_debugger = this;
registerCmd("help", WRAP_METHOD(Debugger, cmdHelp));
+
registerCmd("version", WRAP_METHOD(Debugger, cmdVersion));
+
registerCmd("repl", WRAP_METHOD(Debugger, cmdRepl));
+ registerCmd("stack", WRAP_METHOD(Debugger, cmdStack));
+ registerCmd("st", WRAP_METHOD(Debugger, cmdStack));
+ registerCmd("backtrace", WRAP_METHOD(Debugger, cmdBacktrace));
+ registerCmd("bt", WRAP_METHOD(Debugger, cmdBacktrace));
+ registerCmd("vars", WRAP_METHOD(Debugger, cmdVars));
}
Debugger::~Debugger() {
@@ -69,11 +76,11 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf("Lingo execution:\n");
//debugPrintf(" eval [statement] - Evaluates a single Lingo statement\n");
debugPrintf(" repl - Switches to a REPL interface for evaluating Lingo code\n");
- //debugPrintf(" backtrace / bt - Prints a backtrace of all stack frames\n");
+ debugPrintf(" backtrace / bt - Prints a backtrace of all stack frames\n");
//debugPrintf(" disasm [function] - Lists the bytecode disassembly for a script function\n");
- //debugPrintf(" stack / st - Lists the elements on the stack\n");
+ debugPrintf(" stack / st - Lists the elements on the stack\n");
//debugPrintf(" frame / f - Prints the current script frame\n");
- //debugPrintf(" vars - Lists all of the variables available in the current script frame\n");
+ debugPrintf(" vars - Lists all of the variables available in the current script frame\n");
//debugPrintf(" step / s [n] - Steps forward one or more operations\n");
//debugPrintf(" next / n [n] - Steps forward one or more operations, skips over calls\n");
//debugPrintf(" finish / fin - Steps until the current stack frame returns/n");
@@ -107,6 +114,22 @@ bool Debugger::cmdRepl(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdStack(int argc, const char **argv) {
+ debugPrintf("%s\n", g_director->getLingo()->formatStack().c_str());
+ debugPrintf("\n");
+ return true;
+}
+
+bool Debugger::cmdBacktrace(int argc, const char **argv) {
+ debugPrintf("%s\n", g_director->getLingo()->formatCallStack(g_director->getLingo()->_pc).c_str());
+ return true;
+}
+
+bool Debugger::cmdVars(int argc, const char **argv) {
+ debugPrintf("%s\n", g_director->getLingo()->formatAllVars().c_str());
+ return true;
+}
+
bool Debugger::lingoCommandProcessor(const char *inputOrig) {
if (!strcmp(inputOrig, "exit")) {
registerDefaultCmd(nullptr);
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index c469ed57b9b..864b5ee431e 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -38,6 +38,9 @@ private:
bool cmdVersion(int argc, const char **argv);
bool cmdRepl(int argc, const char **argv);
+ bool cmdBacktrace(int argc, const char **argv);
+ bool cmdStack(int argc, const char **argv);
+ bool cmdVars(int argc, const char **argv);
bool lingoCommandProcessor(const char *inputOrig);
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index cadb91a09f0..797a44e8a52 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -311,23 +311,31 @@ void LingoArchive::replaceCode(const Common::U32String &code, ScriptType type, u
addCode(code, type, id, scriptName);
}
-void Lingo::printStack(const char *s, uint pc) {
- Common::String stack(s);
+Common::String Lingo::formatStack() {
+ Common::String stack;
for (uint i = 0; i < _stack.size(); i++) {
Datum d = _stack[i];
stack += Common::String::format("<%s> ", d.asString(true).c_str());
}
+ return stack;
+}
+
+void Lingo::printStack(const char *s, uint pc) {
+ Common::String stack(s);
+ stack += formatStack();
+
debugC(5, kDebugLingoExec, "[%3d]: %s", pc, stack.c_str());
}
-void Lingo::printCallStack(uint pc) {
+Common::String Lingo::formatCallStack(uint pc) {
+ Common::String result;
Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
if (callstack.size() == 0) {
- debugC(2, kDebugLingoExec, "\nEnd of execution");
- return;
+ result += Common::String("End of execution\n");
+ return result;
}
- debugC(2, kDebugLingoExec, "\nCall stack:");
+ result += Common::String("Call stack:\n");
for (int i = 0; i < (int)callstack.size(); i++) {
CFrame *frame = callstack[i];
uint framePc = pc;
@@ -335,16 +343,21 @@ void Lingo::printCallStack(uint pc) {
framePc = callstack[i + 1]->retPC;
if (frame->sp.type != VOIDSYM) {
- debugC(2, kDebugLingoExec, "#%d %s:%d", i + 1,
+ result += Common::String::format("#%d %s:%d\n", i + 1,
callstack[i]->sp.name->c_str(),
framePc
);
} else {
- debugC(2, kDebugLingoExec, "#%d [unknown]:%d", i + 1,
+ result += Common::String::format("#%d [unknown]:%d\n", i + 1,
framePc
);
}
}
+ return result;
+}
+
+void Lingo::printCallStack(uint pc) {
+ debugC(2, kDebugLingoExec, "\n%s", formatCallStack(pc).c_str());
}
Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
@@ -1225,31 +1238,38 @@ void Lingo::cleanLocalVars() {
g_lingo->_localvars = nullptr;
}
-void Lingo::printAllVars() {
- debugN(" Local vars: ");
+Common::String Lingo::formatAllVars() {
+ Common::String result;
+
+ result += Common::String(" Local vars: ");
if (_localvars) {
for (DatumHash::iterator i = _localvars->begin(); i != _localvars->end(); ++i) {
- debugN("%s, ", (*i)._key.c_str());
+ result += Common::String::format("%s, ", (*i)._key.c_str());
}
} else {
- debugN("(no local vars)");
+ result += Common::String("(no local vars)");
}
- debugN("\n");
+ result += Common::String("\n");
if (_currentMe.type == OBJECT && _currentMe.u.obj->getObjType() & (kFactoryObj | kScriptObj)) {
ScriptContext *script = static_cast<ScriptContext *>(_currentMe.u.obj);
- debugN(" Instance/property vars: ");
+ result += Common::String(" Instance/property vars: ");
for (DatumHash::iterator i = script->_properties.begin(); i != script->_properties.end(); ++i) {
- debugN("%s, ", (*i)._key.c_str());
+ result += Common::String("%s, ", (*i)._key.c_str());
}
- debugN("\n");
+ result += Common::String("\n");
}
- debugN(" Global vars: ");
+ result += Common::String(" Global vars: ");
for (DatumHash::iterator i = _globalvars.begin(); i != _globalvars.end(); ++i) {
- debugN("%s, ", (*i)._key.c_str());
+ result += Common::String::format("%s, ", (*i)._key.c_str());
}
- debugN("\n");
+ result += Common::String("\n");
+ return result;
+}
+
+void Lingo::printAllVars() {
+ debugN("%s", formatAllVars().c_str());
}
int Lingo::getInt(uint pc) {
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 158654caad3..847c180e850 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -301,7 +301,9 @@ public:
void executeHandler(const Common::String &name);
void executeScript(ScriptType type, CastMemberID id);
+ Common::String formatStack();
void printStack(const char *s, uint pc);
+ Common::String formatCallStack(uint pc);
void printCallStack(uint pc);
Common::String decodeInstruction(ScriptData *sd, uint pc, uint *newPC = NULL);
@@ -354,6 +356,7 @@ public:
int getAlignedType(const Datum &d1, const Datum &d2, bool numsOnly);
+ Common::String formatAllVars();
void printAllVars();
inst readInst() { return getInst(_pc++); }
Commit: 6876849f976a2cfc01a5f5e83896b97f30cfc856
https://github.com/scummvm/scummvm/commit/6876849f976a2cfc01a5f5e83896b97f30cfc856
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Add step, finish and next commands for debugger
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/lingo/lingo-code.cpp
engines/director/lingo/lingo.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 9d723685f9c..628b59ea0d9 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -47,6 +47,19 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("backtrace", WRAP_METHOD(Debugger, cmdBacktrace));
registerCmd("bt", WRAP_METHOD(Debugger, cmdBacktrace));
registerCmd("vars", WRAP_METHOD(Debugger, cmdVars));
+ registerCmd("step", WRAP_METHOD(Debugger, cmdStep));
+ registerCmd("s", WRAP_METHOD(Debugger, cmdStep));
+ registerCmd("next", WRAP_METHOD(Debugger, cmdNext));
+ registerCmd("n", WRAP_METHOD(Debugger, cmdNext));
+ registerCmd("finish", WRAP_METHOD(Debugger, cmdFinish));
+ registerCmd("fin", WRAP_METHOD(Debugger, cmdFinish));
+
+ _step = false;
+ _stepCounter = 0;
+ _finish = false;
+ _finishCounter = 0;
+ _next = false;
+ _nextCounter = 0;
}
Debugger::~Debugger() {
@@ -81,9 +94,9 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" stack / st - Lists the elements on the stack\n");
//debugPrintf(" frame / f - Prints the current script frame\n");
debugPrintf(" vars - Lists all of the variables available in the current script frame\n");
- //debugPrintf(" step / s [n] - Steps forward one or more operations\n");
- //debugPrintf(" next / n [n] - Steps forward one or more operations, skips over calls\n");
- //debugPrintf(" finish / fin - Steps until the current stack frame returns/n");
+ debugPrintf(" step / s [n] - Steps forward one or more operations\n");
+ debugPrintf(" next / n [n] - Steps forward one or more operations, skips over calls\n");
+ debugPrintf(" finish / fin - Steps until the current stack frame returns/n");
debugPrintf("\n");
debugPrintf("Breakpoints:\n");
debugPrintf("\n");
@@ -130,6 +143,33 @@ bool Debugger::cmdVars(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdStep(int argc, const char **argv) {
+ _step = true;
+ if (argc == 2 && atoi(argv[1]) > 0) {
+ _stepCounter = atoi(argv[1]);
+ } else {
+ _stepCounter = 1;
+ }
+ return cmdExit(0, nullptr);
+}
+
+bool Debugger::cmdNext(int argc, const char **argv) {
+ _step = true;
+ _next = true;
+ if (argc == 2 && atoi(argv[1]) > 0) {
+ _stepCounter = atoi(argv[1]);
+ } else {
+ _stepCounter = 1;
+ }
+ return cmdExit(0, nullptr);
+}
+
+bool Debugger::cmdFinish(int argc, const char **argv) {
+ _finish = true;
+ _finishCounter = 1;
+ return cmdExit(0, nullptr);
+}
+
bool Debugger::lingoCommandProcessor(const char *inputOrig) {
if (!strcmp(inputOrig, "exit")) {
registerDefaultCmd(nullptr);
@@ -146,6 +186,38 @@ bool Debugger::lingoCommandProcessor(const char *inputOrig) {
return true;
}
+void Debugger::stepHook() {
+ if (_step && _nextCounter == 0) {
+ _stepCounter--;
+ if (_stepCounter == 0) {
+ _step = false;
+ _next = false;
+ attach();
+ g_system->updateScreen();
+ }
+ }
+ if (_finish && _finishCounter == 0) {
+ _finish = false;
+ attach();
+ g_system->updateScreen();
+ }
+}
+
+void Debugger::pushContextHook() {
+ if (_next)
+ _nextCounter++;
+ if (_finish)
+ _finishCounter++;
+}
+
+void Debugger::popContextHook() {
+ if (_next && _nextCounter > 0)
+ _nextCounter--;
+ if (_finish)
+ _finishCounter--;
+}
+
+
void Debugger::debugLogFile(Common::String logs, bool prompt) {
if (prompt)
debugPrintf("-- %s", logs.c_str());
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index 864b5ee431e..27a7c75164f 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -32,6 +32,9 @@ public:
Debugger();
~Debugger();
void debugLogFile(Common::String logs, bool prompt);
+ void stepHook();
+ void pushContextHook();
+ void popContextHook();
private:
bool cmdHelp(int argc, const char **argv);
@@ -41,11 +44,22 @@ private:
bool cmdBacktrace(int argc, const char **argv);
bool cmdStack(int argc, const char **argv);
bool cmdVars(int argc, const char **argv);
+ bool cmdStep(int argc, const char **argv);
+ bool cmdNext(int argc, const char **argv);
+ bool cmdFinish(int argc, const char **argv);
bool lingoCommandProcessor(const char *inputOrig);
+
Common::DumpFile _out;
Common::String _outName;
+
+ bool _step;
+ int _stepCounter;
+ bool _finish;
+ int _finishCounter;
+ bool _next;
+ int _nextCounter;
};
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index f6049704422..307f8139ab7 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -240,6 +240,7 @@ void Lingo::saveStateToWindow() {
}
void Lingo::pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRetVal) {
+ g_debugger->pushContextHook();
Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
debugC(5, kDebugLingoExec, "Pushing frame %d", callstack.size() + 1);
@@ -373,6 +374,8 @@ void Lingo::popContext(bool aborting) {
}
delete fp;
+
+ g_debugger->popContextHook();
}
bool Lingo::hasFrozenContext() {
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 797a44e8a52..f388378346a 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -459,6 +459,7 @@ void Lingo::execute() {
Common::String instr = decodeInstruction(_currentScript, _pc);
uint current = _pc;
+
if (debugChannelSet(5, kDebugLingoExec))
printStack("Stack before: ", current);
@@ -471,6 +472,8 @@ void Lingo::execute() {
debugC(3, kDebugLingoExec, "[%3d]: %s", current, instr.c_str());
+ g_debugger->stepHook();
+
_pc++;
(*((*_currentScript)[_pc - 1]))();
@@ -502,6 +505,7 @@ void Lingo::execute() {
if (_freezeContext) {
debugC(1, kDebugLingoExec, "Lingo::execute(): Context is frozen, pausing execution");
}
+ g_debugger->stepHook();
}
void Lingo::executeScript(ScriptType type, CastMemberID id) {
Commit: c8ccf0e68827a66372afe853c2e4cf8ee7fa2d53
https://github.com/scummvm/scummvm/commit/c8ccf0e68827a66372afe853c2e4cf8ee7fa2d53
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Add scriptframe command for debugger
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 628b59ea0d9..7dbde087dbd 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -44,6 +44,8 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("repl", WRAP_METHOD(Debugger, cmdRepl));
registerCmd("stack", WRAP_METHOD(Debugger, cmdStack));
registerCmd("st", WRAP_METHOD(Debugger, cmdStack));
+ registerCmd("scriptframe", WRAP_METHOD(Debugger, cmdScriptFrame));
+ registerCmd("sf", WRAP_METHOD(Debugger, cmdScriptFrame));
registerCmd("backtrace", WRAP_METHOD(Debugger, cmdBacktrace));
registerCmd("bt", WRAP_METHOD(Debugger, cmdBacktrace));
registerCmd("vars", WRAP_METHOD(Debugger, cmdVars));
@@ -92,7 +94,7 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" backtrace / bt - Prints a backtrace of all stack frames\n");
//debugPrintf(" disasm [function] - Lists the bytecode disassembly for a script function\n");
debugPrintf(" stack / st - Lists the elements on the stack\n");
- //debugPrintf(" frame / f - Prints the current script frame\n");
+ debugPrintf(" scriptframe / sf - Prints the current script frame\n");
debugPrintf(" vars - Lists all of the variables available in the current script frame\n");
debugPrintf(" step / s [n] - Steps forward one or more operations\n");
debugPrintf(" next / n [n] - Steps forward one or more operations, skips over calls\n");
@@ -133,6 +135,13 @@ bool Debugger::cmdStack(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdScriptFrame(int argc, const char **argv) {
+ Lingo *lingo = g_director->getLingo();
+ debugPrintf("%s\n", lingo->formatFrame().c_str());
+ debugPrintf("\n");
+ return true;
+}
+
bool Debugger::cmdBacktrace(int argc, const char **argv) {
debugPrintf("%s\n", g_director->getLingo()->formatCallStack(g_director->getLingo()->_pc).c_str());
return true;
@@ -192,12 +201,14 @@ void Debugger::stepHook() {
if (_stepCounter == 0) {
_step = false;
_next = false;
+ cmdScriptFrame(0, nullptr);
attach();
g_system->updateScreen();
}
}
if (_finish && _finishCounter == 0) {
_finish = false;
+ cmdScriptFrame(0, nullptr);
attach();
g_system->updateScreen();
}
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index 27a7c75164f..fa6f9fef183 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -43,6 +43,7 @@ private:
bool cmdRepl(int argc, const char **argv);
bool cmdBacktrace(int argc, const char **argv);
bool cmdStack(int argc, const char **argv);
+ bool cmdScriptFrame(int argc, const char **argv);
bool cmdVars(int argc, const char **argv);
bool cmdStep(int argc, const char **argv);
bool cmdNext(int argc, const char **argv);
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index f388378346a..7c05ba5641a 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -337,18 +337,18 @@ Common::String Lingo::formatCallStack(uint pc) {
}
result += Common::String("Call stack:\n");
for (int i = 0; i < (int)callstack.size(); i++) {
- CFrame *frame = callstack[i];
+ CFrame *frame = callstack[callstack.size() - i - 1];
uint framePc = pc;
- if (i < (int)callstack.size() - 1)
- framePc = callstack[i + 1]->retPC;
+ if (i > 0)
+ framePc = callstack[callstack.size() - i]->retPC;
if (frame->sp.type != VOIDSYM) {
- result += Common::String::format("#%d %s:%d\n", i + 1,
- callstack[i]->sp.name->c_str(),
+ result += Common::String::format("#%d %s:%d\n", i,
+ frame->sp.name->c_str(),
framePc
);
} else {
- result += Common::String::format("#%d [unknown]:%d\n", i + 1,
+ result += Common::String::format("#%d [unknown]:%d\n", i,
framePc
);
}
@@ -360,6 +360,18 @@ void Lingo::printCallStack(uint pc) {
debugC(2, kDebugLingoExec, "\n%s", formatCallStack(pc).c_str());
}
+Common::String Lingo::formatFrame() {
+ Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
+ if (callstack.size() == 0) {
+ return Common::String("End of execution");
+ }
+ CFrame *frame = callstack[callstack.size() - 1];
+ const char *funcName = frame->sp.type == VOIDSYM ? "[unknown]" : frame->sp.name->c_str();
+ Common::String result = Common::String::format("%s:%d\n", funcName, _pc);
+ result += Common::String::format("[%3d]: %s", _pc, decodeInstruction(_currentScript, _pc).c_str());
+ return result;
+}
+
Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
Symbol sym;
Common::String res;
@@ -456,10 +468,8 @@ void Lingo::execute() {
break;
}
- Common::String instr = decodeInstruction(_currentScript, _pc);
uint current = _pc;
-
if (debugChannelSet(5, kDebugLingoExec))
printStack("Stack before: ", current);
@@ -470,7 +480,10 @@ void Lingo::execute() {
debug("me: %s", _currentMe.asString(true).c_str());
}
- debugC(3, kDebugLingoExec, "[%3d]: %s", current, instr.c_str());
+ if (debugChannelSet(3, kDebugLingoExec)) {
+ Common::String instr = decodeInstruction(_currentScript, _pc);
+ debugC(3, kDebugLingoExec, "[%3d]: %s", current, instr.c_str());
+ }
g_debugger->stepHook();
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 847c180e850..c81ad351fa8 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -305,6 +305,7 @@ public:
void printStack(const char *s, uint pc);
Common::String formatCallStack(uint pc);
void printCallStack(uint pc);
+ Common::String formatFrame();
Common::String decodeInstruction(ScriptData *sd, uint pc, uint *newPC = NULL);
void reloadBuiltIns();
Commit: b8155408f2b6cf8aa13e64b14273a3878456b8ce
https://github.com/scummvm/scummvm/commit/b8155408f2b6cf8aa13e64b14273a3878456b8ce
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Add warning for unhandled Datum::reset()
Changed paths:
engines/director/lingo/lingo.cpp
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 7c05ba5641a..0059326518b 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -741,6 +741,12 @@ void Datum::reset() {
#ifndef __COVERITY__
if (*refCount <= 0) {
switch (type) {
+ case VOID:
+ case INT:
+ case FLOAT:
+ case ARGC:
+ case ARGCNORET:
+ break;
case VARREF:
case GLOBALREF:
case LOCALREF:
@@ -777,6 +783,7 @@ void Datum::reset() {
delete u.menu;
break;
default:
+ warning("Datum::reset(): Unprocessed REF type %d", type);
break;
}
if (type != OBJECT) // object owns refCount
Commit: d3a293128524b5cfc1680c026f43dec4be3a3ddf
https://github.com/scummvm/scummvm/commit/d3a293128524b5cfc1680c026f43dec4be3a3ddf
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-12T15:52:18+02:00
Commit Message:
DIRECTOR: Tidy up debugger based on feedback
Changed paths:
engines/director/debugger.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 7dbde087dbd..ca6fc4dc564 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -27,7 +27,6 @@
#include "director/lingo/lingo-object.h"
#include "director/lingo/lingo-codegen.h"
#include "director/debugger.h"
-#include "game.h"
namespace Director {
@@ -98,12 +97,12 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" vars - Lists all of the variables available in the current script frame\n");
debugPrintf(" step / s [n] - Steps forward one or more operations\n");
debugPrintf(" next / n [n] - Steps forward one or more operations, skips over calls\n");
- debugPrintf(" finish / fin - Steps until the current stack frame returns/n");
+ debugPrintf(" finish / fin - Steps until the current stack frame returns\n");
debugPrintf("\n");
debugPrintf("Breakpoints:\n");
debugPrintf("\n");
- //debugPrintf(" bpset [funcname:n] - Creates a breakpoint on a Lingo script/n");
- //debugPrintf(" bpdel [n] - Deletes a specific breakpoint /n");
+ //debugPrintf(" bpset [funcname:n] - Creates a breakpoint on a Lingo script\n");
+ //debugPrintf(" bpdel [n] - Deletes a specific breakpoint \n");
return true;
}
@@ -123,14 +122,15 @@ bool Debugger::cmdVersion(int argc, const char **argv) {
}
bool Debugger::cmdRepl(int argc, const char **argv) {
- debugPrintf("Switching to Lingo REPL mode, type 'exit' to return to the debug console.\n");
+ debugPrintf("Switching to Lingo REPL mode, type 'lingo off' to return to the debug console.\n");
registerDefaultCmd(WRAP_DEFAULTCOMMAND(Debugger, lingoCommandProcessor));
debugPrintf(PROMPT);
return true;
}
bool Debugger::cmdStack(int argc, const char **argv) {
- debugPrintf("%s\n", g_director->getLingo()->formatStack().c_str());
+ Lingo *lingo = g_director->getLingo();
+ debugPrintf("%s\n", lingo->formatStack().c_str());
debugPrintf("\n");
return true;
}
@@ -143,12 +143,14 @@ bool Debugger::cmdScriptFrame(int argc, const char **argv) {
}
bool Debugger::cmdBacktrace(int argc, const char **argv) {
- debugPrintf("%s\n", g_director->getLingo()->formatCallStack(g_director->getLingo()->_pc).c_str());
+ Lingo *lingo = g_director->getLingo();
+ debugPrintf("%s\n", lingo->formatCallStack(lingo->_pc).c_str());
return true;
}
bool Debugger::cmdVars(int argc, const char **argv) {
- debugPrintf("%s\n", g_director->getLingo()->formatAllVars().c_str());
+ Lingo *lingo = g_director->getLingo();
+ debugPrintf("%s\n", lingo->formatAllVars().c_str());
return true;
}
@@ -180,7 +182,7 @@ bool Debugger::cmdFinish(int argc, const char **argv) {
}
bool Debugger::lingoCommandProcessor(const char *inputOrig) {
- if (!strcmp(inputOrig, "exit")) {
+ if (!strcmp(inputOrig, "lingo off")) {
registerDefaultCmd(nullptr);
return true;
}
@@ -228,7 +230,6 @@ void Debugger::popContextHook() {
_finishCounter--;
}
-
void Debugger::debugLogFile(Common::String logs, bool prompt) {
if (prompt)
debugPrintf("-- %s", logs.c_str());
More information about the Scummvm-git-logs
mailing list