[Scummvm-git-logs] scummvm master -> c7c5f28bdb2f393c1290bcac803cf9fc86ac8ed8
csnover
csnover at users.noreply.github.com
Sat Oct 7 05:57:32 CEST 2017
This automated email contains information about 23 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
5e2e6e9e8a COMMON: Switch to compile-time checking of invalid SortedArray calls
79dd02373c COMMON: Prevent implicit conversion of smart pointers to non-bools
f037d4df16 COMMON: Allow construction of Arrays of non-copyable members
5cffa3891f SCI32: Clean up GfxPalette32
0ac5d84062 SCI32: Clean up ScreenItem
ff3503abde SCI32: Clean up GfxTransitions32
9d05bf7920 SCI32: Clean up GfxCursor32
c413030be3 SCI32: Clean up Video32
f51b158f8c SCI32: Clean up GfxFrameout
93c8044f69 SCI32: Clean up Audio32
42180527c4 SCI32: Fix music volume not being restored after speech in Torin
a2c8674252 SCI32: Clean up GfxText32
1b42146955 SCI32: Clean up GfxRemap32
31e1d0932c SCI32: Clean up Plane
4521e9774a SCI32: Clean up GfxPaint32
d5e09a9f68 SCI32: Rewrap comments to 80 columns in lists32.h
ac0a83a424 SCI32: Clean up GfxControls32
b6c3f0f547 SCI32: Clean up CelObj
ce13b1699a SCI32: Clean up Robot decoder
8c9276e75a SCI32: Clean up script patch comments
15f6e6b97e SCI32: Remove resolved TODO in helpers.h
d53e778739 SCI32: Rewrap comments to 80 columns in SOL decoder
c7c5f28bdb SCI32: Clean up scriptWidth/scriptHeight/screenWidth/screenHeight
Commit: 5e2e6e9e8a06a3a54e74b889d167a094d74f5d5a
https://github.com/scummvm/scummvm/commit/5e2e6e9e8a06a3a54e74b889d167a094d74f5d5a
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:10:49-05:00
Commit Message:
COMMON: Switch to compile-time checking of invalid SortedArray calls
Runtime error detection is error-prone and unnecessary.
Changed paths:
common/array.h
diff --git a/common/array.h b/common/array.h
index bb7e03c..1645db0 100644
--- a/common/array.h
+++ b/common/array.h
@@ -418,31 +418,19 @@ public:
Array<T>::insert(where, element);
}
- T &operator[](size_type idx) {
- error("Operation []= not allowed with SortedArray");
- }
+private:
+ T &operator[](size_type idx);
- void insert_at(size_type idx, const T &element) {
- error("Operation insert_at(idx, element) not allowed with SortedArray");
- }
+ void insert_at(size_type idx, const T &element);
- void insert_at(size_type idx, const Array<T> &array) {
- error("Operation insert_at(idx, array) not allowed with SortedArray");
- }
+ void insert_at(size_type idx, const Array<T> &array);
- void insert(iterator pos, const T &element) {
- error("Operation insert(pos, elemnet) not allowed with SortedArray");
- }
+ void insert(iterator pos, const T &element);
- void push_back(const T &element) {
- error("Operation push_back(element) not allowed with SortedArray");
- }
+ void push_back(const T &element);
- void push_back(const Array<T> &array) {
- error("Operation push_back(array) not allowed with SortedArray");
- }
+ void push_back(const Array<T> &array);
-private:
// Based on code Copyright (C) 2008-2009 Ksplice, Inc.
// Author: Tim Abbott <tabbott at ksplice.com>
// Licensed under GPLv2+
@@ -465,7 +453,6 @@ private:
return &this->_storage[start_];
}
-private:
int (*_comparator)(const void *, const void *);
};
Commit: 79dd02373cb431adfceeb4be50366b7c084490d9
https://github.com/scummvm/scummvm/commit/79dd02373cb431adfceeb4be50366b7c084490d9
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:10:49-05:00
Commit Message:
COMMON: Prevent implicit conversion of smart pointers to non-bools
Changed paths:
common/ptr.h
diff --git a/common/ptr.h b/common/ptr.h
index ebdd77c..510fec1 100644
--- a/common/ptr.h
+++ b/common/ptr.h
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "common/noncopyable.h"
+#include "common/safe-bool.h"
#include "common/types.h"
namespace Common {
@@ -103,7 +104,7 @@ private:
* a plain pointer is only possible via SharedPtr::get.
*/
template<class T>
-class SharedPtr {
+class SharedPtr : public SafeBool<SharedPtr<T> > {
#if !defined(__GNUC__) || GCC_ATLEAST(3, 0)
template<class T2> friend class SharedPtr;
#endif
@@ -167,7 +168,7 @@ public:
* Implicit conversion operator to bool for convenience, to make
* checks like "if (sharedPtr) ..." possible.
*/
- operator bool() const { return _pointer != 0; }
+ bool operator_bool() const { return _pointer != nullptr; }
/**
* Checks if the SharedPtr object is the only object refering
@@ -223,7 +224,7 @@ private:
};
template<typename T>
-class ScopedPtr : NonCopyable {
+class ScopedPtr : private NonCopyable, public SafeBool<ScopedPtr<T> > {
public:
typedef T ValueType;
typedef T *PointerType;
@@ -238,7 +239,7 @@ public:
* Implicit conversion operator to bool for convenience, to make
* checks like "if (scopedPtr) ..." possible.
*/
- operator bool() const { return _pointer != 0; }
+ bool operator_bool() const { return _pointer != nullptr; }
~ScopedPtr() {
delete _pointer;
@@ -277,7 +278,7 @@ private:
template<typename T>
-class DisposablePtr : NonCopyable {
+class DisposablePtr : private NonCopyable, public SafeBool<DisposablePtr<T> > {
public:
typedef T ValueType;
typedef T *PointerType;
@@ -296,7 +297,7 @@ public:
* Implicit conversion operator to bool for convenience, to make
* checks like "if (scopedPtr) ..." possible.
*/
- operator bool() const { return _pointer; }
+ bool operator_bool() const { return _pointer != nullptr; }
/**
* Returns the plain pointer value.
Commit: f037d4df1680aecefac2ffb240547385a74971d0
https://github.com/scummvm/scummvm/commit/f037d4df1680aecefac2ffb240547385a74971d0
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:10:50-05:00
Commit Message:
COMMON: Allow construction of Arrays of non-copyable members
Although the previous count-constructor would never make a copy of
a member at runtime, Array<T>::reserve *may* copy-construct, so
the compiler would forbid creation of arrays of NonCopyable objects
even when the array was created only once and then never resized
(and thus never actually tried to perform a copy-construction).
Changed paths:
common/array.h
test/common/array.h
diff --git a/common/array.h b/common/array.h
index 1645db0..d4dac35 100644
--- a/common/array.h
+++ b/common/array.h
@@ -63,9 +63,10 @@ public:
* Constructs an array with `count` default-inserted instances of T. No
* copies are made.
*/
- explicit Array(size_type count) : _size(0) {
+ explicit Array(size_type count) : _size(count) {
allocCapacity(count);
- resize(count);
+ for (size_type i = 0; i < count; ++i)
+ new ((void *)&_storage[i]) T();
}
/**
diff --git a/test/common/array.h b/test/common/array.h
index 45be993..e0a6438 100644
--- a/test/common/array.h
+++ b/test/common/array.h
@@ -1,6 +1,7 @@
#include <cxxtest/TestSuite.h>
#include "common/array.h"
+#include "common/noncopyable.h"
#include "common/str.h"
class ArrayTestSuite : public CxxTest::TestSuite
@@ -315,6 +316,10 @@ class ArrayTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(array.size(), 10U);
TS_ASSERT_EQUALS(array[0], 0);
TS_ASSERT_EQUALS(array[9], 0);
+
+ // This will fail at compile time if it is not possible to construct an
+ // array without copy-construction
+ Common::Array<Common::NonCopyable> nonCopyable(1);
}
void test_array_constructor_count_copy_value() {
Commit: 5cffa3891f48d64154f00571c8127ef2c601d6d5
https://github.com/scummvm/scummvm/commit/5cffa3891f48d64154f00571c8127ef2c601d6d5
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:10:50-05:00
Commit Message:
SCI32: Clean up GfxPalette32
* Replace raw pointers with smart pointers
* Use references instead of const pointers where appropriate
* Tweak initialisation
* Tweak palette copies to the stack
Changed paths:
engines/sci/engine/savegame.cpp
engines/sci/graphics/palette32.cpp
engines/sci/graphics/palette32.h
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index b0fa31a..06a26ec 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -866,25 +866,25 @@ void GfxPalette::saveLoadWithSerializer(Common::Serializer &s) {
}
#ifdef ENABLE_SCI32
-static void saveLoadPalette32(Common::Serializer &s, Palette *const palette) {
- s.syncAsUint32LE(palette->timestamp);
- for (int i = 0; i < ARRAYSIZE(palette->colors); ++i) {
- s.syncAsByte(palette->colors[i].used);
- s.syncAsByte(palette->colors[i].r);
- s.syncAsByte(palette->colors[i].g);
- s.syncAsByte(palette->colors[i].b);
+static void saveLoadPalette32(Common::Serializer &s, Palette &palette) {
+ s.syncAsUint32LE(palette.timestamp);
+ for (int i = 0; i < ARRAYSIZE(palette.colors); ++i) {
+ s.syncAsByte(palette.colors[i].used);
+ s.syncAsByte(palette.colors[i].r);
+ s.syncAsByte(palette.colors[i].g);
+ s.syncAsByte(palette.colors[i].b);
}
}
-static void saveLoadOptionalPalette32(Common::Serializer &s, Palette **const palette) {
+static void saveLoadOptionalPalette32(Common::Serializer &s, Common::ScopedPtr<Palette> &palette) {
bool hasPalette = false;
if (s.isSaving()) {
- hasPalette = (*palette != nullptr);
+ hasPalette = palette;
}
s.syncAsByte(hasPalette);
if (hasPalette) {
if (s.isLoading()) {
- *palette = new Palette;
+ palette.reset(new Palette);
}
saveLoadPalette32(s, *palette);
}
@@ -899,14 +899,11 @@ void GfxPalette32::saveLoadWithSerializer(Common::Serializer &s) {
++_version;
for (int i = 0; i < kNumCyclers; ++i) {
- delete _cyclers[i];
- _cyclers[i] = nullptr;
+ _cyclers[i].reset();
}
- delete _varyTargetPalette;
- _varyTargetPalette = nullptr;
- delete _varyStartPalette;
- _varyStartPalette = nullptr;
+ _varyTargetPalette.reset();
+ _varyStartPalette.reset();
}
s.syncAsSint16LE(_varyDirection);
@@ -928,14 +925,14 @@ void GfxPalette32::saveLoadWithSerializer(Common::Serializer &s) {
if (g_sci->_features->hasLatePaletteCode() && s.getVersion() >= 41) {
s.syncAsSint16LE(_gammaLevel);
- saveLoadPalette32(s, &_sourcePalette);
+ saveLoadPalette32(s, _sourcePalette);
++_version;
_needsUpdate = true;
_gammaChanged = true;
}
- saveLoadOptionalPalette32(s, &_varyTargetPalette);
- saveLoadOptionalPalette32(s, &_varyStartPalette);
+ saveLoadOptionalPalette32(s, _varyTargetPalette);
+ saveLoadOptionalPalette32(s, _varyStartPalette);
// _nextPalette is not saved by SSCI
@@ -944,14 +941,15 @@ void GfxPalette32::saveLoadWithSerializer(Common::Serializer &s) {
bool hasCycler = false;
if (s.isSaving()) {
- cycler = _cyclers[i];
+ cycler = _cyclers[i].get();
hasCycler = (cycler != nullptr);
}
s.syncAsByte(hasCycler);
if (hasCycler) {
if (s.isLoading()) {
- _cyclers[i] = cycler = new PalCycler;
+ cycler = new PalCycler;
+ _cyclers[i].reset(cycler);
}
s.syncAsByte(cycler->fromColor);
diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index d8a2ead..7a3b396 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -39,11 +39,10 @@ namespace Sci {
HunkPalette::HunkPalette(const SciSpan<const byte> &rawPalette) :
_version(0),
- // NOTE: The header size in palettes is garbage. In at least KQ7 2.00b and
- // Phant1, the 999.pal sets this value to 0. In most other palettes it is
- // set to 14, but the *actual* size of the header structure used in SSCI is
- // 13, which is reflected by `kHunkPaletteHeaderSize`.
- // _headerSize(rawPalette[0]),
+ // The header size in palettes is garbage. In at least KQ7 2.00b and Phant1,
+ // the 999.pal sets this value to 0. In most other palettes it is set to 14,
+ // but the *actual* size of the header structure used in SSCI is 13, which
+ // is reflected by `kHunkPaletteHeaderSize`.
_numPalettes(rawPalette.getUint8At(kNumPaletteEntriesOffset)),
_data() {
assert(_numPalettes == 0 || _numPalettes == 1);
@@ -371,18 +370,17 @@ static const uint8 gammaTables[GfxPalette32::numGammaTables][256] = {
_varyLastTick(0),
_varyTime(0),
_varyDirection(0),
+ _varyPercent(0),
_varyTargetPercent(0),
_varyNumTimesPaused(0),
// Palette cycling
- _cyclers(),
_cycleMap(),
// Gamma correction
_gammaLevel(-1),
_gammaChanged(false) {
- _varyPercent = _varyTargetPercent;
for (int i = 0, len = ARRAYSIZE(_fadeTable); i < len; ++i) {
_fadeTable[i] = 100;
}
@@ -390,11 +388,6 @@ static const uint8 gammaTables[GfxPalette32::numGammaTables][256] = {
loadPalette(999);
}
-GfxPalette32::~GfxPalette32() {
- varyOff();
- cycleAllOff();
-}
-
bool GfxPalette32::loadPalette(const GuiResourceId resourceId) {
Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false);
@@ -604,16 +597,16 @@ void GfxPalette32::setVary(const Palette &target, const int16 percent, const int
}
void GfxPalette32::setVaryPercent(const int16 percent, const int32 ticks) {
- if (_varyTargetPalette != nullptr) {
+ if (_varyTargetPalette) {
setVaryTime(percent, ticks);
}
- // NOTE: SSCI had two additional parameters for this function to change the
+ // SSCI had two additional parameters for this function to change the
// `_varyFromColor`, but they were always hardcoded to be ignored
}
void GfxPalette32::setVaryTime(const int32 time) {
- if (_varyTargetPalette != nullptr) {
+ if (_varyTargetPalette) {
setVaryTime(_varyTargetPercent, time);
}
}
@@ -645,16 +638,8 @@ void GfxPalette32::varyOff() {
_varyFromColor = 0;
_varyToColor = 255;
_varyDirection = 0;
-
- if (_varyTargetPalette != nullptr) {
- delete _varyTargetPalette;
- _varyTargetPalette = nullptr;
- }
-
- if (_varyStartPalette != nullptr) {
- delete _varyStartPalette;
- _varyStartPalette = nullptr;
- }
+ _varyTargetPalette.reset();
+ _varyStartPalette.reset();
}
void GfxPalette32::varyPause() {
@@ -667,7 +652,7 @@ void GfxPalette32::varyOn() {
--_varyNumTimesPaused;
}
- if (_varyTargetPalette != nullptr && _varyNumTimesPaused == 0) {
+ if (_varyTargetPalette && _varyNumTimesPaused == 0) {
if (_varyPercent != _varyTargetPercent && _varyTime != 0) {
_varyDirection = (_varyTargetPercent - _varyPercent > 0) ? 1 : -1;
} else {
@@ -677,28 +662,26 @@ void GfxPalette32::varyOn() {
}
void GfxPalette32::setTarget(const Palette &palette) {
- delete _varyTargetPalette;
- _varyTargetPalette = new Palette(palette);
+ _varyTargetPalette.reset(new Palette(palette));
}
void GfxPalette32::setStart(const Palette &palette) {
- delete _varyStartPalette;
- _varyStartPalette = new Palette(palette);
+ _varyStartPalette.reset(new Palette(palette));
}
void GfxPalette32::mergeStart(const Palette &palette) {
- if (_varyStartPalette != nullptr) {
+ if (_varyStartPalette) {
mergePalette(*_varyStartPalette, palette);
} else {
- _varyStartPalette = new Palette(palette);
+ _varyStartPalette.reset(new Palette(palette));
}
}
void GfxPalette32::mergeTarget(const Palette &palette) {
- if (_varyTargetPalette != nullptr) {
+ if (_varyTargetPalette) {
mergePalette(*_varyTargetPalette, palette);
} else {
- _varyTargetPalette = new Palette(palette);
+ _varyTargetPalette.reset(new Palette(palette));
}
}
@@ -714,9 +697,9 @@ void GfxPalette32::applyVary() {
_varyPercent += _varyDirection;
}
- if (_varyPercent == 0 || _varyTargetPalette == nullptr) {
+ if (_varyPercent == 0 || !_varyTargetPalette) {
for (int i = 0; i < ARRAYSIZE(_nextPalette.colors); ++i) {
- if (_varyStartPalette != nullptr && i >= _varyFromColor && i <= _varyToColor) {
+ if (_varyStartPalette && i >= _varyFromColor && i <= _varyToColor) {
_nextPalette.colors[i] = _varyStartPalette->colors[i];
} else {
_nextPalette.colors[i] = _sourcePalette.colors[i];
@@ -728,7 +711,7 @@ void GfxPalette32::applyVary() {
Color targetColor = _varyTargetPalette->colors[i];
Color sourceColor;
- if (_varyStartPalette != nullptr) {
+ if (_varyStartPalette) {
sourceColor = _varyStartPalette->colors[i];
} else {
sourceColor = _sourcePalette.colors[i];
@@ -816,27 +799,28 @@ void GfxPalette32::setCycle(const uint8 fromColor, const uint8 toColor, const in
clearCycleMap(fromColor, cycler->numColorsToCycle);
} else {
for (int i = 0; i < kNumCyclers; ++i) {
- if (_cyclers[i] == nullptr) {
- _cyclers[i] = cycler = new PalCycler;
+ if (!_cyclers[i]) {
+ cycler = new PalCycler;
+ _cyclers[i].reset(cycler);
break;
}
}
}
- // If there are no free cycler slots, SCI engine overrides the first oldest
- // cycler that it finds, where "oldest" is determined by the difference
- // between the tick and now
+ // If there are no free cycler slots, SSCI overrides the first oldest cycler
+ // that it finds, where "oldest" is determined by the difference between the
+ // tick and now
if (cycler == nullptr) {
const uint32 now = g_sci->getTickCount();
uint32 minUpdateDelta = 0xFFFFFFFF;
for (int i = 0; i < kNumCyclers; ++i) {
- PalCycler *const candidate = _cyclers[i];
+ PalCyclerOwner &candidate = _cyclers[i];
const uint32 updateDelta = now - candidate->lastUpdateTick;
if (updateDelta < minUpdateDelta) {
minUpdateDelta = updateDelta;
- cycler = candidate;
+ cycler = candidate.get();
}
}
@@ -882,19 +866,18 @@ void GfxPalette32::cyclePause(const uint8 fromColor) {
void GfxPalette32::cycleAllOn() {
for (int i = 0; i < kNumCyclers; ++i) {
- PalCycler *const cycler = _cyclers[i];
- if (cycler != nullptr && cycler->numTimesPaused > 0) {
+ PalCyclerOwner &cycler = _cyclers[i];
+ if (cycler && cycler->numTimesPaused > 0) {
--cycler->numTimesPaused;
}
}
}
void GfxPalette32::cycleAllPause() {
- // NOTE: The original engine did not check for null pointers in the
- // palette cyclers pointer array.
+ // SSCI did not check for null pointers in the palette cyclers pointer array
for (int i = 0; i < kNumCyclers; ++i) {
- PalCycler *const cycler = _cyclers[i];
- if (cycler != nullptr) {
+ PalCyclerOwner &cycler = _cyclers[i];
+ if (cycler) {
// This seems odd, because currentCycle is 0..numColorsPerCycle,
// but fromColor is 0..255. When applyAllCycles runs, the values
// end up back in range
@@ -905,8 +888,8 @@ void GfxPalette32::cycleAllPause() {
applyAllCycles();
for (int i = 0; i < kNumCyclers; ++i) {
- PalCycler *const cycler = _cyclers[i];
- if (cycler != nullptr) {
+ PalCyclerOwner &cycler = _cyclers[i];
+ if (cycler) {
++cycler->numTimesPaused;
}
}
@@ -914,11 +897,10 @@ void GfxPalette32::cycleAllPause() {
void GfxPalette32::cycleOff(const uint8 fromColor) {
for (int i = 0; i < kNumCyclers; ++i) {
- PalCycler *const cycler = _cyclers[i];
- if (cycler != nullptr && cycler->fromColor == fromColor) {
+ PalCyclerOwner &cycler = _cyclers[i];
+ if (cycler && cycler->fromColor == fromColor) {
clearCycleMap(fromColor, cycler->numColorsToCycle);
- delete cycler;
- _cyclers[i] = nullptr;
+ _cyclers[i].reset();
break;
}
}
@@ -926,11 +908,10 @@ void GfxPalette32::cycleOff(const uint8 fromColor) {
void GfxPalette32::cycleAllOff() {
for (int i = 0; i < kNumCyclers; ++i) {
- PalCycler *const cycler = _cyclers[i];
- if (cycler != nullptr) {
+ PalCyclerOwner &cycler = _cyclers[i];
+ if (cycler) {
clearCycleMap(cycler->fromColor, cycler->numColorsToCycle);
- delete cycler;
- _cyclers[i] = nullptr;
+ _cyclers[i].reset();
}
}
}
@@ -969,9 +950,9 @@ void GfxPalette32::setCycleMap(const uint16 fromColor, const uint16 numColorsToS
PalCycler *GfxPalette32::getCycler(const uint16 fromColor) {
for (int cyclerIndex = 0; cyclerIndex < kNumCyclers; ++cyclerIndex) {
- PalCycler *cycler = _cyclers[cyclerIndex];
- if (cycler != nullptr && cycler->fromColor == fromColor) {
- return cycler;
+ PalCyclerOwner &cycler = _cyclers[cyclerIndex];
+ if (cycler && cycler->fromColor == fromColor) {
+ return cycler.get();
}
}
@@ -980,12 +961,12 @@ PalCycler *GfxPalette32::getCycler(const uint16 fromColor) {
void GfxPalette32::applyAllCycles() {
Color paletteCopy[256];
- memcpy(paletteCopy, _nextPalette.colors, sizeof(Color) * 256);
+ memcpy(paletteCopy, _nextPalette.colors, sizeof(paletteCopy));
for (int i = 0; i < kNumCyclers; ++i) {
- PalCycler *const cycler = _cyclers[i];
- if (cycler != nullptr) {
- cycler->currentCycle = (((int) cycler->currentCycle) + 1) % cycler->numColorsToCycle;
+ PalCyclerOwner &cycler = _cyclers[i];
+ if (cycler) {
+ cycler->currentCycle = (cycler->currentCycle + 1) % cycler->numColorsToCycle;
for (int j = 0; j < cycler->numColorsToCycle; j++) {
_nextPalette.colors[cycler->fromColor + j] = paletteCopy[cycler->fromColor + (cycler->currentCycle + j) % cycler->numColorsToCycle];
}
@@ -995,12 +976,12 @@ void GfxPalette32::applyAllCycles() {
void GfxPalette32::applyCycles() {
Color paletteCopy[256];
- memcpy(paletteCopy, _nextPalette.colors, sizeof(Color) * 256);
+ memcpy(paletteCopy, _nextPalette.colors, sizeof(paletteCopy));
const uint32 now = g_sci->getTickCount();
for (int i = 0; i < kNumCyclers; ++i) {
- PalCycler *const cycler = _cyclers[i];
- if (cycler == nullptr) {
+ PalCyclerOwner &cycler = _cyclers[i];
+ if (!cycler) {
continue;
}
diff --git a/engines/sci/graphics/palette32.h b/engines/sci/graphics/palette32.h
index b8ba85e..2d00b86 100644
--- a/engines/sci/graphics/palette32.h
+++ b/engines/sci/graphics/palette32.h
@@ -23,6 +23,8 @@
#ifndef SCI_GRAPHICS_PALETTE32_H
#define SCI_GRAPHICS_PALETTE32_H
+#include "common/ptr.h"
+
namespace Sci {
#pragma mark HunkPalette
@@ -233,7 +235,6 @@ struct PalCycler {
class GfxPalette32 {
public:
GfxPalette32(ResourceManager *resMan);
- ~GfxPalette32();
void saveLoadWithSerializer(Common::Serializer &s);
@@ -440,13 +441,13 @@ private:
* operation. If this palette is not specified, `_sourcePalette` is used
* instead.
*/
- Palette *_varyStartPalette;
+ Common::ScopedPtr<Palette> _varyStartPalette;
/**
* An optional palette used to provide target colors for a palette vary
* operation.
*/
- Palette *_varyTargetPalette;
+ Common::ScopedPtr<Palette> _varyTargetPalette;
/**
* The minimum palette index that has been varied from the source palette.
@@ -553,7 +554,8 @@ private:
kNumCyclers = 10
};
- PalCycler *_cyclers[kNumCyclers];
+ typedef Common::ScopedPtr<PalCycler> PalCyclerOwner;
+ PalCyclerOwner _cyclers[kNumCyclers];
/**
* Updates the `currentCycle` of the given `cycler` by `speed` entries.
@@ -564,8 +566,8 @@ private:
* The cycle map is used to detect overlapping cyclers, and to avoid
* remapping to palette entries that are being cycled.
*
- * According to SCI engine code, when two cyclers overlap, a fatal error has
- * occurred and the engine will display an error and then exit.
+ * According to SSCI, when two cyclers overlap, a fatal error has occurred
+ * and the engine will display an error and then exit.
*
* The color remapping system avoids attempts to remap to palette entries
* that are cycling because they won't be the expected color once the cycler
Commit: 0ac5d84062e430dff0f102788015dbb609fcdaa0
https://github.com/scummvm/scummvm/commit/0ac5d84062e430dff0f102788015dbb609fcdaa0
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:10:50-05:00
Commit Message:
SCI32: Clean up ScreenItem
* Rewrap comments to 80 columns
* Clarify comments where possible
* Use smart pointers where appropriate
Changed paths:
engines/sci/engine/object.h
engines/sci/graphics/plane32.cpp
engines/sci/graphics/screen_item32.cpp
engines/sci/graphics/screen_item32.h
diff --git a/engines/sci/engine/object.h b/engines/sci/engine/object.h
index ffc4ac2..9ab6ca3 100644
--- a/engines/sci/engine/object.h
+++ b/engines/sci/engine/object.h
@@ -169,7 +169,6 @@ public:
}
}
- // NOTE: In real engine, -info- is treated as byte size
void clearInfoSelectorFlag(infoSelectorFlags flag) {
if (getSciVersion() == SCI_VERSION_3) {
_infoSelectorSci3 &= ~flag;
diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp
index d9e0d2d..08708f2 100644
--- a/engines/sci/graphics/plane32.cpp
+++ b/engines/sci/graphics/plane32.cpp
@@ -201,10 +201,9 @@ void Plane::addPicInternal(const GuiResourceId pictureId, const Common::Point *p
} else {
screenItem->_position = celObj->_relativePosition;
}
- _screenItemList.add(screenItem);
+ screenItem->_celObj.reset(celObj);
- delete screenItem->_celObj;
- screenItem->_celObj = celObj;
+ _screenItemList.add(screenItem);
}
_type = (g_sci->_features->hasTransparentPicturePlanes() && transparent) ? kPlaneTypeTransparentPicture : kPlaneTypePicture;
}
diff --git a/engines/sci/graphics/screen_item32.cpp b/engines/sci/graphics/screen_item32.cpp
index 14e7173..4e1ed83 100644
--- a/engines/sci/graphics/screen_item32.cpp
+++ b/engines/sci/graphics/screen_item32.cpp
@@ -39,7 +39,6 @@ uint32 ScreenItem::_nextCreationId = 0;
ScreenItem::ScreenItem(const reg_t object) :
_creationId(_nextCreationId++),
-_celObj(nullptr),
_object(object),
_pictureId(-1),
_created(g_sci->_gfxFrameout->getScreenCount()),
@@ -59,7 +58,6 @@ _plane(plane),
_useInsetRect(false),
_z(0),
_celInfo(celInfo),
-_celObj(nullptr),
_fixedPriority(false),
_position(0, 0),
_object(make_reg(0, _nextObjectId++)),
@@ -76,7 +74,6 @@ _plane(plane),
_useInsetRect(false),
_z(0),
_celInfo(celInfo),
-_celObj(nullptr),
_fixedPriority(false),
_position(rect.left, rect.top),
_object(make_reg(0, _nextObjectId++)),
@@ -98,7 +95,6 @@ _scale(scaleInfo),
_useInsetRect(false),
_z(0),
_celInfo(celInfo),
-_celObj(nullptr),
_fixedPriority(false),
_position(position),
_object(make_reg(0, _nextObjectId++)),
@@ -115,7 +111,6 @@ _plane(other._plane),
_scale(other._scale),
_useInsetRect(other._useInsetRect),
_celInfo(other._celInfo),
-_celObj(nullptr),
_object(other._object),
_mirrorX(other._mirrorX),
_scaledPosition(other._scaledPosition),
@@ -127,18 +122,18 @@ _drawBlackLines(other._drawBlackLines) {
}
void ScreenItem::operator=(const ScreenItem &other) {
- // NOTE: The original engine did not check for differences in `_celInfo`
- // to clear `_celObj` here; instead, it unconditionally set `_celInfo`,
- // didn't clear `_celObj`, and did hacky stuff in `kIsOnMe` to avoid
- // testing a mismatched `_celObj`. See `GfxFrameout::kernelIsOnMe` for
- // more detail. kCelTypeMem types are unconditionally invalidated because
- // the properties of a CelObjMem can "change" when a game deletes a bitmap
- // and then creates a new one that reuses the old bitmap's offset in
- // BitmapTable (as happens in the LSL7 About screen when hovering names).
+ // SSCI did not check for differences in `_celInfo` to clear `_celObj` here;
+ // instead, it unconditionally set `_celInfo`, didn't clear `_celObj`, and
+ // did hacky stuff in `kIsOnMe` to avoid testing a mismatched `_celObj`. See
+ // `GfxFrameout::kernelIsOnMe` for more detail.
+ //
+ // kCelTypeMem types are unconditionally invalidated because the properties
+ // of a CelObjMem can "change" when a game deletes a bitmap and then creates
+ // a new one that reuses the old bitmap's offset in BitmapTable (as happens
+ // in the LSL7 About screen when hovering names).
if (_celInfo.type == kCelTypeMem || _celInfo != other._celInfo) {
_celInfo = other._celInfo;
- delete _celObj;
- _celObj = nullptr;
+ _celObj.reset();
}
_creationId = other._creationId;
@@ -153,10 +148,6 @@ void ScreenItem::operator=(const ScreenItem &other) {
_drawBlackLines = other._drawBlackLines;
}
-ScreenItem::~ScreenItem() {
- delete _celObj;
-}
-
void ScreenItem::init() {
_nextObjectId = 20000;
_nextCreationId = 0;
@@ -176,17 +167,12 @@ void ScreenItem::setFromObject(SegManager *segMan, const reg_t object, const boo
_celInfo.celNo = readSelectorValue(segMan, object, SELECTOR(cel));
if (_celInfo.resourceId <= kPlanePic) {
- // TODO: Enhance GfxView or ResourceManager to allow
- // metadata for resources to be retrieved once, from a
- // single location
Resource *view = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, _celInfo.resourceId), false);
if (!view) {
error("Failed to load %s", _celInfo.toString().c_str());
}
- // NOTE: +2 because the header size field itself is excluded from
- // the header size in the data
- const uint16 headerSize = view->getUint16SEAt(0) + 2;
+ const uint16 headerSize = view->getUint16SEAt(0) + /* header size field */ sizeof(uint16);
const uint8 loopCount = view->getUint8At(2);
const uint8 loopSize = view->getUint8At(12);
@@ -225,8 +211,7 @@ void ScreenItem::setFromObject(SegManager *segMan, const reg_t object, const boo
}
if (updateCel || updateBitmap) {
- delete _celObj;
- _celObj = nullptr;
+ _celObj.reset();
}
if (readSelectorValue(segMan, object, SELECTOR(fixPriority))) {
@@ -305,8 +290,8 @@ void ScreenItem::calcRects(const Plane &plane) {
}
// Cel may use a coordinate system that is not the same size as the
- // script coordinate system (usually this means high-resolution
- // pictures with low-resolution scripts)
+ // script coordinate system (usually this means high-resolution pictures
+ // with low-resolution scripts)
if (celObj._xResolution != kLowResX || celObj._yResolution != kLowResY) {
// high resolution coordinates
@@ -386,7 +371,7 @@ void ScreenItem::calcRects(const Plane &plane) {
mulinc(temp, celToScreenX, Ratio());
- CelObjPic *celObjPic = dynamic_cast<CelObjPic *>(_celObj);
+ CelObjPic *celObjPic = dynamic_cast<CelObjPic *>(_celObj.get());
if (celObjPic == nullptr) {
error("Expected a CelObjPic");
}
@@ -415,9 +400,8 @@ void ScreenItem::calcRects(const Plane &plane) {
if (!scaleX.isOne() || !scaleY.isOne()) {
mulinc(_screenItemRect, scaleX, scaleY);
- // TODO: This was in the original code, baked into the
- // multiplication though it is not immediately clear
- // why this is the only one that reduces the BR corner
+ // TODO: This was in SSCI, baked into the multiplication. It is
+ // not clear why this is the only one that reduces the BR corner
_screenItemRect.right -= 1;
_screenItemRect.bottom -= 1;
}
@@ -434,7 +418,7 @@ void ScreenItem::calcRects(const Plane &plane) {
temp.right -= 1;
}
- CelObjPic *celObjPic = dynamic_cast<CelObjPic *>(_celObj);
+ CelObjPic *celObjPic = dynamic_cast<CelObjPic *>(_celObj.get());
if (celObjPic == nullptr) {
error("Expected a CelObjPic");
}
@@ -487,19 +471,19 @@ void ScreenItem::calcRects(const Plane &plane) {
}
CelObj &ScreenItem::getCelObj() const {
- if (_celObj == nullptr) {
+ if (!_celObj) {
switch (_celInfo.type) {
case kCelTypeView:
- _celObj = new CelObjView(_celInfo.resourceId, _celInfo.loopNo, _celInfo.celNo);
+ _celObj.reset(new CelObjView(_celInfo.resourceId, _celInfo.loopNo, _celInfo.celNo));
break;
case kCelTypePic:
error("Internal error, pic screen item with no cel.");
break;
case kCelTypeMem:
- _celObj = new CelObjMem(_celInfo.bitmap);
+ _celObj.reset(new CelObjMem(_celInfo.bitmap));
break;
case kCelTypeColor:
- _celObj = new CelObjColor(_celInfo.color, _insetRect.width(), _insetRect.height());
+ _celObj.reset(new CelObjColor(_celInfo.color, _insetRect.width(), _insetRect.height()));
break;
}
}
@@ -534,7 +518,7 @@ void ScreenItem::printDebugInfo(Console *con) const {
con->debugPrintf(" %s\n", _celInfo.toString().c_str());
- if (_celObj != nullptr) {
+ if (_celObj) {
con->debugPrintf(" width %d, height %d, x-resolution %d, y-resolution %d\n",
_celObj->_width,
_celObj->_height,
@@ -583,8 +567,7 @@ void ScreenItem::update() {
}
_deleted = 0;
- delete _celObj;
- _celObj = nullptr;
+ _celObj.reset();
}
Common::Rect ScreenItem::getNowSeenRect(const Plane &plane) const {
@@ -647,15 +630,13 @@ Common::Rect ScreenItem::getNowSeenRect(const Plane &plane) const {
if (!scaleX.isOne() || !scaleY.isOne()) {
// Different games use a different cel scaling mode, but the
- // difference isn't consistent across SCI versions; instead,
- // it seems to be related to an update that happened during
- // SCI2.1mid where games started using hi-resolution game
- // scripts
+ // difference isn't consistent across SCI versions; instead, it
+ // seems to be related to an update that happened during SCI2.1mid
+ // where games started using high-resolution game scripts
if (scriptWidth == kLowResX) {
mulinc(nsRect, scaleX, scaleY);
- // TODO: This was in the original code, baked into the
- // multiplication though it is not immediately clear
- // why this is the only one that reduces the BR corner
+ // TODO: This was in SSCI, baked into the multiplication. It is
+ // not clear why this is the only one that reduces the BR corner
nsRect.right -= 1;
nsRect.bottom -= 1;
} else {
@@ -693,9 +674,8 @@ Common::Rect ScreenItem::getNowSeenRect(const Plane &plane) const {
if (!scaleX.isOne() || !scaleY.isOne()) {
mulinc(nsRect, scaleX, scaleY);
- // TODO: This was in the original code, baked into the
- // multiplication though it is not immediately clear
- // why this is the only one that reduces the BR corner
+ // TODO: This was in SSCI, baked into the multiplication. It is not
+ // clear why this is the only one that reduces the BR corner
nsRect.right -= 1;
nsRect.bottom -= 1;
}
diff --git a/engines/sci/graphics/screen_item32.h b/engines/sci/graphics/screen_item32.h
index cdde2d3..5acf759 100644
--- a/engines/sci/graphics/screen_item32.h
+++ b/engines/sci/graphics/screen_item32.h
@@ -49,22 +49,20 @@ class SegManager;
#pragma mark ScreenItem
/**
- * A ScreenItem is the engine-side representation of a
- * game script View.
+ * A ScreenItem is the engine-side representation of a game script View.
*/
class ScreenItem {
private:
/**
- * A serial used for screen items that are generated
- * inside the graphics engine, rather than the
- * interpreter.
+ * A serial used for screen items that are generated inside the graphics
+ * engine, rather than the interpreter.
*/
static uint16 _nextObjectId;
/**
- * A serial used to identify the creation order of
- * screen items, to ensure a stable sort order for
- * screen items with identical priorities and z-indexes.
+ * A serial used to identify the creation order of screen items, to ensure a
+ * stable sort order for screen items with identical priorities and
+ * z-indexes.
*/
static uint32 _nextCreationId;
@@ -75,160 +73,145 @@ public:
reg_t _plane;
/**
- * Scaling data used to calculate the final screen
- * dimensions of the screen item as well as the scaling
- * ratios used when drawing the item to screen.
+ * Scaling data used to calculate the final screen dimensions of the screen
+ * item as well as the scaling ratios used when drawing the item to screen.
*/
ScaleInfo _scale;
private:
/**
- * The position & dimensions of the screen item in
- * screen coordinates. This rect includes the offset
- * of the parent plane, but is not clipped to the
- * screen, so may include coordinates that are
- * offscreen.
+ * The position & dimensions of the screen item in screen coordinates. This
+ * rect includes the offset of the parent plane, but is not clipped to the
+ * screen, so may include coordinates that are offscreen.
*/
Common::Rect _screenItemRect;
/**
- * If true, the `_insetRect` rectangle will be used
- * when calculating the dimensions of the screen item
- * instead of the cel's intrinsic width and height.
+ * If true, the `_insetRect` rectangle will be used when calculating the
+ * dimensions of the screen item instead of the cel's intrinsic width and
+ * height.
*
- * In other words, using an inset rect means that
- * the cel is cropped to the dimensions given in
- * `_insetRect`.
+ * In other words, using an inset rect means that the cel is cropped to the
+ * dimensions given in `_insetRect`.
*/
bool _useInsetRect;
/**
- * The cropping rectangle used when `_useInsetRect`
- * is true.
+ * The cropping rectangle used when `_useInsetRect` is true.
*
- * `_insetRect` is also used to describe the fill
- * rectangle of a screen item with a CelObjColor
- * cel.
+ * `_insetRect` is also used to describe the fill rectangle of a screen item
+ * with a CelObjColor cel.
*/
Common::Rect _insetRect;
/**
- * The z-index of the screen item in pseudo-3D space.
- * Higher values are drawn on top of lower values.
+ * The z-index of the screen item in pseudo-3D space. Higher values are
+ * drawn on top of lower values.
*/
int _z;
/**
- * Sets the common properties of a screen item that must
- * be set both during creation and update of a screen
- * item.
+ * Sets the common properties of a screen item that must be set both during
+ * creation and update of a screen item.
*/
void setFromObject(SegManager *segMan, const reg_t object, const bool updateCel, const bool updateBitmap);
public:
/**
- * The creation order number, which ensures a stable
- * sort when screen items with identical priorities and
- * z-indexes are added to the screen item list.
+ * The creation order number, which ensures a stable sort when screen items
+ * with identical priorities and z-indexes are added to the screen item
+ * list.
*/
uint32 _creationId;
/**
- * A descriptor for the cel object represented by the
- * screen item.
+ * A descriptor for the cel object represented by the screen item.
*/
CelInfo32 _celInfo;
/**
- * The cel object used to actually render the screen
- * item. This member is populated by calling
- * `getCelObj`.
+ * The cel object used to actually render the screen item. This member is
+ * populated by calling `getCelObj`.
*/
- mutable CelObj *_celObj;
+ mutable Common::ScopedPtr<CelObj> _celObj;
/**
- * If set, the priority for this screen item is fixed
- * in place. Otherwise, the priority of the screen item
- * is calculated from its y-position + z-index.
+ * If set, the priority for this screen item is fixed in place. Otherwise,
+ * the priority of the screen item is calculated from its y-position +
+ * z-index.
*/
bool _fixedPriority;
/**
- * The rendering priority of the screen item, relative
- * only to the other screen items within the same plane.
- * Higher priorities are drawn above lower priorities.
+ * The rendering priority of the screen item, relative only to the other
+ * screen items within the same plane. Higher priorities are drawn above
+ * lower priorities.
*/
int16 _priority;
/**
- * The top-left corner of the screen item, in game
- * script coordinates, relative to the parent plane.
+ * The top-left corner of the screen item, in game script coordinates,
+ * relative to the parent plane.
*/
Common::Point _position;
/**
- * The associated View script object that was
- * used to create the ScreenItem, or a numeric
- * value in the case of a ScreenItem that was
- * generated outside of the VM.
+ * The associated View script object that was used to create the ScreenItem,
+ * or a numeric value in the case of a ScreenItem that was generated by the
+ * kernel.
*/
reg_t _object;
/**
- * For screen items representing picture resources,
- * the resource ID of the picture.
+ * For screen items representing picture resources, the resource ID of the
+ * picture.
*/
GuiResourceId _pictureId;
/**
* Flags indicating the state of the screen item.
- * - `created` is set when the screen item is first
- * created, either from a VM object or from within the
- * engine itself
- * - `updated` is set when `created` is not already set
- * and the screen item is updated from a VM object
- * - `deleted` is set by the parent plane, if the parent
- * plane is a pic type and its picture resource ID has
- * changed
+ * - `created` is set when the screen item is first created, either from a
+ * VM object or from within the kernel
+ * - `updated` is set when `created` is not already set and the screen item
+ * is updated from a VM object
+ * - `deleted` is set by the parent plane, if the parent plane is a pic type
+ * and its picture resource ID has changed
*/
int _created, _updated, _deleted;
/**
- * For screen items that represent picture cels, this
- * value is set to match the `_mirrorX` property of the
- * parent plane and indicates that the cel should be
- * drawn horizontally mirrored. For final drawing, it is
- * XORed with the `_mirrorX` property of the cel object.
- * The cel object's `_mirrorX` property comes from the
- * resource data itself.
+ * For screen items that represent picture cels, this value is set to match
+ * the `_mirrorX` property of the parent plane and indicates that the cel
+ * should be
+ * drawn horizontally mirrored. For final drawing, it is XORed with the
+ * `_mirrorX` property of the cel object. The cel object's `_mirrorX`
+ * property comes from the resource data.
*/
bool _mirrorX;
/**
- * The scaling ratios to use when drawing this screen
- * item. These values are calculated according to the
- * scale info whenever the screen item is updated.
+ * The scaling ratios to use when drawing this screen item. These values are
+ * calculated according to the scale info whenever the screen item is
+ * updated.
*/
Ratio _ratioX, _ratioY;
/**
- * The top-left corner of the screen item, in screen
- * coordinates.
+ * The top-left corner of the screen item, in screen coordinates.
*/
Common::Point _scaledPosition;
/**
- * The position & dimensions of the screen item in
- * screen coordinates. This rect includes the offset of
- * the parent plane and is clipped to the screen.
+ * The position & dimensions of the screen item in screen coordinates. This
+ * rect includes the offset of the parent plane and is clipped to the
+ * screen.
*/
Common::Rect _screenRect;
/**
- * Whether or not the screen item should be drawn
- * with black lines drawn every second line. This is
- * used when pixel doubling videos to improve apparent
- * sharpness at the cost of your eyesight.
+ * Whether or not the screen item should be drawn with black lines drawn
+ * every second line. This is used when pixel doubling videos to improve
+ * apparent sharpness at the cost of your eyesight.
*/
bool _drawBlackLines;
@@ -242,7 +225,6 @@ public:
ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Rect &rect);
ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Point &position, const ScaleInfo &scaleInfo);
ScreenItem(const ScreenItem &other);
- ~ScreenItem();
void operator=(const ScreenItem &);
inline bool operator<(const ScreenItem &other) const {
@@ -337,39 +319,36 @@ public:
}
/**
- * Calculates the dimensions and scaling parameters for
- * the screen item, using the given plane as the parent
- * plane for screen rect positioning.
+ * Calculates the dimensions and scaling parameters for the screen item,
+ * using the given plane as the parent plane for screen rect positioning.
*
- * @note This method was called Update in SCI engine.
+ * @note This method was called Update in SSCI.
*/
void calcRects(const Plane &plane);
/**
- * Retrieves the corresponding cel object for this
- * screen item. If a cel object does not already exist,
- * one will be created and assigned.
+ * Retrieves the corresponding cel object for this screen item. If a cel
+ * object does not already exist, one will be created and assigned.
*/
CelObj &getCelObj() const;
void printDebugInfo(Console *con) const;
/**
- * Updates the properties of the screen item from a
- * VM object.
+ * Updates the properties of the screen item from a VM object.
*/
void update(const reg_t object);
/**
- * Updates the properties of the screen item for one not belonging
- * to a VM object. Originally GraphicsMgr::UpdateScreenItem.
+ * Updates the properties of the screen item for one not belonging to a VM
+ * object. Originally GraphicsMgr::UpdateScreenItem.
*/
void update();
/**
- * Gets the "now seen" rect for the screen item, which
- * represents the current size and position of the
- * screen item on the screen in script coordinates.
+ * Gets the "now seen" rect for the screen item, which represents the
+ * current size and position of the screen item on the screen in script
+ * coordinates.
*/
Common::Rect getNowSeenRect(const Plane &plane) const;
};
Commit: ff3503abdee09fcd35d86297dfb79879d0ecc8b8
https://github.com/scummvm/scummvm/commit/ff3503abdee09fcd35d86297dfb79879d0ecc8b8
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:10:50-05:00
Commit Message:
SCI32: Clean up GfxTransitions32
* Use containers where appropriate
* Re-wrap doxygen comments to 80 columns
* Clarify comments for parts of the engine that are understood now
but were not understood at the time of the initial
implementation
Changed paths:
engines/sci/engine/kgraphics32.cpp
engines/sci/graphics/transitions32.cpp
engines/sci/graphics/transitions32.h
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index b7fae2e..d093c55 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -368,10 +368,10 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) {
const uint16 type = argv[0].toUint16();
reg_t planeObj = argv[1];
int16 seconds = argv[2].toSint16();
- // NOTE: This value seems to indicate whether the transition is an
- // “exit” transition (0) or an “enter” transition (-1) for fade
- // transitions. For other types of transitions, it indicates a palette
- // index value to use when filling the screen.
+ // This value indicates whether the transition is an "exit" transition (0)
+ // or an "enter" transition (-1) for fade transitions. For other types of
+ // transitions, it indicates a palette index value to use when filling the
+ // screen.
int16 back = argv[3].toSint16();
int16 priority = argv[4].toSint16();
int16 animate = argv[5].toSint16();
@@ -404,9 +404,8 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) {
error("Illegal show style %d for plane %04x:%04x", type, PRINT_REG(planeObj));
}
- // NOTE: The order of planeObj and showStyle are reversed
- // because this is how SCI3 called the corresponding method
- // on the KernelMgr
+ // The order of planeObj and showStyle are reversed because this is how
+ // SSCI3 called the corresponding method on the KernelMgr
g_sci->_gfxTransitions32->kernelSetShowStyle(argc, planeObj, (ShowStyleType)type, seconds, back, priority, animate, refFrame, pFadeArray, divisions, blackScreen);
return s->r_acc;
@@ -881,8 +880,8 @@ reg_t kSetScroll(EngineState *s, int argc, reg_t *argv) {
const int16 deltaY = argv[2].toSint16();
const GuiResourceId pictureId = argv[3].toUint16();
const bool animate = argv[4].toUint16();
- // NOTE: speed was accepted as an argument, but then never actually used
- // const int16 speed = argc > 5 ? (bool)argv[5].toSint16() : -1;
+ // argv[5] was some speed argument, but it was not actually used by SSCI, so
+ // we ignore it here
const bool mirrorX = argc > 6 ? (bool)argv[6].toUint16() : false;
g_sci->_gfxTransitions32->kernelSetScroll(plane, deltaX, deltaY, pictureId, animate, mirrorX);
diff --git a/engines/sci/graphics/transitions32.cpp b/engines/sci/graphics/transitions32.cpp
index df9c2da..8be9e63 100644
--- a/engines/sci/graphics/transitions32.cpp
+++ b/engines/sci/graphics/transitions32.cpp
@@ -126,7 +126,7 @@ void GfxTransitions32::processShowStyles() {
g_sci->_gfxFrameout->frameOut(true);
throttle();
}
- } while(continueProcessing && doFrameOut);
+ } while (continueProcessing && doFrameOut);
}
void GfxTransitions32::processEffects(PlaneShowStyle &showStyle) {
@@ -249,14 +249,13 @@ void GfxTransitions32::kernelSetShowStyle(const uint16 argc, const reg_t planeOb
if (createNewEntry) {
entry = new PlaneShowStyle;
- // NOTE: SCI2.1 engine tests if allocation returned a null pointer
- // but then only avoids setting currentStep if this is so. Since
- // this is a nonsensical approach, we do not do that here
+ // SSCI2.1 tests if allocation returned a null pointer but then only
+ // avoids setting currentStep if this is so. Since this nonsensical, we
+ // do not do that here
entry->currentStep = 0;
entry->processed = false;
entry->divisions = hasDivisions ? divisions : _defaultDivisions[type];
entry->plane = planeObj;
- entry->fadeColorRangesCount = 0;
if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
// for pixel dissolve
@@ -267,32 +266,26 @@ void GfxTransitions32::kernelSetShowStyle(const uint16 argc, const reg_t planeOb
entry->screenItems.clear();
entry->width = plane->_gameRect.width();
entry->height = plane->_gameRect.height();
- } else {
- entry->fadeColorRanges = nullptr;
- if (hasFadeArray) {
- // NOTE: SCI2.1mid engine does no check to verify that an array is
- // successfully retrieved, and SegMan will cause a fatal error
- // if we try to use a memory segment that is not an array
- SciArray &table = *_segMan->lookupArray(pFadeArray);
-
- uint32 rangeCount = table.size();
- entry->fadeColorRangesCount = rangeCount;
-
- // NOTE: SCI engine code always allocates memory even if the range
- // table has no entries, but this does not really make sense, so
- // we avoid the allocation call in this case
- if (rangeCount > 0) {
- entry->fadeColorRanges = new uint16[rangeCount];
- for (size_t i = 0; i < rangeCount; ++i) {
- entry->fadeColorRanges[i] = table.getAsInt16(i);
- }
+ } else if (hasFadeArray) {
+ // SSCI2.1mid does no check to verify that an array is successfully
+ // retrieved
+ SciArray &table = *_segMan->lookupArray(pFadeArray);
+
+ const uint32 rangeCount = table.size();
+
+ // SSCI always allocates memory even if the range table has no
+ // entries, but this does not really make sense, so we avoid the
+ // allocation call in this case
+ if (rangeCount > 0) {
+ entry->fadeColorRanges.reserve(rangeCount);
+ for (uint32 i = 0; i < rangeCount; ++i) {
+ entry->fadeColorRanges.push_back(table.getAsInt16(i));
}
}
}
}
- // NOTE: The original engine had no nullptr check and would just crash
- // if it got to here
+ // SSCI had no nullptr check and would just crash if it got to here
if (entry == nullptr) {
error("Cannot edit non-existing ShowStyle entry");
}
@@ -397,10 +390,9 @@ ShowStyleList::iterator GfxTransitions32::deleteShowStyle(const ShowStyleList::i
break;
case kShowStyleFadeIn:
case kShowStyleFadeOut:
- if (getSciVersion() > SCI_VERSION_2_1_EARLY && showStyle->fadeColorRangesCount > 0) {
- delete[] showStyle->fadeColorRanges;
- }
- break;
+ // SSCI manually allocated the color ranges for fades and deleted that
+ // memory here, but we use a container so there is no extra cleanup
+ // needed
case kShowStyleNone:
case kShowStyleMorph:
case kShowStyleHShutterIn:
@@ -944,8 +936,8 @@ bool GfxTransitions32::processFade(const int8 direction, PlaneShowStyle &showSty
percent *= 100;
percent /= showStyle.divisions - 1;
- if (showStyle.fadeColorRangesCount > 0) {
- for (int i = 0, len = showStyle.fadeColorRangesCount; i < len; i += 2) {
+ if (showStyle.fadeColorRanges.size()) {
+ for (uint i = 0, len = showStyle.fadeColorRanges.size(); i < len; i += 2) {
g_sci->_gfxPalette32->setFade(percent, showStyle.fadeColorRanges[i], showStyle.fadeColorRanges[i + 1]);
}
} else {
diff --git a/engines/sci/graphics/transitions32.h b/engines/sci/graphics/transitions32.h
index c4c5228..4dbacf4 100644
--- a/engines/sci/graphics/transitions32.h
+++ b/engines/sci/graphics/transitions32.h
@@ -28,7 +28,7 @@
#include "sci/engine/vm_types.h"
namespace Sci {
-enum ShowStyleType /* : uint8 */ {
+enum ShowStyleType {
kShowStyleNone = 0,
kShowStyleHShutterOut = 1,
kShowStyleHShutterIn = 2,
@@ -48,14 +48,12 @@ enum ShowStyleType /* : uint8 */ {
};
/**
- * Show styles represent transitions applied to draw planes.
- * One show style per plane can be active at a time.
+ * A show style represents a transition applied to a Plane. One show style per
+ * plane can be active at a time.
*/
struct PlaneShowStyle {
/**
- * The ID of the plane this show style belongs to.
- * In SCI2.1mid (at least SQ6), per-plane transitions
- * were removed and a single plane ID is used.
+ * The ID of the plane this transition applies to.
*/
reg_t plane;
@@ -65,9 +63,8 @@ struct PlaneShowStyle {
ShowStyleType type;
/**
- * When true, the show style is an entry transition
- * to a new room. When false, it is an exit
- * transition away from an old room.
+ * When true, the show style is an entry transition to a new room. When
+ * false, it is an exit transition away from an old room.
*/
bool fadeUp;
@@ -77,38 +74,35 @@ struct PlaneShowStyle {
int16 divisions;
/**
- * The color used by transitions that draw CelObjColor
- * screen items. -1 for transitions that do not draw
- * screen items.
+ * The color used by transitions that draw CelObjColor screen items. -1 for
+ * transitions that do not draw screen items.
*/
int16 color;
- // TODO: Probably uint32
- // TODO: This field probably should be used in order to
- // provide time-accurate processing of show styles. In the
- // actual SCI engine (at least 2–2.1mid) it appears that
- // style transitions are drawn “as fast as possible”, one
- // step per loop, even though this delay field exists
+ /**
+ * The amount of time, in ticks, between each cycle of the animation.
+ */
int delay;
- // TODO: Probably bool, but never seems to be true?
+ /**
+ * If true, GfxTransitions32 will yield back to the main game loop after
+ * calculating the next frame. Otherwise, GfxTransitions32 takes exclusive
+ * control over the game loop until the transition has completed.
+ */
bool animate;
/**
- * The wall time at which the next step of the animation
- * should execute.
+ * The time at which the next step of the animation should execute.
*/
uint32 nextTick;
/**
- * During playback of the show style, the current step
- * (out of divisions).
+ * During playback of the show style, the current step (out of `divisions`).
*/
int currentStep;
/**
- * Whether or not this style has finished running and
- * is ready for disposal.
+ * Whether or not this style has finished running and is ready for disposal.
*/
bool processed;
@@ -117,32 +111,30 @@ struct PlaneShowStyle {
//
/**
- * A list of screen items, each representing one
- * block of a wipe transition.
+ * A list of screen items, each representing one block of a wipe transition.
+ * These screen items are owned by GfxFrameout.
*/
Common::Array<ScreenItem *> screenItems;
/**
- * For wipe transitions, the number of edges with a
- * moving wipe (1, 2, or 4).
+ * For wipe transitions, the number of edges with a moving wipe (1, 2, or
+ * 4).
*/
uint8 numEdges;
/**
- * The dimensions of the plane, in game script
- * coordinates.
+ * The dimensions of the plane, in game script coordinates.
*/
int16 width, height;
/**
- * For pixel dissolve transitions, the screen item
- * used to render the transition.
+ * For pixel dissolve transitions, the screen item used to render the
+ * transition. This screen item is owned by GfxFrameout.
*/
ScreenItem *bitmapScreenItem;
/**
- * For pixel dissolve transitions, the bitmap used
- * to render the transition.
+ * For pixel dissolve transitions, the bitmap used to render the transition.
*/
reg_t bitmap;
@@ -152,15 +144,13 @@ struct PlaneShowStyle {
uint32 dissolveMask;
/**
- * The first pixel that was dissolved in a pixel
- * dissolve transition.
+ * The first pixel that was dissolved in a pixel dissolve transition.
*/
uint32 firstPixel;
/**
- * The last pixel that was dissolved. Once all
- * pixels have been dissolved, `pixel` will once
- * again equal `firstPixel`.
+ * The last pixel that was dissolved. Once all pixels have been dissolved,
+ * `pixel` will once again equal `firstPixel`.
*/
uint32 pixel;
@@ -169,21 +159,15 @@ struct PlaneShowStyle {
//
/**
- * The number of entries in the fadeColorRanges array.
- */
- uint8 fadeColorRangesCount;
-
- /**
- * A pointer to an dynamically sized array of palette
- * indexes, in the order [ fromColor, toColor, ... ].
+ * An array of palette indexes, in the order [ fromColor, toColor, ... ].
* Only colors within this range are transitioned.
*/
- uint16 *fadeColorRanges;
+ Common::Array<uint16> fadeColorRanges;
};
/**
- * PlaneScroll describes a transition between two different
- * pictures within a single plane.
+ * PlaneScroll describes a transition between two different pictures within a
+ * single plane.
*/
struct PlaneScroll {
/**
@@ -197,28 +181,26 @@ struct PlaneScroll {
int16 x, y;
/**
- * The distance that should be scrolled. Only one of
- * `deltaX` or `deltaY` may be set.
+ * The distance that should be scrolled. Only one of `deltaX` or `deltaY`
+ * may be set.
*/
int16 deltaX, deltaY;
/**
- * The pic that should be created and scrolled into
- * view inside the plane.
+ * The pic that should be created and scrolled into view inside the plane.
*/
GuiResourceId newPictureId;
/**
- * The picture that should be scrolled out of view
- * and deleted from the plane.
+ * The picture that should be scrolled out of view and deleted from the
+ * plane.
*/
GuiResourceId oldPictureId;
/**
- * If true, the scroll animation is interleaved
- * with other updates to the graphics. If false,
- * the scroll will be exclusively animated until
- * it is finished.
+ * If true, GfxTransitions32 will yield back to the main game loop after
+ * calculating the next frame. Otherwise, GfxTransitions32 takes exclusive
+ * control over the game loop until the transition has completed.
*/
bool animate;
@@ -235,6 +217,7 @@ class GfxTransitions32 {
public:
GfxTransitions32(SegManager *_segMan);
~GfxTransitions32();
+
private:
SegManager *_segMan;
@@ -264,209 +247,185 @@ public:
inline bool hasShowStyles() const { return !_showStyles.empty(); }
/**
- * Processes all active show styles in a loop
- * until they are finished.
+ * Processes all active show styles in a loop until they are finished.
*/
void processShowStyles();
/**
- * Processes show styles that are applied
- * through `GfxFrameout::palMorphFrameOut`.
+ * Processes show styles that are applied through
+ * `GfxFrameout::palMorphFrameOut`.
*/
void processEffects(PlaneShowStyle &showStyle);
- // NOTE: This signature is taken from SCI3 Phantasmagoria 2
- // and is valid for all implementations of SCI32
void kernelSetShowStyle(const uint16 argc, const reg_t planeObj, const ShowStyleType type, const int16 seconds, const int16 direction, const int16 priority, const int16 animate, const int16 frameOutNow, reg_t pFadeArray, int16 divisions, const int16 blackScreen);
/**
- * Sets the range that will be used by
- * `GfxFrameout::palMorphFrameOut` to alter
- * palette entries.
+ * Sets the range that will be used by `GfxFrameout::palMorphFrameOut` to
+ * alter palette entries.
*/
void kernelSetPalStyleRange(const uint8 fromColor, const uint8 toColor);
/**
- * A map of palette entries that can be morphed
- * by the Morph show style.
+ * A map of palette entries that can be morphed by the Morph show style.
*/
int8 _styleRanges[256];
private:
/**
- * Default sequence values for pixel dissolve
- * transition bit masks.
+ * Default sequence values for pixel dissolve transition bit masks.
*/
int *_dissolveSequenceSeeds;
/**
- * Default values for `PlaneShowStyle::divisions`
- * for the current SCI version.
+ * Default values for `PlaneShowStyle::divisions` for the current SCI
+ * version.
*/
int16 *_defaultDivisions;
/**
- * The list of PlaneShowStyles that are
- * currently active.
+ * The list of PlaneShowStyles that are currently active.
*/
ShowStyleList _showStyles;
/**
- * Finds a show style that applies to the given
- * plane.
+ * Finds a show style that applies to the given plane.
*/
PlaneShowStyle *findShowStyleForPlane(const reg_t planeObj);
/**
- * Finds the iterator for a show style that
- * applies to the given plane.
+ * Finds the iterator for a show style that applies to the given plane.
*/
ShowStyleList::iterator findIteratorForPlane(const reg_t planeObj);
/**
- * Deletes the given PlaneShowStyle and returns
- * the next PlaneShowStyle from the list of
- * styles.
+ * Deletes the given PlaneShowStyle and returns the next PlaneShowStyle from
+ * the list of styles.
*/
ShowStyleList::iterator deleteShowStyle(const ShowStyleList::iterator &showStyle);
/**
- * Initializes the given PlaneShowStyle for a
- * horizontal wipe effect for SCI2 to 2.1early.
+ * Initializes the given PlaneShowStyle for a horizontal wipe effect for
+ * SCI2 to 2.1early.
*/
void configure21EarlyHorizontalWipe(PlaneShowStyle &showStyle, const int16 priority);
/**
- * Initializes the given PlaneShowStyle for a
- * horizontal shutter effect for SCI2 to 2.1early.
+ * Initializes the given PlaneShowStyle for a horizontal shutter effect for
+ * SCI2 to 2.1early.
*/
void configure21EarlyHorizontalShutter(PlaneShowStyle &showStyle, const int16 priority);
/**
- * Initializes the given PlaneShowStyle for an
- * iris effect for SCI2 to 2.1early.
+ * Initializes the given PlaneShowStyle for an iris effect for SCI2 to
+ * 2.1early.
*/
void configure21EarlyIris(PlaneShowStyle &showStyle, const int16 priority);
/**
- * Initializes the given PlaneShowStyle for a
- * pixel dissolve effect for SCI2 to 2.1early.
+ * Initializes the given PlaneShowStyle for a pixel dissolve effect for SCI2
+ * to 2.1early.
*/
void configure21EarlyDissolve(PlaneShowStyle &showStyle, const int16 priority, const Common::Rect &gameRect);
/**
- * Processes one tick of the given
- * PlaneShowStyle.
+ * Processes one tick of the given PlaneShowStyle.
*/
bool processShowStyle(PlaneShowStyle &showStyle, uint32 now);
/**
- * Performs an instant transition between two
- * rooms.
+ * Performs an instant transition between two rooms.
*/
bool processNone(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders into a room
- * with a horizontal shutter effect.
+ * Performs a transition that renders into a room with a horizontal shutter
+ * effect.
*/
bool processHShutterOut(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders to black
- * with a horizontal shutter effect.
+ * Performs a transition that renders to black with a horizontal shutter
+ * effect.
*/
void processHShutterIn(const PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders into a room
- * with a vertical shutter effect.
+ * Performs a transition that renders into a room with a vertical shutter
+ * effect.
*/
void processVShutterOut(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders to black
- * with a vertical shutter effect.
+ * Performs a transition that renders to black with a vertical shutter
+ * effect.
*/
void processVShutterIn(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders into a room
- * with a wipe to the left.
+ * Performs a transition that renders into a room with a wipe to the left.
*/
void processWipeLeft(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders to black
- * with a wipe to the right.
+ * Performs a transition that renders to black with a wipe to the right.
*/
void processWipeRight(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders into a room
- * with a wipe upwards.
+ * Performs a transition that renders into a room with a wipe upwards.
*/
void processWipeUp(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders to black
- * with a wipe downwards.
+ * Performs a transition that renders to black with a wipe downwards.
*/
void processWipeDown(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders into a room
- * with an iris effect.
+ * Performs a transition that renders into a room with an iris effect.
*/
bool processIrisOut(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders to black
- * with an iris effect.
+ * Performs a transition that renders to black with an iris effect.
*/
bool processIrisIn(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders between
- * rooms using a block dissolve effect.
+ * Performs a transition that renders between rooms using a block dissolve
+ * effect.
*/
void processDissolveNoMorph(PlaneShowStyle &showStyle);
/**
- * Performs a transition that renders between
- * rooms with a pixel dissolve effect.
+ * Performs a transition that renders between rooms with a pixel dissolve
+ * effect.
*/
bool processPixelDissolve(PlaneShowStyle &showStyle);
/**
- * SCI2 to 2.1early implementation of pixel
- * dissolve.
+ * SCI2 to 2.1early implementation of pixel dissolve.
*/
bool processPixelDissolve21Early(PlaneShowStyle &showStyle);
/**
- * SCI2.1mid and later implementation of
- * pixel dissolve.
+ * SCI2.1mid and later implementation of pixel dissolve.
*/
bool processPixelDissolve21Mid(const PlaneShowStyle &showStyle);
/**
- * Performs a transition that fades to black
- * between rooms.
+ * Performs a transition that fades to black between rooms.
*/
bool processFade(const int8 direction, PlaneShowStyle &showStyle);
/**
- * Morph transition calls back into the
- * transition system's `processEffects`
- * method, which then applies transitions
- * other than None, Fade, or Morph.
+ * Morph transition calls back into the transition system's `processEffects`
+ * method, which then applies transitions other than None, Fade, or Morph.
*/
bool processMorph(PlaneShowStyle &showStyle);
/**
- * Performs a generic transition for any of
- * the wipe/shutter/iris effects.
+ * Performs a generic transition for any of the wipe/shutter/iris effects.
*/
bool processWipe(const int8 direction, PlaneShowStyle &showStyle);
@@ -476,8 +435,7 @@ public:
inline bool hasScrolls() const { return !_scrolls.empty(); }
/**
- * Processes all active plane scrolls
- * in a loop until they are finished.
+ * Processes all active plane scrolls in a loop until they are finished.
*/
void processScrolls();
@@ -490,8 +448,7 @@ private:
ScrollList _scrolls;
/**
- * Performs a scroll of the content of
- * a plane.
+ * Performs a scroll of the content of a plane.
*/
bool processScroll(PlaneScroll &scroll);
};
Commit: 9d05bf79208fac113b81531996cead6521efa6fe
https://github.com/scummvm/scummvm/commit/9d05bf79208fac113b81531996cead6521efa6fe
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:10:51-05:00
Commit Message:
SCI32: Clean up GfxCursor32
* Rewrap doxygen comments to 80 columns
* Renamings for clarity
* Deduplicate copy/paint code
Changed paths:
engines/sci/graphics/cursor32.cpp
engines/sci/graphics/cursor32.h
diff --git a/engines/sci/graphics/cursor32.cpp b/engines/sci/graphics/cursor32.cpp
index 74fbafa..ae8c014 100644
--- a/engines/sci/graphics/cursor32.cpp
+++ b/engines/sci/graphics/cursor32.cpp
@@ -34,22 +34,22 @@ namespace Sci {
GfxCursor32::GfxCursor32() :
_hideCount(0),
_position(0, 0),
- _writeToVMAP(false) {
+ _needsPaint(false) {
}
-void GfxCursor32::init(const Buffer &vmap) {
- _vmap = vmap;
- _vmapRegion.rect = Common::Rect(_vmap.screenWidth, _vmap.screenHeight);
- _vmapRegion.data = (byte *)_vmap.getPixels();
- _restrictedArea = _vmapRegion.rect;
+void GfxCursor32::init(const Buffer &outputBuffer) {
+ _screen = outputBuffer;
+ _screenRegion.rect = Common::Rect(_screen.screenWidth, _screen.screenHeight);
+ _screenRegion.data = static_cast<byte *>(_screen.getPixels());
+ _restrictedArea = _screenRegion.rect;
}
GfxCursor32::~GfxCursor32() {
free(_cursor.data);
free(_cursorBack.data);
- free(_drawBuff1.data);
- free(_drawBuff2.data);
- free(_savedVmapRegion.data);
+ free(_scratch1.data);
+ free(_scratch2.data);
+ free(_savedScreenRegion.data);
}
void GfxCursor32::hide() {
@@ -58,25 +58,26 @@ void GfxCursor32::hide() {
}
if (!_cursorBack.rect.isEmpty()) {
- drawToHardware(_cursorBack);
+ drawToScreen(_cursorBack);
}
}
void GfxCursor32::revealCursor() {
_cursorBack.rect = _cursor.rect;
- _cursorBack.rect.clip(_vmapRegion.rect);
+ _cursorBack.rect.clip(_screenRegion.rect);
if (_cursorBack.rect.isEmpty()) {
return;
}
- readVideo(_cursorBack);
- _drawBuff1.rect = _cursor.rect;
- copy(_drawBuff1, _cursorBack);
- paint(_drawBuff1, _cursor);
- drawToHardware(_drawBuff1);
+ copyFromScreen(_cursorBack);
+ _scratch1.rect = _cursor.rect;
+ copy<false>(_scratch1, _cursorBack);
+ copy<true>(_scratch1, _cursor);
+ drawToScreen(_scratch1);
}
-void GfxCursor32::paint(DrawRegion &target, const DrawRegion &source) {
+template <bool SKIP>
+void GfxCursor32::copy(DrawRegion &target, const DrawRegion &source) {
if (source.rect.isEmpty()) {
return;
}
@@ -96,25 +97,33 @@ void GfxCursor32::paint(DrawRegion &target, const DrawRegion &source) {
const byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset;
const uint8 skipColor = source.skipColor;
- const int16 sourceStride = source.rect.width() - drawRectWidth;
- const int16 targetStride = target.rect.width() - drawRectWidth;
+ int16 sourceStride = source.rect.width();
+ int16 targetStride = target.rect.width();
+ if (SKIP) {
+ sourceStride -= drawRectWidth;
+ targetStride -= drawRectWidth;
+ }
for (int16 y = 0; y < drawRectHeight; ++y) {
- for (int16 x = 0; x < drawRectWidth; ++x) {
- if (*sourcePixel != skipColor) {
- *targetPixel = *sourcePixel;
+ if (SKIP) {
+ for (int16 x = 0; x < drawRectWidth; ++x) {
+ if (*sourcePixel != skipColor) {
+ *targetPixel = *sourcePixel;
+ }
+ ++targetPixel;
+ ++sourcePixel;
}
- ++targetPixel;
- ++sourcePixel;
+ } else {
+ memcpy(targetPixel, sourcePixel, drawRectWidth);
}
- sourcePixel += sourceStride;
targetPixel += targetStride;
+ sourcePixel += sourceStride;
}
}
-void GfxCursor32::drawToHardware(const DrawRegion &source) {
+void GfxCursor32::drawToScreen(const DrawRegion &source) {
Common::Rect drawRect(source.rect);
- drawRect.clip(_vmapRegion.rect);
+ drawRect.clip(_screenRegion.rect);
const int16 sourceXOffset = drawRect.left - source.rect.left;
const int16 sourceYOffset = drawRect.top - source.rect.top;
byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset;
@@ -174,7 +183,7 @@ void GfxCursor32::setRestrictedArea(const Common::Rect &rect) {
}
void GfxCursor32::clearRestrictedArea() {
- _restrictedArea = _vmapRegion.rect;
+ _restrictedArea = _screenRegion.rect;
}
void GfxCursor32::setView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo) {
@@ -279,58 +288,29 @@ void GfxCursor32::setView(const GuiResourceId viewId, const int16 loopNo, const
_cursor.rect = Common::Rect(_width, _height);
*_cursor.data = _cursor.skipColor;
_cursorBack.rect = _cursor.rect;
- _cursorBack.rect.clip(_vmapRegion.rect);
+ _cursorBack.rect.clip(_screenRegion.rect);
if (!_cursorBack.rect.isEmpty()) {
- readVideo(_cursorBack);
+ copyFromScreen(_cursorBack);
}
}
_cursorBack.data = (byte *)realloc(_cursorBack.data, _width * _height);
memset(_cursorBack.data, 0, _width * _height);
- _drawBuff1.data = (byte *)realloc(_drawBuff1.data, _width * _height);
- _drawBuff2.data = (byte *)realloc(_drawBuff2.data, _width * _height * 4);
- _savedVmapRegion.data = (byte *)realloc(_savedVmapRegion.data, _width * _height);
+ _scratch1.data = (byte *)realloc(_scratch1.data, _width * _height);
+ _scratch2.data = (byte *)realloc(_scratch2.data, _width * _height * 4);
+ _savedScreenRegion.data = (byte *)realloc(_savedScreenRegion.data, _width * _height);
unhide();
}
-void GfxCursor32::readVideo(DrawRegion &target) {
- // NOTE: In SSCI, mouse events were received via hardware interrupt, so
- // there was a separate branch here that would read from VRAM instead of
- // from the game's back buffer when a mouse event was received while the
- // back buffer was being updated. In ScummVM, mouse events are polled, which
- // means it is not possible to receive a mouse event during a back buffer
- // update, so the code responsible for handling that is removed.
- copy(target, _vmapRegion);
-}
-
-void GfxCursor32::copy(DrawRegion &target, const DrawRegion &source) {
- if (source.rect.isEmpty()) {
- return;
- }
-
- Common::Rect drawRect(source.rect);
- drawRect.clip(target.rect);
- if (drawRect.isEmpty()) {
- return;
- }
-
- const int16 sourceXOffset = drawRect.left - source.rect.left;
- const int16 sourceYOffset = drawRect.top - source.rect.top;
- const int16 drawWidth = drawRect.width();
- const int16 drawHeight = drawRect.height();
-
- byte *targetPixel = target.data + ((drawRect.top - target.rect.top) * target.rect.width()) + (drawRect.left - target.rect.left);
- const byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset;
-
- const int16 sourceStride = source.rect.width();
- const int16 targetStride = target.rect.width();
-
- for (int y = 0; y < drawHeight; ++y) {
- memcpy(targetPixel, sourcePixel, drawWidth);
- targetPixel += targetStride;
- sourcePixel += sourceStride;
- }
+void GfxCursor32::copyFromScreen(DrawRegion &target) {
+ // In SSCI, mouse events were received via hardware interrupt, so there was
+ // a separate branch here that would read from VRAM instead of from the
+ // game's back buffer when a mouse event was received while the back buffer
+ // was being updated. In ScummVM, mouse events are polled, which means it is
+ // not possible to receive a mouse event during a back buffer update, so the
+ // code responsible for handling that is removed.
+ copy<false>(target, _screenRegion);
}
void GfxCursor32::setPosition(const Common::Point &position) {
@@ -349,32 +329,32 @@ void GfxCursor32::setPosition(const Common::Point &position) {
}
void GfxCursor32::gonnaPaint(Common::Rect paintRect) {
- if (!_hideCount && !_writeToVMAP && !_cursorBack.rect.isEmpty()) {
+ if (!_hideCount && !_needsPaint && !_cursorBack.rect.isEmpty()) {
paintRect.left &= ~3;
paintRect.right |= 3;
if (_cursorBack.rect.intersects(paintRect)) {
- _writeToVMAP = true;
+ _needsPaint = true;
}
}
}
void GfxCursor32::paintStarting() {
- if (_writeToVMAP) {
- _savedVmapRegion.rect = _cursor.rect;
- copy(_savedVmapRegion, _vmapRegion);
- paint(_vmapRegion, _cursor);
+ if (_needsPaint) {
+ _savedScreenRegion.rect = _cursor.rect;
+ copy<false>(_savedScreenRegion, _screenRegion);
+ copy<true>(_screenRegion, _cursor);
}
}
void GfxCursor32::donePainting() {
- if (_writeToVMAP) {
- copy(_vmapRegion, _savedVmapRegion);
- _savedVmapRegion.rect = Common::Rect();
- _writeToVMAP = false;
+ if (_needsPaint) {
+ copy<false>(_screenRegion, _savedScreenRegion);
+ _savedScreenRegion.rect = Common::Rect();
+ _needsPaint = false;
}
if (!_hideCount && !_cursorBack.rect.isEmpty()) {
- copy(_cursorBack, _vmapRegion);
+ copy<false>(_cursorBack, _screenRegion);
}
}
@@ -423,45 +403,45 @@ void GfxCursor32::move() {
}
// Cursor moved offscreen
- if (!_cursor.rect.intersects(_vmapRegion.rect)) {
- drawToHardware(_cursorBack);
+ if (!_cursor.rect.intersects(_screenRegion.rect)) {
+ drawToScreen(_cursorBack);
return;
}
if (!_cursor.rect.intersects(_cursorBack.rect)) {
// Cursor moved to a completely different part of the screen
- _drawBuff1.rect = _cursor.rect;
- _drawBuff1.rect.clip(_vmapRegion.rect);
- readVideo(_drawBuff1);
+ _scratch1.rect = _cursor.rect;
+ _scratch1.rect.clip(_screenRegion.rect);
+ copyFromScreen(_scratch1);
- _drawBuff2.rect = _drawBuff1.rect;
- copy(_drawBuff2, _drawBuff1);
+ _scratch2.rect = _scratch1.rect;
+ copy<false>(_scratch2, _scratch1);
- paint(_drawBuff1, _cursor);
- drawToHardware(_drawBuff1);
+ copy<true>(_scratch1, _cursor);
+ drawToScreen(_scratch1);
- drawToHardware(_cursorBack);
+ drawToScreen(_cursorBack);
_cursorBack.rect = _cursor.rect;
- _cursorBack.rect.clip(_vmapRegion.rect);
- copy(_cursorBack, _drawBuff2);
+ _cursorBack.rect.clip(_screenRegion.rect);
+ copy<false>(_cursorBack, _scratch2);
} else {
// Cursor moved, but still overlaps the previous cursor location
Common::Rect mergedRect(_cursorBack.rect);
mergedRect.extend(_cursor.rect);
- mergedRect.clip(_vmapRegion.rect);
+ mergedRect.clip(_screenRegion.rect);
- _drawBuff2.rect = mergedRect;
- readVideo(_drawBuff2);
+ _scratch2.rect = mergedRect;
+ copyFromScreen(_scratch2);
- copy(_drawBuff2, _cursorBack);
+ copy<false>(_scratch2, _cursorBack);
_cursorBack.rect = _cursor.rect;
- _cursorBack.rect.clip(_vmapRegion.rect);
- copy(_cursorBack, _drawBuff2);
+ _cursorBack.rect.clip(_screenRegion.rect);
+ copy<false>(_cursorBack, _scratch2);
- paint(_drawBuff2, _cursor);
- drawToHardware(_drawBuff2);
+ copy<true>(_scratch2, _cursor);
+ drawToScreen(_scratch2);
}
}
diff --git a/engines/sci/graphics/cursor32.h b/engines/sci/graphics/cursor32.h
index 562a2c5..fb07c49 100644
--- a/engines/sci/graphics/cursor32.h
+++ b/engines/sci/graphics/cursor32.h
@@ -23,6 +23,7 @@
#ifndef SCI_GRAPHICS_CURSOR32_H
#define SCI_GRAPHICS_CURSOR32_H
+#include "common/array.h" // for Array
#include "common/rect.h" // for Point, Rect
#include "common/scummsys.h" // for int16, byte, uint8
#include "common/serializer.h" // for Serializable, Serializer (ptr only)
@@ -37,11 +38,10 @@ public:
~GfxCursor32();
/**
- * Initialises the cursor system with the given
- * buffer to use as the output buffer for
- * rendering the cursor.
+ * Initialises the cursor system with the given buffer to use as the output
+ * buffer for rendering the cursor.
*/
- void init(const Buffer &vmap);
+ void init(const Buffer &outputBuffer);
/**
* Called when the hardware mouse moves.
@@ -49,41 +49,35 @@ public:
bool deviceMoved(Common::Point &position);
/**
- * Called by GfxFrameout once for each show
- * rectangle that is going to be drawn to
- * hardware.
+ * Called by GfxFrameout once for each show rectangle that is going to be
+ * drawn to hardware.
*/
void gonnaPaint(Common::Rect paintRect);
/**
- * Called by GfxFrameout when the rendering to
- * hardware begins.
+ * Called by GfxFrameout when the rendering to hardware begins.
*/
void paintStarting();
/**
- * Called by GfxFrameout when the output buffer
- * has finished rendering to hardware.
+ * Called by GfxFrameout when the output buffer has finished rendering to
+ * hardware.
*/
void donePainting();
/**
- * Hides the cursor. Each call to `hide` will
- * increment a hide counter, which must be
- * returned to 0 before the cursor will be
- * shown again.
+ * Hides the cursor. Each call to `hide` will increment a hide counter,
+ * which must be returned to 0 before the cursor will be shown again.
*/
void hide();
/**
- * Shows the cursor, if the hide counter is
- * returned to 0.
+ * Shows the cursor, if the hide counter is returned to 0.
*/
void unhide();
/**
- * Shows the cursor regardless of the state of
- * the hide counter.
+ * Shows the cursor regardless of the state of the hide counter.
*/
void show();
@@ -93,14 +87,12 @@ public:
void setView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo);
/**
- * Explicitly sets the position of the cursor,
- * in game script coordinates.
+ * Explicitly sets the position of the cursor, in game script coordinates.
*/
void setPosition(const Common::Point &position);
/**
- * Sets the region that the mouse is allowed
- * to move within.
+ * Sets the region that the mouse is allowed to move within.
*/
void setRestrictedArea(const Common::Rect &rect);
@@ -109,10 +101,6 @@ public:
*/
void clearRestrictedArea();
-#ifdef ENABLE_SCI32_MAC
- void setMacCursorRemapList(int cursorCount, reg_t *cursors);
-#endif
-
virtual void saveLoadWithSerializer(Common::Serializer &ser);
private:
@@ -121,42 +109,41 @@ private:
byte *data;
uint8 skipColor;
- DrawRegion() : rect(), data(nullptr) {}
+ DrawRegion() : data(nullptr) {}
};
/**
- * Information about the current cursor.
- * Used to restore cursor when loading a
- * savegame.
+ * Information about the current cursor. Used to restore cursor when loading
+ * a savegame.
*/
CelInfo32 _cursorInfo;
/**
- * Content behind the cursor? TODO
+ * The content of the frame buffer which was behind the cursor prior to its
+ * being drawn.
*/
DrawRegion _cursorBack;
/**
* Scratch buffer.
*/
- DrawRegion _drawBuff1;
+ DrawRegion _scratch1;
/**
* Scratch buffer 2.
*/
- DrawRegion _drawBuff2;
+ DrawRegion _scratch2;
/**
- * A draw region representing the current
- * output buffer.
+ * A draw region representing the entire output buffer.
*/
- DrawRegion _vmapRegion;
+ DrawRegion _screenRegion;
/**
- * The content behind the cursor in the
+ * The region behind the cursor immediately before it is painted to the
* output buffer.
*/
- DrawRegion _savedVmapRegion;
+ DrawRegion _savedScreenRegion;
/**
* The cursor bitmap.
@@ -164,93 +151,82 @@ private:
DrawRegion _cursor;
/**
- * The width and height of the cursor,
- * in screen coordinates.
+ * The width and height of the cursor, in screen coordinates.
*/
int16 _width, _height;
/**
- * The output buffer where the cursor is
- * rendered.
+ * The output buffer where the cursor is rendered.
*/
- Buffer _vmap;
+ Buffer _screen;
/**
- * The number of times the cursor has been
- * hidden.
+ * The number of times the cursor has been hidden.
*/
int _hideCount;
/**
- * The rendered position of the cursor, in
- * screen coordinates.
+ * The rendered position of the cursor, in screen coordinates.
*/
Common::Point _position;
/**
- * The position of the cursor hot spot, relative
- * to the cursor origin, in screen pixels.
+ * The position of the cursor hot spot, relative to the cursor origin, in
+ * screen pixels.
*/
Common::Point _hotSpot;
/**
- * The area within which the cursor is allowed
- * to move, in screen pixels.
+ * The area within which the cursor is allowed to move, in screen pixels.
*/
Common::Rect _restrictedArea;
/**
- * Indicates whether or not the cursor needs to
- * be repainted on the output buffer due to a
- * change of graphics in the area underneath the
- * cursor.
- */
- bool _writeToVMAP;
-
- // Mac versions of games use a remap list to remap their cursors
- Common::Array<uint16> _macCursorRemap;
-
- /**
- * Reads data from the output buffer or hardware
- * to the given draw region.
+ * Indicates whether or not the cursor needs to be repainted on the output
+ * buffer due to a change of graphics in the area underneath the cursor.
*/
- void readVideo(DrawRegion &target);
+ bool _needsPaint;
/**
- * Reads data from the output buffer to the
- * given draw region.
+ * Reads data from the output buffer to the given draw region.
*/
- void readVideoFromVmap(DrawRegion &target);
+ void copyFromScreen(DrawRegion &target);
/**
- * Copies pixel data from the given source to
- * the given target.
+ * Copies pixel data from the given source to the given target. If SKIP is
+ * true, pixels that match the `skipColor` property of the source will be
+ * skipped.
+ *
+ * @note In SSCI, the function that did not handle skip color was called
+ * `copy` and the one that did was called `paint`.
*/
+ template <bool SKIP>
void copy(DrawRegion &target, const DrawRegion &source);
/**
- * Draws from the given source onto the given
- * target, skipping pixels in the source that
- * match the `skipColor` property.
- */
- void paint(DrawRegion &target, const DrawRegion &source);
-
- /**
- * Draws the cursor to the position it was
- * drawn to prior to moving offscreen or being
- * hidden by a call to `hide`.
+ * Draws the cursor to the position it was drawn to prior to moving
+ * offscreen or being hidden by a call to `hide`.
*/
void revealCursor();
/**
* Draws the given source to the output buffer.
*/
- void drawToHardware(const DrawRegion &source);
+ void drawToScreen(const DrawRegion &source);
/**
* Renders the cursor at its new location.
*/
void move();
+
+#ifdef ENABLE_SCI32_MAC
+public:
+ void setMacCursorRemapList(int cursorCount, reg_t *cursors);
+
+private:
+ // Mac versions of games use a remap list to remap their cursors
+ Common::Array<uint16> _macCursorRemap;
+#endif
};
} // End of namespace Sci
Commit: c413030be3a03e363c7c5728dbeb1fe65f90688e
https://github.com/scummvm/scummvm/commit/c413030be3a03e363c7c5728dbeb1fe65f90688e
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:10:51-05:00
Commit Message:
SCI32: Clean up Video32
* Rewrap comments to 80 columns
* Clarify comments where appropriate
Changed paths:
engines/sci/graphics/video32.cpp
engines/sci/graphics/video32.h
diff --git a/engines/sci/graphics/video32.cpp b/engines/sci/graphics/video32.cpp
index e837cec..c128ba1 100644
--- a/engines/sci/graphics/video32.cpp
+++ b/engines/sci/graphics/video32.cpp
@@ -63,8 +63,8 @@ bool VideoPlayer::open(const Common::String &fileName) {
}
#ifndef USE_RGB_COLOR
- // KQ7 2.00b videos are compressed in 24bpp Cinepak, so cannot play on
- // a system with no RGB support
+ // KQ7 2.00b videos are compressed in 24bpp Cinepak, so cannot play on a
+ // system with no RGB support
if (_decoder->getPixelFormat().bytesPerPixel != 1) {
void showScummVMDialog(const Common::String &message);
showScummVMDialog(Common::String::format(_("Cannot play back %dbpp video on a system with maximum color depth of 8bpp"), _decoder->getPixelFormat().bpp()));
@@ -117,8 +117,8 @@ bool VideoPlayer::endHQVideo() {
}
VideoPlayer::EventFlags VideoPlayer::playUntilEvent(const EventFlags flags, const uint32 maxSleepMs) {
- // Flushing all the keyboard and mouse events out of the event manager
- // keeps events queued from before the start of playback from accidentally
+ // Flushing all the keyboard and mouse events out of the event manager keeps
+ // events queued from before the start of playback from accidentally
// activating a video stop flag
_eventMan->flushEvents();
@@ -201,11 +201,10 @@ void VideoPlayer::submitPalette(const uint8 palette[256 * 3]) const {
g_system->getPaletteManager()->setPalette(palette, 0, 256);
// KQ7 1.x has videos encoded using Microsoft Video 1 where palette 0 is
- // white and 255 is black, which is basically the opposite of DOS/Win
- // SCI palettes. So, when drawing to an 8bpp hwscreen, whenever a new
- // palette is seen, the screen must be re-filled with the new black
- // entry to ensure areas outside the video are always black and not some
- // other color
+ // white and 255 is black, which is basically the opposite of DOS/Win SCI
+ // palettes. So, when drawing to an 8bpp hwscreen, whenever a new palette is
+ // seen, the screen must be re-filled with the new black entry to ensure
+ // areas outside the video are always black and not some other color
for (int color = 0; color < 256; ++color) {
if (palette[0] == 0 && palette[1] == 0 && palette[2] == 0) {
g_system->fillScreen(color);
@@ -231,7 +230,8 @@ void VideoPlayer::renderFrame(const Graphics::Surface &nextFrame) const {
if (_decoder->getWidth() != _drawRect.width() || _decoder->getHeight() != _drawRect.height()) {
Graphics::Surface *const unscaledFrame(convertedFrame);
// TODO: The only reason TransparentSurface is used here because it is
- // where common scaler code is right now.
+ // where common scaler code is right now, which should just be part of
+ // Graphics::Surface (or some free functions).
const Graphics::TransparentSurface tsUnscaledFrame(*unscaledFrame);
#ifdef USE_RGB_COLOR
if (_hqVideoMode) {
@@ -315,9 +315,9 @@ void SEQPlayer::play(const Common::String &fileName, const int16 numTicks, const
const int16 scaledWidth = (_decoder->getWidth() * Ratio(screenWidth, scriptWidth)).toInt();
const int16 scaledHeight = (_decoder->getHeight() * Ratio(screenHeight, scriptHeight)).toInt();
- // Normally we would use the coordinates passed into the play function
- // to position the video, but since we are scaling the video (which SSCI
- // did not do), the coordinates are not correct. Since videos are always
+ // Normally we would use the coordinates passed into the play function to
+ // position the video, but since we are scaling the video (which SSCI did
+ // not do), the coordinates are not correct. Since videos are always
// intended to play in the center of the screen, we just recalculate the
// origin here.
_drawRect.left = (screenWidth - scaledWidth) / 2;
@@ -449,9 +449,9 @@ AVIPlayer::IOStatus AVIPlayer::play(const int16 from, const int16 to, const int1
}
AVIPlayer::EventFlags AVIPlayer::playUntilEvent(const EventFlags flags, const uint32 maxSleepMs) {
- // NOTE: In SSCI, whether or not a video could be skipped was controlled by
- // game scripts; here, we always allow skipping video with the mouse or
- // escape key, to improve the user experience
+ // In SSCI, whether or not a video could be skipped was controlled by game
+ // scripts; here, we always allow skipping video with the mouse or escape
+ // key, to improve the user experience
return VideoPlayer::playUntilEvent(flags | kEventFlagMouseDown | kEventFlagEscapeKey, maxSleepMs);
}
@@ -681,8 +681,8 @@ VMDPlayer::EventFlags VMDPlayer::kernelPlayUntilEvent(const EventFlags flags, co
VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags, const uint32) {
if (flags & kEventFlagReverse) {
- // NOTE: This flag may not work properly since SSCI does not care
- // if a video has audio, but the VMD decoder does.
+ // This flag may not work properly since SSCI does not care if a video
+ // has audio, but the VMD decoder does.
warning("VMD reverse playback flag was set. Please report this event to the bug tracker");
const bool success = _decoder->setReverse(true);
assert(success);
@@ -838,10 +838,10 @@ void VMDPlayer::submitPalette(const uint8 rawPalette[256 * 3]) const {
if (_isComposited) {
SciBitmap *bitmap = _segMan->lookupBitmap(_bitmapId);
bitmap->setPalette(palette);
- // NOTE: SSCI calls updateScreenItem and frameOut here, but this should
- // not be necessary in ScummVM since the new palette gets submitted
- // before the next frame is rendered, and the frame rendering call will
- // perform the same operations.
+ // SSCI calls updateScreenItem and frameOut here, but this is not
+ // necessary in ScummVM since the new palette gets submitted before the
+ // next frame is rendered, and the frame rendering call will perform the
+ // same operations.
} else {
g_sci->_gfxPalette32->submit(palette);
g_sci->_gfxPalette32->updateForFrame();
@@ -931,7 +931,7 @@ void VMDPlayer::initComposited() {
_screenItem->_drawBlackLines = true;
}
- // NOTE: There was code for positioning the screen item using insetRect
+ // In SSCI, there was code for positioning the screen item using insetRect
// here, but none of the game scripts seem to use this functionality.
g_sci->_gfxFrameout->addScreenItem(*_screenItem);
@@ -1016,9 +1016,8 @@ void VMDPlayer::setPlane(const int16 priority, const reg_t planeId) {
void VMDPlayer::restrictPalette(const uint8 startColor, const int16 endColor) {
_startColor = startColor;
- // At least GK2 sends 256 as the end color, which is wrong,
- // but works in the original engine as the storage size is 4 bytes
- // and used values are clamped to 0-255
+ // At least GK2 sends 256 as the end color, which is wrong, but works in
+ // SSCI as the storage size is 4 bytes and used values are clamped to 0-255
_endColor = MIN<int16>(255, endColor);
}
diff --git a/engines/sci/graphics/video32.h b/engines/sci/graphics/video32.h
index 7b2cffa..ce5e4ba 100644
--- a/engines/sci/graphics/video32.h
+++ b/engines/sci/graphics/video32.h
@@ -331,7 +331,7 @@ public:
*/
VMDStatus getStatus() const;
- // NOTE: Was WaitForEvent in SSCI
+ // Was WaitForEvent in SSCI
EventFlags kernelPlayUntilEvent(const EventFlags flags, const int16 lastFrameNo, const int16 yieldInterval);
private:
@@ -347,7 +347,8 @@ private:
/**
* The Resource object for VMDs that are read out of a resource bundle
- * instead of being streamed from the filesystem.
+ * instead of being streamed from the filesystem. The resource is owned by
+ * ResourceManager.
*/
Resource *_bundledVmd;
@@ -399,12 +400,13 @@ protected:
private:
/**
- * The plane where the VMD will be drawn.
+ * The plane where the VMD will be drawn. The plane is owned by GfxFrameout.
*/
Plane *_plane;
/**
- * The screen item representing the VMD surface.
+ * The screen item representing the VMD surface. The screen item is owned by
+ * GfxFrameout.
*/
ScreenItem *_screenItem;
@@ -538,7 +540,7 @@ private:
/**
* An optional plane that will be used to black out areas of the screen
- * outside of the VMD surface.
+ * outside of the VMD surface. The plane is owned by GfxFrameout.
*/
Plane *_blackoutPlane;
@@ -675,6 +677,7 @@ protected:
private:
/**
* An empty plane drawn behind the video when the doFrameOut flag is true.
+ * The plane is owned by GfxFrameout.
*/
Plane *_plane;
Commit: f51b158f8cc7cb40eb56904e475aae89ac5e55a4
https://github.com/scummvm/scummvm/commit/f51b158f8cc7cb40eb56904e475aae89ac5e55a4
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:10:51-05:00
Commit Message:
SCI32: Clean up GfxFrameout
* Rewrap doxygen comments to 80 columns
* Swap public/private sections so public APIs come first
* Clarify comments where easily possible
Changed paths:
engines/sci/engine/kgraphics32.cpp
engines/sci/graphics/frameout.cpp
engines/sci/graphics/frameout.h
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index d093c55..1734221 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -102,9 +102,9 @@ reg_t kBaseSetter32(EngineState *s, int argc, reg_t *argv) {
reg_t kSetNowSeen32(EngineState *s, int argc, reg_t *argv) {
const bool found = g_sci->_gfxFrameout->kernelSetNowSeen(argv[0]);
- // NOTE: MGDX is assumed to use the older kSetNowSeen since it was
- // released before SQ6, but this has not been verified since it cannot be
- // disassembled at the moment (Phar Lap Windows-only release)
+ // MGDX is assumed to use the older kSetNowSeen since it was released before
+ // SQ6, but this has not been verified since it cannot be disassembled at
+ // the moment (Phar Lap Windows-only release)
// (See also getNowSeenRect)
if (getSciVersion() <= SCI_VERSION_2_1_EARLY ||
g_sci->getGameId() == GID_SQ6 ||
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index f2ae0df..a8746ee 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -119,9 +119,9 @@ void GfxFrameout::run() {
ScreenItem::init();
GfxText32::init();
- // NOTE: This happens in SCI::InitPlane in the actual engine,
- // and is a background fill plane to ensure hidden planes
- // (planes with a priority of -1) are never drawn
+ // This plane is created in SCI::InitPlane in SSCI, and is a background fill
+ // plane to ensure "hidden" planes (planes with negative priority) are never
+ // drawn
Plane *initPlane = new Plane(Common::Rect(_currentBuffer.scriptWidth, _currentBuffer.scriptHeight));
initPlane->_priority = 0;
_planes.add(initPlane);
@@ -296,8 +296,8 @@ void GfxFrameout::kernelDeletePlane(const reg_t object) {
}
if (plane->_created) {
- // NOTE: The original engine calls some `AbortPlane` function that
- // just ends up doing this anyway so we skip the extra indirection
+ // SSCI calls some `AbortPlane` function that just ends up doing this
+ // anyway, so we skip the extra indirection
_planes.erase(plane);
} else {
plane->_created = 0;
@@ -331,8 +331,8 @@ void GfxFrameout::kernelMovePlaneItems(const reg_t object, const int16 deltaX, c
for (ScreenItemList::iterator it = plane->_screenItemList.begin(); it != plane->_screenItemList.end(); ++it) {
ScreenItem &screenItem = **it;
- // If object is a number, the screen item from the
- // engine, not a script, and should be ignored
+ // If object is a number, the screen item from the engine, not a script,
+ // and should be ignored
if (screenItem._object.isNumber()) {
continue;
}
@@ -365,14 +365,14 @@ void GfxFrameout::addPlane(Plane *plane) {
}
void GfxFrameout::updatePlane(Plane &plane) {
- // NOTE: This assertion comes from SCI engine code.
+ // This assertion comes from SSCI
assert(_planes.findByObject(plane._object) == &plane);
Plane *visiblePlane = _visiblePlanes.findByObject(plane._object);
plane.sync(visiblePlane, _screenRect);
- // NOTE: updateScreenRect was originally called a second time here,
- // but it is already called at the end of the Plane::Update call
- // in the original engine anyway.
+ // updateScreenRect was called a second time here in SSCI, but it is already
+ // called at the end of the sync call (also in SSCI) so there is no reason
+ // to do it again
_planes.sort();
}
@@ -401,8 +401,8 @@ void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &eraseR
robotPlayer.doRobot();
}
- // NOTE: The original engine allocated these as static arrays of 100
- // pointers to ScreenItemList / RectList
+ // SSCI allocated these as static arrays of 100 pointers to
+ // ScreenItemList / RectList
ScreenItemListList screenItemLists;
EraseListList eraseLists;
@@ -459,8 +459,8 @@ void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, PlaneShowStyle *show
_showList.add(rect);
showBits();
- // NOTE: The original engine allocated these as static arrays of 100
- // pointers to ScreenItemList / RectList
+ // SSCI allocated these as static arrays of 100 pointers to
+ // ScreenItemList / RectList
ScreenItemListList screenItemLists;
EraseListList eraseLists;
@@ -651,8 +651,7 @@ int splitRectsForRender(Common::Rect &middleRect, const Common::Rect &showRect,
return splitCount;
}
-// NOTE: The third rectangle parameter is only ever given a non-empty rect
-// by VMD code, via `frameOut`
+// The third rectangle parameter is only ever passed by VMD code
void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseLists, const Common::Rect &eraseRect) {
RectList eraseList;
Common::Rect outRects[4];
@@ -670,8 +669,8 @@ void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseL
const Plane *outerPlane = _planes[outerPlaneIndex];
const Plane *visiblePlane = _visiblePlanes.findByObject(outerPlane->_object);
- // NOTE: SSCI only ever checks for kPlaneTypeTransparent here, even
- // though kPlaneTypeTransparentPicture is also a transparent plane
+ // SSCI only ever checks for kPlaneTypeTransparent here, even though
+ // kPlaneTypeTransparentPicture is also a transparent plane
if (outerPlane->_type == kPlaneTypeTransparent) {
foundTransparentPlane = true;
}
@@ -741,7 +740,6 @@ void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseL
}
}
- // clean up deleted planes
if (deletedPlaneCount) {
for (int planeIndex = planeCount - 1; planeIndex >= 0; --planeIndex) {
Plane *plane = _planes[planeIndex];
@@ -866,7 +864,7 @@ void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseL
}
}
- // NOTE: SSCI only looks for kPlaneTypeTransparent, not
+ // SSCI really only looks for kPlaneTypeTransparent, not
// kPlaneTypeTransparentPicture
if (foundTransparentPlane) {
for (PlaneList::size_type planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
@@ -913,8 +911,6 @@ void GfxFrameout::drawScreenItemList(const DrawList &screenItemList) {
const DrawItem &drawItem = *screenItemList[i];
mergeToShowList(drawItem.rect, _showList, _overdrawThreshold);
const ScreenItem &screenItem = *drawItem.screenItem;
- // TODO: Remove
-// debug("Drawing item %04x:%04x to %d %d %d %d", PRINT_REG(screenItem._object), PRINT_RECT(drawItem.rect));
CelObj &celObj = *screenItem._celObj;
celObj.draw(_currentBuffer, screenItem, drawItem.rect, screenItem._mirrorX ^ celObj._mirrorX);
}
@@ -986,9 +982,8 @@ void GfxFrameout::showBits() {
for (RectList::const_iterator rect = _showList.begin(); rect != _showList.end(); ++rect) {
Common::Rect rounded(**rect);
- // NOTE: SCI engine used BR-inclusive rects so used slightly
- // different masking here to ensure that the width of rects
- // was always even.
+ // SSCI uses BR-inclusive rects so has slightly different masking here
+ // to ensure that the width of rects is always even
rounded.left &= ~1;
rounded.right = (rounded.right + 1) & ~1;
_cursor->gonnaPaint(rounded);
@@ -998,9 +993,8 @@ void GfxFrameout::showBits() {
for (RectList::const_iterator rect = _showList.begin(); rect != _showList.end(); ++rect) {
Common::Rect rounded(**rect);
- // NOTE: SCI engine used BR-inclusive rects so used slightly
- // different masking here to ensure that the width of rects
- // was always even.
+ // SSCI uses BR-inclusive rects so has slightly different masking here
+ // to ensure that the width of rects is always even
rounded.left &= ~1;
rounded.right = (rounded.right + 1) & ~1;
@@ -1094,9 +1088,9 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co
int8 styleRangeValue = styleRanges[currentValue];
if (styleRangeValue == -1 && styleRangeValue == style) {
currentValue = pixels[pixelIndex] = clut[currentValue];
- // NOTE: In original engine this assignment happens outside of the
- // condition, but if the branch is not followed the value is just
- // going to be the same as it was before
+ // In SSCI this assignment happens outside of the condition, but if
+ // the branch is not followed the value is just going to be the same
+ // as it was before, so we do it here instead
styleRangeValue = styleRanges[currentValue];
}
@@ -1110,7 +1104,7 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co
}
void GfxFrameout::updateScreen(const int delta) {
- // using OSystem::getMillis instead of Sci::getTickCount because these
+ // Using OSystem::getMillis instead of Sci::getTickCount here because these
// values need to be monotonically increasing for the duration of the
// GfxFrameout object or else the screen will stop updating
const uint32 now = g_system->getMillis() * 60 / 1000;
@@ -1199,13 +1193,12 @@ reg_t GfxFrameout::kernelIsOnMe(const reg_t object, const Common::Point &positio
return make_reg(0, 0);
}
- // NOTE: The original engine passed a copy of the ScreenItem into isOnMe
- // as a hack around the fact that the screen items in `_visiblePlanes`
- // did not have their `_celObj` pointers cleared when their CelInfo was
- // updated by `Plane::decrementScreenItemArrayCounts`. We handle this
- // this more intelligently by clearing `_celObj` in the copy assignment
- // operator, which is only ever called by `decrementScreenItemArrayCounts`
- // anyway.
+ // SSCI passed a copy of the ScreenItem into isOnMe as a hack around the
+ // fact that the screen items in `_visiblePlanes` did not have their
+ // `_celObj` pointers cleared when their CelInfo was updated by
+ // `Plane::decrementScreenItemArrayCounts`. We handle this this more
+ // intelligently by clearing `_celObj` in the copy assignment operator,
+ // which is only ever called by `decrementScreenItemArrayCounts` anyway.
return make_reg(0, isOnMe(*screenItem, *plane, position, checkPixel));
}
@@ -1271,9 +1264,9 @@ bool GfxFrameout::getNowSeenRect(const reg_t screenItemObject, Common::Rect &res
const ScreenItem *screenItem = plane->_screenItemList.findByObject(screenItemObject);
if (screenItem == nullptr) {
- // NOTE: MGDX is assumed to use the older getNowSeenRect since it was
- // released before SQ6, but this has not been verified since it cannot
- // be disassembled at the moment (Phar Lap Windows-only release)
+ // MGDX is assumed to use the older getNowSeenRect since it was released
+ // before SQ6, but this has not been verified since it cannot be
+ // disassembled at the moment (Phar Lap Windows-only release)
// (See also kSetNowSeen32)
if (getSciVersion() <= SCI_VERSION_2_1_EARLY ||
g_sci->getGameId() == GID_SQ6 ||
diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h
index a7b529f..78bf2e0 100644
--- a/engines/sci/graphics/frameout.h
+++ b/engines/sci/graphics/frameout.h
@@ -37,21 +37,11 @@ class GfxTransitions32;
struct PlaneShowStyle;
/**
- * Frameout class, kFrameout and relevant functions for SCI32 games.
- * Roughly equivalent to GraphicsMgr in the actual SCI engine.
+ * Frameout class, kFrameOut and relevant functions for SCI32 games.
+ * Roughly equivalent to GraphicsMgr in SSCI.
*/
class GfxFrameout {
friend class GfxTransitions32;
-private:
- GfxCursor32 *_cursor;
- GfxPalette32 *_palette;
- SegManager *_segMan;
-
- /**
- * Determines whether the current game should be rendered in
- * high resolution.
- */
- bool gameIsHiRes() const;
public:
GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor);
@@ -62,12 +52,20 @@ public:
void clear();
void run();
-#pragma mark -
-#pragma mark Screen items
private:
- void remapMarkRedraw();
- bool getNowSeenRect(const reg_t screenItemObject, Common::Rect &result) const;
+ GfxCursor32 *_cursor;
+ GfxPalette32 *_palette;
+ GfxTransitions32 *_transitions;
+ SegManager *_segMan;
+
+ /**
+ * Determines whether the current game should be rendered in high
+ * resolution.
+ */
+ bool gameIsHiRes() const;
+#pragma mark -
+#pragma mark Screen items
public:
/**
* Adds a screen item.
@@ -100,39 +98,27 @@ public:
bool kernelSetNowSeen(const reg_t screenItemObject) const;
int16 kernelObjectIntersect(const reg_t object1, const reg_t object2) const;
-#pragma mark -
-#pragma mark Planes
private:
- /**
- * The list of planes (i.e. layers) that have been added
- * to the screen.
- *
- * @note This field is on `GraphicsMgr.screen` in SCI
- * engine.
- */
- PlaneList _planes;
-
- /**
- * Updates an existing plane with properties from the
- * given VM object.
- */
- void updatePlane(Plane &plane);
+ void remapMarkRedraw();
+ bool getNowSeenRect(const reg_t screenItemObject, Common::Rect &result) const;
+#pragma mark -
+#pragma mark Planes
public:
/**
* Creates and adds a new plane to the plane list. Ownership of the passed
* object is transferred to GfxFrameout.
*
- * @note This method is on Screen in SCI engine, but it
- * is only ever called on `GraphicsMgr.screen`.
+ * @note This method is on Screen in SSCI, but it is only ever called on
+ * `GraphicsMgr.screen`.
*/
void addPlane(Plane *plane);
/**
* Deletes a plane within the current plane list.
*
- * @note This method is on Screen in SCI engine, but it
- * is only ever called on `GraphicsMgr.screen`.
+ * @note This method is on Screen in SSCI, but it is only ever called on
+ * `GraphicsMgr.screen`.
*/
void deletePlane(Plane &plane);
@@ -148,6 +134,20 @@ public:
void kernelMovePlaneItems(const reg_t object, const int16 deltaX, const int16 deltaY, const bool scrollPics);
int16 kernelGetHighPlanePri();
+private:
+ /**
+ * The list of planes (i.e. layers) that will be rendered to the screen on
+ * the next call to `frameOut`.
+ *
+ * @note This field is on `GraphicsMgr.screen` in SSCI.
+ */
+ PlaneList _planes;
+
+ /**
+ * Updates an existing plane with properties from the given VM object.
+ */
+ void updatePlane(Plane &plane);
+
#pragma mark -
#pragma mark Pics
public:
@@ -155,121 +155,193 @@ public:
#pragma mark -
#pragma mark Rendering
+public:
+ /**
+ * Updates the hardware screen, no more than once per tick.
+ *
+ * @param delta An additional number of ticks that should elapse
+ * since the last time the screen was updated before it gets updated now.
+ * This is used for updating the screen within run_vm, where we normally
+ * expect that a call to kFrameOut will occur later during the current
+ * frame, but if it does not, then update the screen on the second frame
+ * anyway since the game is doing something bad.
+ */
+ void updateScreen(const int delta = 0);
+
+ /**
+ * Resets the pixel format of the hardware surface to the given format.
+ */
+ void setPixelFormat(const Graphics::PixelFormat &format) const {
+ initGraphics(_currentBuffer.screenWidth, _currentBuffer.screenHeight, _isHiRes, &format);
+ }
+
+ /**
+ * Whether or not to throttle kFrameOut calls.
+ */
+ bool _throttleKernelFrameOut;
+
+ /**
+ * Whether `palMorphFrameOut` should be used instead of `frameOut` for
+ * rendering. Used by `kMorphOn` to explicitly enable `palMorphFrameOut` for
+ * one frame.
+ */
+ bool _palMorphIsOn;
+
+ inline const Buffer &getCurrentBuffer() const {
+ return _currentBuffer;
+ }
+
+ void kernelFrameOut(const bool showBits);
+
+ /**
+ * Throttles the engine as necessary to maintain 60fps output.
+ */
+ void throttle();
+
+ /**
+ * Updates the internal screen buffer for the next frame. If
+ * `shouldShowBits` is true, also sends the buffer to hardware. If
+ * `eraseRect` is non-empty, it is added to the erase list for this frame.
+ */
+ void frameOut(const bool shouldShowBits, const Common::Rect &eraseRect = Common::Rect());
+
+ /**
+ * TODO: Documentation
+ */
+ void palMorphFrameOut(const int8 *styleRanges, PlaneShowStyle *showStyle);
+
+ /**
+ * Draws the given rect from the internal screen buffer to hardware without
+ * processing any other graphics updates except for cursor changes.
+ */
+ void directFrameOut(const Common::Rect &showRect);
+
+#ifdef USE_RGB_COLOR
+ /**
+ * Sends the entire internal screen buffer and palette to hardware.
+ */
+ void resetHardware();
+#endif
+
+ /**
+ * Modifies the raw pixel data for the next frame with new palette indexes
+ * based on matched style ranges.
+ */
+ void alterVmap(const Palette &palette1, const Palette &palette2, const int8 style, const int8 *const styleRanges);
+
+ // This function is used within ScreenItem subsystem and assigned to various
+ // booleanish fields that seem to represent the state of the screen item
+ // (created, updated, deleted). In GK1/DOS, Phant1/m68k, SQ6/DOS, SQ6/Win,
+ // and Phant2/Win, this function simply returns 1. If you know of any
+ // game/environment where this function returns some value other than 1, or
+ // if you used to work at Sierra and can explain why this is a thing (and if
+ // anyone needs to care about it), please open a ticket!!
+ inline int getScreenCount() const {
+ return 1;
+ };
+
+ /**
+ * Shakes the screen.
+ */
+ void shakeScreen(const int16 numShakes, const ShakeDirection direction);
+
private:
/**
* The last time the hardware screen was updated.
*/
uint32 _lastScreenUpdateTick;
- GfxTransitions32 *_transitions;
-
/**
- * State tracker to provide more accurate 60fps
- * video throttling.
+ * State tracker to provide more accurate 60fps video throttling.
*/
uint8 _throttleState;
/**
- * The internal display pixel buffer. During frameOut,
- * this buffer is drawn into according to the draw and
- * erase rects calculated by `calcLists`, then drawn out
- * to the hardware surface according to the `_showList`
- * rects (which are also calculated by `calcLists`).
+ * The internal display pixel buffer. During `frameOut`, this buffer is
+ * drawn into according to the draw and erase rects calculated by
+ * `calcLists`, then drawn out to the hardware surface according to the
+ * `_showList` rects (which are also calculated by `calcLists`).
*/
Buffer _currentBuffer;
/**
- * When true, a change to the remap zone in the palette
- * has occurred and screen items with remap data need to
- * be redrawn.
+ * When true, a change to the remap zone in the palette has occurred and
+ * screen items with remap data need to be redrawn.
*/
bool _remapOccurred;
/**
- * TODO: Document
- * TODO: Depending upon if the engine ever modifies this
- * rect, it may be stupid to store it separately instead
- * of just getting width/height from GfxScreen.
+ * The dimensions of the output buffer, in display coordinates.
*
- * @note This field is on `GraphicsMgr.screen` in SCI
- * engine.
+ * @note This field is on `GraphicsMgr.screen` in SSCI.
*/
Common::Rect _screenRect;
/**
- * A list of rectangles, in display coordinates, that
- * represent portions of the internal screen buffer that
- * should be drawn to the hardware display surface.
+ * A list of rectangles, in screen coordinates, that represent portions of
+ * the internal screen buffer that are dirty and should be drawn to the
+ * hardware display surface.
*
- * @note This field is on `GraphicsMgr.screen` in SCI
- * engine.
+ * @note This field is on `GraphicsMgr.screen` in SSCI.
*/
RectList _showList;
/**
- * The amount of extra overdraw that is acceptable when
- * merging two show list rectangles together into a
- * single larger rectangle.
+ * The amount of extra overdraw that is acceptable when merging two show
+ * list rectangles together into a single larger rectangle.
*
- * @note This field is on `GraphicsMgr.screen` in SCI
- * engine.
+ * @note This field is on `GraphicsMgr.screen` in SSCI.
*/
int _overdrawThreshold;
/**
- * A list of planes that are currently drawn to the
- * hardware display surface. Used to calculate
- * differences in plane properties between the last
- * frame and current frame.
+ * The list of planes that are currently drawn to the hardware display
+ * surface. Used to calculate differences in plane properties between the
+ * last frame and current frame.
*
- * @note This field is on `GraphicsMgr.visibleScreen` in
- * SCI engine.
+ * @note This field is on `GraphicsMgr.visibleScreen` in SSCI.
*/
PlaneList _visiblePlanes;
/**
- * Calculates the location and dimensions of dirty rects
- * over the entire screen for rendering the next frame.
- * The draw and erase lists in `drawLists` and
- * `eraseLists` each represent one plane on the screen.
- * The optional `eraseRect` argument allows a specific
- * area of the screen to be erased.
+ * Calculates the location and dimensions of dirty rects over the entire
+ * screen for rendering the next frame. The draw and erase lists in
+ * `drawLists` and `eraseLists` each represent one plane on the screen.
+ * The optional `eraseRect` argument allows a specific area of the screen to
+ * be explicitly erased.
*/
void calcLists(ScreenItemListList &drawLists, EraseListList &eraseLists, const Common::Rect &eraseRect = Common::Rect());
/**
- * Erases the areas in the given erase list from the
- * visible screen buffer by filling them with the color
- * from the corresponding plane. This is an optimisation
- * for colored-type planes only; other plane types have
- * to be redrawn from pixel data.
+ * Erases the areas in the given erase list from the visible screen buffer
+ * by filling them with the color from the corresponding plane. This is an
+ * optimisation for colored-type planes only; other plane types have to be
+ * redrawn from pixel data.
*/
void drawEraseList(const RectList &eraseList, const Plane &plane);
/**
- * Draws all screen items from the given draw list to
- * the visible screen buffer.
+ * Draws all screen items from the given draw list to the visible screen
+ * buffer.
*/
void drawScreenItemList(const DrawList &screenItemList);
/**
- * Adds a new rectangle to the list of regions to write
- * out to the hardware. The provided rect may be merged
- * into an existing rectangle to reduce the number of
- * blit operations.
+ * Adds a new rectangle to the list of regions to write out to the hardware.
+ * The provided rect may be merged into an existing rectangle to reduce the
+ * number of blit operations.
*/
void mergeToShowList(const Common::Rect &drawRect, RectList &showList, const int overdrawThreshold);
/**
- * Sends all dirty rects from the internal frame buffer to the backend,
- * then updates the hardware screen.
+ * Sends all dirty rects from the internal frame buffer to the backend, then
+ * updates the hardware screen.
*/
void showBits();
/**
- * Validates whether the given palette index in the
- * style range should copy a color from the next
- * palette to the source palette during a palette
+ * Validates whether the given palette index in the style range should copy
+ * a color from the next palette to the source palette during a palette
* morph operation.
*/
inline bool validZeroStyle(const uint8 style, const int i) const {
@@ -290,101 +362,11 @@ private:
}
}
-public:
- /**
- * Updates the hardware screen, no more than once per tick.
- *
- * @param delta An additional number of ticks that should elapse
- * since the last time the screen was updated before it gets updated now.
- * This is used for updating the screen within run_vm, where we normally
- * expect that a call to kFrameOut will occur later during the current
- * frame, but if it does not, then update the screen on the second frame
- * anyway since the game is doing something bad.
- */
- void updateScreen(const int delta = 0);
-
- /**
- * Resets the pixel format of the hardware surface to the given format.
- */
- void setPixelFormat(const Graphics::PixelFormat &format) const {
- initGraphics(_currentBuffer.screenWidth, _currentBuffer.screenHeight, _isHiRes, &format);
- }
-
- /**
- * Whether or not to throttle kFrameOut calls.
- */
- bool _throttleKernelFrameOut;
-
- /**
- * Whether palMorphFrameOut should be used instead of
- * frameOut for rendering. Used by kMorphOn to
- * explicitly enable palMorphFrameOut for one frame.
- */
- bool _palMorphIsOn;
-
- inline const Buffer &getCurrentBuffer() const {
- return _currentBuffer;
- }
-
- void kernelFrameOut(const bool showBits);
-
- /**
- * Throttles the engine as necessary to maintain
- * 60fps output.
- */
- void throttle();
-
- /**
- * Updates the internal screen buffer for the next
- * frame. If `shouldShowBits` is true, also sends the
- * buffer to hardware. If `eraseRect` is non-empty,
- * it is added to the erase list for this frame.
- */
- void frameOut(const bool shouldShowBits, const Common::Rect &eraseRect = Common::Rect());
-
- /**
- * TODO: Documentation
- */
- void palMorphFrameOut(const int8 *styleRanges, PlaneShowStyle *showStyle);
-
- /**
- * Draws the given rect from the internal screen buffer to hardware without
- * processing any other graphics updates except for cursor changes.
- */
- void directFrameOut(const Common::Rect &showRect);
-
-#ifdef USE_RGB_COLOR
- /**
- * Sends the entire internal screen buffer and palette to hardware.
- */
- void resetHardware();
-#endif
-
- /**
- * Modifies the raw pixel data for the next frame with
- * new palette indexes based on matched style ranges.
- */
- void alterVmap(const Palette &palette1, const Palette &palette2, const int8 style, const int8 *const styleRanges);
-
- // NOTE: This function is used within ScreenItem subsystem and assigned
- // to various booleanish fields that seem to represent the state of the
- // screen item (created, updated, deleted). In GK1/DOS, Phant1/m68k,
- // SQ6/DOS, SQ6/Win, and Phant2/Win, this function simply returns 1. If
- // you know of any game/environment where this function returns some
- // value other than 1, or if you used to work at Sierra and can explain
- // why this is a thing (and if anyone needs to care about it), please
- // open a ticket!!
- inline int getScreenCount() const {
- return 1;
- };
-
- /**
- * Shakes the screen.
- */
- void shakeScreen(const int16 numShakes, const ShakeDirection direction);
-
#pragma mark -
#pragma mark Mouse cursor
+public:
+ reg_t kernelIsOnMe(const reg_t object, const Common::Point &position, const bool checkPixel) const;
+
private:
void updateMousePositionForRendering() const {
// In SSCI, mouse events were received via hardware interrupt, so the
@@ -398,14 +380,11 @@ private:
}
/**
- * Determines whether or not the point given by
- * `position` is inside of the given screen item.
+ * Determines whether or not the point given by `position` is inside of the
+ * given screen item.
*/
bool isOnMe(const ScreenItem &screenItem, const Plane &plane, const Common::Point &position, const bool checkPixel) const;
-public:
- reg_t kernelIsOnMe(const reg_t object, const Common::Point &position, const bool checkPixel) const;
-
#pragma mark -
#pragma mark Debugging
public:
Commit: 93c8044f690306e23b5b3eb621207fbf57682c40
https://github.com/scummvm/scummvm/commit/93c8044f690306e23b5b3eb621207fbf57682c40
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:10:52-05:00
Commit Message:
SCI32: Clean up Audio32
* Rewrap comments to 80 columns
* Remove resolved TODOs
* Use containers and smart pointers where appropriate
Changed paths:
engines/sci/engine/ksound.cpp
engines/sci/sound/audio32.cpp
engines/sci/sound/audio32.h
engines/sci/sound/soundcmd.cpp
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index bbfadf1..4d171bd 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -384,10 +384,6 @@ reg_t kDoAudioPosition(EngineState *s, int argc, reg_t *argv) {
}
reg_t kDoAudioRate(EngineState *s, int argc, reg_t *argv) {
- // NOTE: In the original engine this would set the hardware
- // DSP sampling rate; ScummVM mixer does not need this, so
- // we only store the value to satisfy engine compatibility.
-
if (argc > 0) {
const uint16 sampleRate = argv[0].toUint16();
if (sampleRate != 0) {
@@ -407,10 +403,6 @@ reg_t kDoAudioGetCapability(EngineState *s, int argc, reg_t *argv) {
}
reg_t kDoAudioBitDepth(EngineState *s, int argc, reg_t *argv) {
- // NOTE: In the original engine this would set the hardware
- // DSP bit depth; ScummVM mixer does not need this, so
- // we only store the value to satisfy engine compatibility.
-
if (argc > 0) {
const uint16 bitDepth = argv[0].toUint16();
if (bitDepth != 0) {
@@ -426,10 +418,6 @@ reg_t kDoAudioMixing(EngineState *s, int argc, reg_t *argv) {
}
reg_t kDoAudioChannels(EngineState *s, int argc, reg_t *argv) {
- // NOTE: In the original engine this would set the hardware
- // DSP stereo output; ScummVM mixer does not need this, so
- // we only store the value to satisfy engine compatibility.
-
if (argc > 0) {
const int16 numChannels = argv[0].toSint16();
if (numChannels != 0) {
@@ -441,11 +429,6 @@ reg_t kDoAudioChannels(EngineState *s, int argc, reg_t *argv) {
}
reg_t kDoAudioPreload(EngineState *s, int argc, reg_t *argv) {
- // NOTE: In the original engine this would cause audio
- // data for new channels to be preloaded to memory when
- // the channel was initialized; we do not need this, so
- // we only store the value to satisfy engine compatibility.
-
if (argc > 0) {
g_sci->_audio32->setPreload(argv[0].toUint16());
}
@@ -477,11 +460,8 @@ reg_t kDoAudioPanOff(EngineState *s, int argc, reg_t *argv) {
}
reg_t kSetLanguage(EngineState *s, int argc, reg_t *argv) {
- // This is used by script 90 of MUMG Deluxe from the main menu to toggle
- // the audio language between English and Spanish.
- // Basically, it instructs the interpreter to switch the audio resources
- // (resource.aud and associated map files) and load them from the "Spanish"
- // subdirectory instead.
+ // Used by script 90 of MUMG Deluxe from the main menu to toggle between
+ // English and Spanish.
const Common::String audioDirectory = s->_segMan->getString(argv[0]);
g_sci->getResMan()->changeAudioDirectory(audioDirectory);
return s->r_acc;
diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index 59ebc86..f9a0140 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -153,6 +153,7 @@ Audio32::Audio32(ResourceManager *resMan) :
_handle(),
_mutex(),
+ _channels(getSciVersion() < SCI_VERSION_2_1_EARLY ? 10 : getSciVersion() < SCI_VERSION_3 ? 5 : 8),
_numActiveChannels(0),
_inAudioThread(false),
@@ -170,22 +171,10 @@ Audio32::Audio32(ResourceManager *resMan) :
_startedAtTick(0),
_attenuatedMixing(true),
+ _useModifiedAttenuation(g_sci->_features->usesModifiedAudioAttenuation()),
_monitoredChannelIndex(-1),
- _monitoredBuffer(nullptr),
- _monitoredBufferSize(0),
_numMonitoredSamples(0) {
-
- if (getSciVersion() < SCI_VERSION_2_1_EARLY) {
- _channels.resize(10);
- } else if (getSciVersion() < SCI_VERSION_3) {
- _channels.resize(5);
- } else {
- _channels.resize(8);
- }
-
- _useModifiedAttenuation = g_sci->_features->usesModifiedAudioAttenuation();
-
// In games where scripts premultiply master audio volumes into the volumes
// of the individual audio channels sent to the mixer, Audio32 needs to use
// the kPlainSoundType so that the master SFX volume is not applied twice.
@@ -202,15 +191,14 @@ Audio32::Audio32(ResourceManager *resMan) :
Audio32::~Audio32() {
stop(kAllChannels);
_mixer->stopHandle(_handle);
- free(_monitoredBuffer);
}
#pragma mark -
#pragma mark AudioStream implementation
-int Audio32::writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::RateConverter *const converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume) {
+int Audio32::writeAudioInternal(Audio::AudioStream &sourceStream, Audio::RateConverter &converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume) {
const int samplePairsToRead = numSamples >> 1;
- const int samplePairsWritten = converter->flow(*sourceStream, targetBuffer, samplePairsToRead, leftVolume, rightVolume);
+ const int samplePairsWritten = converter.flow(sourceStream, targetBuffer, samplePairsToRead, leftVolume, rightVolume);
return samplePairsWritten << 1;
}
@@ -243,34 +231,28 @@ bool Audio32::channelShouldMix(const AudioChannel &channel) const {
return true;
}
-// In earlier versions of SCI32 engine, audio mixing is
-// split into three different functions.
+// In earlier versions of SCI32 engine, audio mixing is split into three
+// different functions.
//
-// The first function is called from the main game thread in
-// AsyncEventCheck; later versions of SSCI also call it when
-// getting the playback position. This function is
-// responsible for cleaning up finished channels and
-// filling active channel buffers with decompressed audio
-// matching the hardware output audio format so they can
-// just be copied into the main DAC buffer directly later.
+// The first function is called from the main game thread in AsyncEventCheck;
+// later versions of SSCI also call it when getting the playback position. This
+// function is responsible for cleaning up finished channels and filling active
+// channel buffers with decompressed audio matching the hardware output audio
+// format so they can just be copied into the main DAC buffer directly later.
//
-// The second function is called by the audio hardware when
-// the DAC buffer needs to be filled, and by `play` when
-// there is only one active sample (so it can just blow away
-// whatever was already in the DAC buffer). It merges all
-// active channels into the DAC buffer and then updates the
-// offset into the DAC buffer.
+// The second function is called by the audio hardware when the DAC buffer needs
+// to be filled, and by `play` when there is only one active sample (so it can
+// just blow away whatever was already in the DAC buffer). It merges all active
+// channels into the DAC buffer and then updates the offset into the DAC buffer.
//
-// Finally, a third function is called by the second
-// function, and it actually puts data into the DAC buffer,
-// performing volume, distortion, and balance adjustments.
+// Finally, a third function is called by the second function, and it actually
+// puts data into the DAC buffer, performing volume, distortion, and balance
+// adjustments.
//
-// Since we only have one callback from the audio thread,
-// and should be able to do all audio processing in
-// real time, and we have streams, and we do not need to
-// completely fill the audio buffer, the functionality of
-// all these original functions is combined here and
-// simplified.
+// Since we only have one callback from the audio thread, and should be able to
+// do all audio processing in real time, and we have streams, and we do not need
+// to completely fill the audio buffer, the functionality of all these original
+// functions is combined here and simplified.
int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples) {
Common::StackLock lock(_mutex);
@@ -278,20 +260,17 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples)
return 0;
}
- // ResourceManager is not thread-safe so we need to
- // avoid calling into it from the audio thread, but at
- // the same time we need to be able to clear out any
- // finished channels on a regular basis
+ // ResourceManager is not thread-safe so we need to avoid calling into it
+ // from the audio thread, but at the same time we need to be able to clear
+ // out any finished channels on a regular basis
_inAudioThread = true;
freeUnusedChannels();
const bool playOnlyMonitoredChannel = getSciVersion() != SCI_VERSION_3 && _monitoredChannelIndex != -1;
- // The caller of `readBuffer` is a rate converter,
- // which reuses (without clearing) an intermediate
- // buffer, so we need to zero the intermediate buffer
- // to prevent mixing into audio data from the last
- // callback.
+ // The caller of `readBuffer` is a rate converter, which reuses (without
+ // clearing) an intermediate buffer, so we need to zero the intermediate
+ // buffer to prevent mixing into audio data from the last callback.
memset(buffer, 0, numSamples * sizeof(Audio::st_sample_t));
// This emulates the attenuated mixing mode of SSCI engine, which reduces
@@ -340,8 +319,8 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples)
continue;
}
- // Channel finished fading and had the
- // stopChannelOnFade flag set, so no longer exists
+ // Channel finished fading and had the stopChannelOnFade flag set, so no
+ // longer exists
if (channel.fadeStartTick && processFade(channelIndex)) {
--channelIndex;
continue;
@@ -352,10 +331,10 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples)
if (channel.pan == -1 || !isStereo()) {
int volume = channel.volume;
if (getSciVersion() == SCI_VERSION_2) {
- // NOTE: In SSCI, audio is decompressed into a temporary
- // buffer, then the samples in that buffer are looped over,
- // shifting each sample right 3, 2, or 1 bits to reduce the
- // volume.
+ // In SSCI, audio is decompressed into a temporary buffer, then
+ // the samples in that buffer are looped over, shifting each
+ // sample right 3, 2, or 1 bits to reduce the volume within the
+ // ranges given here
if (volume > 0 && volume <= 42) {
volume = 15;
} else if (volume > 42 && volume <= 84) {
@@ -367,20 +346,18 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples)
// In SCI3, granularity of the non-maximum volumes is 1/32
volume &= ~4;
- // NOTE: In the SSCI DOS interpreter, non-maximum volumes are
- // divided by 8 which puts them in a range of [0, 16). That
- // reduced volume range gets passed into a volume function which
- // expects values [0, 32). So, effectively, all non-maximum
- // volumes are half-volume in DOS in SCI3. In Windows, volumes
- // [120, 124) are the same as 127 due to a programming bug.
- // We do not emulate either of these incorrect behaviors.
+ // In the SSCI DOS interpreter, non-maximum volumes are divided
+ // by 8 which puts them in a range of [0, 16). That reduced
+ // volume range gets passed into a volume function which expects
+ // values [0, 32). So, effectively, all non-maximum volumes are
+ // half-volume in DOS in SCI3 due to a programming bug. In
+ // Windows, volumes [120, 124) are the same as 127 due to
+ // another programming bug. We do not emulate either of these
+ // incorrect behaviors.
}
leftVolume = rightVolume = volume * Audio::Mixer::kMaxChannelVolume / kMaxVolume;
} else {
- // TODO: This should match the SCI3 algorithm,
- // which seems to halve the volume of each
- // channel when centered; is this intended?
leftVolume = channel.volume * (100 - channel.pan) / 100 * Audio::Mixer::kMaxChannelVolume / kMaxVolume;
rightVolume = channel.volume * channel.pan / 100 * Audio::Mixer::kMaxChannelVolume / kMaxVolume;
}
@@ -397,19 +374,15 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples)
}
if (channelIndex == _monitoredChannelIndex) {
- const size_t bufferSize = numSamples * sizeof(Audio::st_sample_t);
- if (_monitoredBufferSize < bufferSize) {
- _monitoredBuffer = (Audio::st_sample_t *)realloc(_monitoredBuffer, bufferSize);
- _monitoredBufferSize = bufferSize;
+ if (numSamples > (int)_monitoredBuffer.size()) {
+ _monitoredBuffer.resize(numSamples);
}
+ memset(_monitoredBuffer.data(), 0, _monitoredBuffer.size() * sizeof(Audio::st_sample_t));
+ _numMonitoredSamples = writeAudioInternal(*channel.stream, *channel.converter, _monitoredBuffer.data(), numSamples, leftVolume, rightVolume);
- memset(_monitoredBuffer, 0, _monitoredBufferSize);
-
- _numMonitoredSamples = writeAudioInternal(channel.stream, channel.converter, _monitoredBuffer, numSamples, leftVolume, rightVolume);
-
- Audio::st_sample_t *sourceBuffer = _monitoredBuffer;
+ Audio::st_sample_t *sourceBuffer = _monitoredBuffer.data();
Audio::st_sample_t *targetBuffer = buffer;
- const Audio::st_sample_t *const end = _monitoredBuffer + _numMonitoredSamples;
+ const Audio::st_sample_t *const end = _monitoredBuffer.data() + _numMonitoredSamples;
while (sourceBuffer != end) {
Audio::clampedAdd(*targetBuffer++, *sourceBuffer++);
}
@@ -428,7 +401,7 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples)
leftVolume = rightVolume = 0;
}
- const int channelSamplesWritten = writeAudioInternal(channel.stream, channel.converter, buffer, numSamples, leftVolume, rightVolume);
+ const int channelSamplesWritten = writeAudioInternal(*channel.stream, *channel.converter, buffer, numSamples, leftVolume, rightVolume);
if (channelSamplesWritten > maxSamplesWritten) {
maxSamplesWritten = channelSamplesWritten;
}
@@ -458,10 +431,9 @@ uint8 Audio32::getNumUnlockedChannels() const {
}
int16 Audio32::findChannelByArgs(int argc, const reg_t *argv, const int startIndex, const reg_t soundNode) const {
- // NOTE: argc/argv are already reduced by one in our engine because
- // this call is always made from a subop, so no reduction for the
- // subop is made in this function. SSCI takes extra steps to skip
- // the subop argument.
+ // SSCI takes extra steps to skip the subop argument here, but argc/argv are
+ // already reduced by one in our engine by the kernel since these calls are
+ // always subops so we do not need to do anything extra
argc -= startIndex;
if (argc <= 0) {
@@ -501,10 +473,10 @@ int16 Audio32::findChannelById(const ResourceId resourceId, const reg_t soundNod
if (resourceId.getType() == kResourceTypeAudio) {
for (int16 i = 0; i < _numActiveChannels; ++i) {
- const AudioChannel channel = _channels[i];
+ const AudioChannel &candidate = _channels[i];
if (
- channel.id == resourceId &&
- (soundNode.isNull() || soundNode == channel.soundNode)
+ candidate.id == resourceId &&
+ (soundNode.isNull() || soundNode == candidate.soundNode)
) {
return i;
}
@@ -553,7 +525,7 @@ void Audio32::freeUnusedChannels() {
}
void Audio32::freeChannel(const int16 channelIndex) {
- // The original engine did this:
+ // SSCI did this:
// 1. Unlock memory-cached resource, if one existed
// 2. Close patched audio file descriptor, if one existed
// 3. Free decompression memory buffer, if one existed
@@ -563,14 +535,13 @@ void Audio32::freeChannel(const int16 channelIndex) {
// Robots have no corresponding resource to free
if (channel.robot) {
- delete channel.stream;
- channel.stream = nullptr;
+ channel.stream.reset();
channel.robot = false;
} else {
- // We cannot unlock resources from the audio thread
- // because ResourceManager is not thread-safe; instead,
- // we just record that the resource needs unlocking and
- // unlock it whenever we are on the main thread again
+ // We cannot unlock resources from the audio thread because
+ // ResourceManager is not thread-safe; instead, we just record that the
+ // resource needs unlocking and unlock it whenever we are on the main
+ // thread again
if (_inAudioThread) {
_resourcesToUnlock.push_back(channel.resource);
} else {
@@ -578,12 +549,10 @@ void Audio32::freeChannel(const int16 channelIndex) {
}
channel.resource = nullptr;
- delete channel.stream;
- channel.stream = nullptr;
+ channel.stream.reset();
}
- delete channel.converter;
- channel.converter = nullptr;
+ channel.converter.reset();
if (_monitoredChannelIndex == channelIndex) {
_monitoredChannelIndex = -1;
@@ -677,13 +646,12 @@ bool Audio32::playRobotAudio(const RobotAudioStream::RobotAudioPacket &packet) {
channel.pausedAtTick = 0;
channel.soundNode = NULL_REG;
channel.volume = kMaxVolume;
- // TODO: SCI3 introduces stereo audio
channel.pan = -1;
- channel.converter = Audio::makeRateConverter(RobotAudioStream::kRobotSampleRate, getRate(), false);
+ channel.converter.reset(Audio::makeRateConverter(RobotAudioStream::kRobotSampleRate, getRate(), false));
// The RobotAudioStream buffer size is
// ((bytesPerSample * channels * sampleRate * 2000ms) / 1000ms) & ~3
// where bytesPerSample = 2, channels = 1, and sampleRate = 22050
- channel.stream = new RobotAudioStream(88200);
+ channel.stream.reset(new RobotAudioStream(88200));
_robotAudioPaused = false;
if (_numActiveChannels == 1) {
@@ -691,7 +659,7 @@ bool Audio32::playRobotAudio(const RobotAudioStream::RobotAudioPacket &packet) {
}
}
- return static_cast<RobotAudioStream *>(channel.stream)->addPacket(packet);
+ return static_cast<RobotAudioStream *>(channel.stream.get())->addPacket(packet);
}
bool Audio32::queryRobotAudio(RobotAudioStream::StreamState &status) const {
@@ -703,7 +671,7 @@ bool Audio32::queryRobotAudio(RobotAudioStream::StreamState &status) const {
return false;
}
- status = static_cast<RobotAudioStream *>(getChannel(channelIndex).stream)->getStatus();
+ status = static_cast<RobotAudioStream *>(getChannel(channelIndex).stream.get())->getStatus();
return true;
}
@@ -715,7 +683,7 @@ bool Audio32::finishRobotAudio() {
return false;
}
- static_cast<RobotAudioStream *>(getChannel(channelIndex).stream)->finish();
+ static_cast<RobotAudioStream *>(getChannel(channelIndex).stream.get())->finish();
return true;
}
@@ -741,7 +709,7 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
if (channelIndex != kNoExistingChannel) {
AudioChannel &channel = getChannel(channelIndex);
- MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream);
+ MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream.get());
if (stream == nullptr) {
error("[Audio32::play]: Unable to cast stream for resource %s", resourceId.toString().c_str());
}
@@ -760,43 +728,42 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
return 0;
}
- // NOTE: SCI engine itself normally searches in this order:
+ // SSCI normally searches in this order:
//
// For Audio36:
//
- // 1. First, request a FD using Audio36 name and use it as the
- // source FD for reading the audio resource data.
- // 2a. If the returned FD is -1, or equals the audio map, or
- // equals the audio bundle, try to get the offset of the
- // data from the audio map, using the Audio36 name.
+ // 1. First, request a FD using Audio36 name and use it as the source FD for
+ // reading the audio resource data.
+ // 2a. If the returned FD is -1, or equals the audio map, or equals the
+ // audio bundle, try to get the offset of the data from the audio map,
+ // using the Audio36 name.
//
- // If the returned offset is -1, this is not a valid resource;
- // return 0. Otherwise, set the read offset for the FD to the
- // returned offset.
- // 2b. Otherwise, use the FD as-is (it is a patch file), with zero
- // offset, and record it separately so it can be closed later.
+ // If the returned offset is -1, this is not a valid resource; return 0.
+ // Otherwise, set the read offset for the FD to the returned offset.
+ // 2b. Otherwise, use the FD as-is (it is a patch file), with zero offset,
+ // and record it separately so it can be closed later.
//
// For plain audio:
//
- // 1. First, request an Audio resource from the resource cache. If
- // one does not exist, make the same request for a Wave resource.
- // 2a. If an audio resource was discovered, record its memory ID
- // and clear the streaming FD
- // 2b. Otherwise, request an Audio FD. If one does not exist, make
- // the same request for a Wave FD. If neither exist, this is not
- // a valid resource; return 0. Otherwise, use the returned FD as
- // the streaming ID and set the memory ID to null.
+ // 1. First, request an Audio resource from the resource cache. If one does
+ // not exist, make the same request for a Wave resource.
+ // 2a. If an audio resource was discovered, record its memory ID and clear
+ // the streaming FD
+ // 2b. Otherwise, request an Audio FD. If one does not exist, make the same
+ // request for a Wave FD. If neither exist, this is not a valid
+ // resource; return 0. Otherwise, use the returned FD as the streaming
+ // ID and set the memory ID to null.
//
// Once these steps are complete, the audio engine either has a file
- // descriptor + offset that it can use to read streamed audio, or it
- // has a memory ID that it can use to read cached audio.
+ // descriptor + offset that it can use to read streamed audio, or it has a
+ // memory ID that it can use to read cached audio.
//
- // Here in ScummVM we just ask the resource manager to give us the
- // resource and we get a seekable stream.
+ // Here in ScummVM we just ask the resource manager to give us the resource
+ // and we get a seekable stream.
- // TODO: This should be fixed to use streaming, which means
- // fixing the resource manager to allow streaming, which means
- // probably rewriting a bunch of the resource manager.
+ // TODO: This should be fixed to use streaming, which means fixing the
+ // resource manager to allow streaming, which means probably rewriting a
+ // bunch of the resource manager.
Resource *resource = _resMan->findResource(resourceId, true);
if (resource == nullptr) {
warning("[Audio32::play]: %s could not be found", resourceId.toString().c_str());
@@ -812,7 +779,6 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
channel.fadeStartTick = 0;
channel.soundNode = soundNode;
channel.volume = volume < 0 || volume > kMaxVolume ? (int)kMaxVolume : volume;
- // TODO: SCI3 introduces stereo audio
channel.pan = -1;
if (monitor) {
@@ -842,18 +808,17 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
audioStream = Audio::makeRawStream(dataStream, _globalSampleRate, flags, DisposeAfterUse::YES);
}
- channel.stream = new MutableLoopAudioStream(audioStream, loop);
- channel.converter = Audio::makeRateConverter(channel.stream->getRate(), getRate(), channel.stream->isStereo(), false);
+ channel.stream.reset(new MutableLoopAudioStream(audioStream, loop));
+ channel.converter.reset(Audio::makeRateConverter(channel.stream->getRate(), getRate(), channel.stream->isStereo(), false));
- // NOTE: SCI engine sets up a decompression buffer here for the audio
- // stream, plus writes information about the sample to the channel to
- // convert to the correct hardware output format, and allocates the
- // monitoring buffer to match the bitrate/samplerate/channels of the
- // original stream. We do not need to do any of these things since we
- // use audio streams, and allocate and fill the monitoring buffer
- // when reading audio data from the stream.
+ // SSCI sets up a decompression buffer here for the audio stream, plus
+ // writes information about the sample to the channel to convert to the
+ // correct hardware output format, and allocates the monitoring buffer to
+ // match the bitrate/samplerate/channels of the original stream. We do not
+ // need to do any of these things since we use audio streams, and allocate
+ // and fill the monitoring buffer when reading audio data from the stream.
- MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream);
+ MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream.get());
if (stream == nullptr) {
error("[Audio32::play]: Unable to cast stream for resource %s", resourceId.toString().c_str());
}
@@ -958,8 +923,8 @@ bool Audio32::pause(const int16 channelIndex) {
}
}
- // NOTE: The actual engine returns false here regardless of whether
- // or not channels were paused
+ // SSCI returns false here regardless of whether or not channels were
+ // paused, so we emulate this behaviour
} else {
AudioChannel &channel = getChannel(channelIndex);
@@ -996,9 +961,10 @@ int16 Audio32::stop(const int16 channelIndex) {
}
}
- // NOTE: SSCI stops the DSP interrupt and frees the
- // global decompression buffer here if there are no
- // more active channels
+ // SSCI stops the DSP interrupt and frees the global decompression buffer
+ // here if there are no more active channels, which we do not need to do
+ // since the system manages audio callbacks and we have no static
+ // decompression buffer
return oldNumChannels;
}
@@ -1015,13 +981,14 @@ int16 Audio32::getPosition(const int16 channelIndex) const {
return -1;
}
- // NOTE: SSCI treats this as an unsigned short except for
- // when the value is 65535, then it treats it as signed
+ // SSCI treats this as an unsigned short except for when the value is 65535,
+ // then it treats it as signed
int position = -1;
const uint32 now = g_sci->getTickCount();
- // NOTE: The original engine also queried the audio driver to see whether
- // it thought that there was audio playback occurring via driver opcode 9
+ // SSCI also queried the audio driver to see whether it thought that there
+ // was audio playback occurring via driver opcode 9, but we have no analogue
+ // to query
if (channelIndex == kAllChannels) {
if (_pausedAtTick) {
position = _pausedAtTick - _startedAtTick;
@@ -1052,7 +1019,7 @@ void Audio32::setLoop(const int16 channelIndex, const bool loop) {
AudioChannel &channel = getChannel(channelIndex);
- MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream);
+ MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream.get());
assert(stream);
stream->loop() = loop;
}
@@ -1161,8 +1128,8 @@ bool Audio32::hasSignal() const {
return false;
}
- const Audio::st_sample_t *buffer = _monitoredBuffer;
- const Audio::st_sample_t *const end = _monitoredBuffer + _numMonitoredSamples;
+ const Audio::st_sample_t *buffer = _monitoredBuffer.data();
+ const Audio::st_sample_t *const end = _monitoredBuffer.data() + _numMonitoredSamples;
while (buffer != end) {
const Audio::st_sample_t sample = *buffer++;
@@ -1193,9 +1160,9 @@ reg_t Audio32::kernelPlay(const bool autoPlay, const int argc, const reg_t *cons
if (argc < 6 || argv[5].toSint16() == 1) {
loop = false;
} else {
- // NOTE: Uses -1 for infinite loop. Presumably the
- // engine was supposed to allow counter loops at one
- // point, but ended up only using loop as a boolean.
+ // SSCI uses -1 for infinite loop. Presumably the engine was
+ // supposed to allow counter loops at one point, but ended up only
+ // using loop as a boolean.
loop = (bool)argv[5].toSint16();
}
@@ -1311,8 +1278,10 @@ reg_t Audio32::kernelFade(const int argc, const reg_t *const argv) {
Common::StackLock lock(_mutex);
- // NOTE: In SSCI, this call to find the channel is hacked up; argc is
- // set to 2 before the call, and then restored after the call.
+ // In SSCI, this call to find the channel is hacked up; argc is set to 2
+ // before the call, and then restored after the call. We just implemented
+ // findChannelByArgs in a manner that allows us to pass this information
+ // without messing with argc/argv instead
const int16 channelIndex = findChannelByArgs(2, argv, 0, argc > 5 ? argv[5] : NULL_REG);
const int16 volume = argv[1].toSint16();
const int16 speed = argv[2].toSint16();
@@ -1359,7 +1328,7 @@ void Audio32::printAudioList(Console *con) const {
Common::StackLock lock(_mutex);
for (int i = 0; i < _numActiveChannels; ++i) {
const AudioChannel &channel = _channels[i];
- const MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream);
+ const MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream.get());
con->debugPrintf(" %d[%04x:%04x]: %s, started at %d, pos %d/%d, vol %d, pan %d%s%s\n",
i,
PRINT_REG(channel.soundNode),
diff --git a/engines/sci/sound/audio32.h b/engines/sci/sound/audio32.h
index 71f5883..a0167f3 100644
--- a/engines/sci/sound/audio32.h
+++ b/engines/sci/sound/audio32.h
@@ -50,22 +50,23 @@ struct AudioChannel {
ResourceId id;
/**
- * The resource loaded into this channel.
+ * The resource loaded into this channel. The resource is owned by
+ * ResourceManager.
*/
Resource *resource;
/**
- * The audio stream loaded into this channel. Can cast
- * to `SeekableAudioStream` for normal channels and
- * `RobotAudioStream` for robot channels.
+ * The audio stream loaded into this channel. Can cast to
+ * `SeekableAudioStream` for normal channels and `RobotAudioStream` for
+ * robot channels.
*/
- Audio::AudioStream *stream;
+ Common::ScopedPtr<Audio::AudioStream> stream;
/**
- * The converter used to transform and merge the input
- * stream into the mixer's output buffer.
+ * The converter used to transform and merge the input stream into the
+ * mixer's output buffer.
*/
- Audio::RateConverter *converter;
+ Common::ScopedPtr<Audio::RateConverter> converter;
/**
* Duration of the channel, in ticks.
@@ -83,8 +84,8 @@ struct AudioChannel {
uint32 pausedAtTick;
/**
- * The time, in ticks, that the channel fade began.
- * If 0, the channel is not being faded.
+ * The time, in ticks, that the channel fade began. If 0, the channel is not
+ * being faded.
*/
uint32 fadeStartTick;
@@ -104,20 +105,19 @@ struct AudioChannel {
int fadeTargetVolume;
/**
- * Whether or not the channel should be stopped and
- * freed when the fade is complete.
+ * Whether or not the channel should be stopped and freed when the fade is
+ * complete.
*/
bool stopChannelOnFade;
/**
- * Whether or not this channel contains a Robot
- * audio block.
+ * Whether or not this channel contains a Robot audio block.
*/
bool robot;
/**
- * For digital sound effects, the related VM
- * Sound::nodePtr object for the sound.
+ * For digital sound effects, the related VM Sound::nodePtr object for the
+ * sound.
*/
reg_t soundNode;
@@ -127,17 +127,37 @@ struct AudioChannel {
int volume;
/**
- * The amount to pan to the right, from 0 to 100.
- * 50 is centered, -1 is not panned.
+ * The amount to pan to the right, from 0 to 100. 50 is centered, -1 is not
+ * panned.
*/
int pan;
+
+ AudioChannel &operator=(AudioChannel &other) {
+ id = other.id;
+ resource = other.resource;
+ stream.reset(other.stream.release());
+ converter.reset(other.converter.release());
+ duration = other.duration;
+ startedAtTick = other.startedAtTick;
+ pausedAtTick = other.pausedAtTick;
+ fadeStartTick = other.fadeStartTick;
+ fadeStartVolume = other.fadeStartVolume;
+ fadeDuration = other.fadeDuration;
+ fadeTargetVolume = other.fadeTargetVolume;
+ stopChannelOnFade = other.stopChannelOnFade;
+ robot = other.robot;
+ soundNode = other.soundNode;
+ volume = other.volume;
+ pan = other.pan;
+ return *this;
+ }
};
#pragma mark -
/**
- * Special audio channel indexes used to select a channel
- * for digital audio playback.
+ * Special audio channel indexes used to select a channel for digital audio
+ * playback.
*/
enum AudioChannelIndex {
kRobotChannel = -3,
@@ -146,10 +166,9 @@ enum AudioChannelIndex {
};
/**
- * Audio32 acts as a permanent audio stream into the system
- * mixer and provides digital audio services for the SCI32
- * engine, since the system mixer does not support all the
- * features of SCI.
+ * Audio32 acts as a permanent audio stream into the system mixer and provides
+ * digital audio services for the SCI32 engine, since the system mixer does not
+ * support all the features of SCI.
*/
class Audio32 : public Audio::AudioStream, public Common::Serializable {
public:
@@ -196,10 +215,10 @@ private:
bool channelShouldMix(const AudioChannel &channel) const;
/**
- * Mixes audio from the given source stream into the
- * target buffer using the given rate converter.
+ * Mixes audio from the given source stream into the target buffer using the
+ * given rate converter.
*/
- int writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::RateConverter *const converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume);
+ int writeAudioInternal(Audio::AudioStream &sourceStream, Audio::RateConverter &converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume);
#pragma mark -
#pragma mark Channel management
@@ -226,17 +245,15 @@ public:
uint8 getNumUnlockedChannels() const;
/**
- * Finds a channel that is already configured for the
- * given audio sample.
+ * Finds a channel that is already configured for the given audio sample.
*
- * @param startIndex The location of the audio resource
- * information in the arguments list.
+ * @param startIndex The location of the audio resource information in the
+ * arguments list.
*/
int16 findChannelByArgs(int argc, const reg_t *argv, const int startIndex, const reg_t soundNode) const;
/**
- * Finds a channel that is already configured for the
- * given audio sample.
+ * Finds a channel that is already configured for the given audio sample.
*/
int16 findChannelById(const ResourceId resourceId, const reg_t soundNode = NULL_REG) const;
@@ -255,26 +272,24 @@ private:
Common::Array<AudioChannel> _channels;
/**
- * The number of active audio channels in the mixer.
- * Being active is not the same as playing; active
- * channels may be paused.
+ * The number of active audio channels in the mixer. Being active is not the
+ * same as playing; active channels may be paused.
*/
uint8 _numActiveChannels;
/**
* Whether or not we are in the audio thread.
*
- * This flag is used instead of passing a parameter to
- * `freeUnusedChannels` because a parameter would
- * require forwarding through the public method `stop`,
- * and there is not currently any reason for this
- * implementation detail to be exposed.
+ * This flag is used instead of passing a parameter to `freeUnusedChannels`
+ * because a parameter would require forwarding through the public method
+ * `stop`, and there is not currently any reason for this implementation
+ * detail to be exposed.
*/
bool _inAudioThread;
/**
- * The list of resources from freed channels that need
- * to be unlocked from the main thread.
+ * The list of resources from freed channels that need to be unlocked from
+ * the main thread.
*/
UnlockList _resourcesToUnlock;
@@ -302,8 +317,7 @@ private:
}
/**
- * Frees all non-looping channels that have reached the
- * end of their stream.
+ * Frees all non-looping channels that have reached the end of their stream.
*/
void freeUnusedChannels();
@@ -313,8 +327,7 @@ private:
void freeChannel(const int16 channelIndex);
/**
- * Unlocks all resources that were freed by the audio
- * thread.
+ * Unlocks all resources that were freed by the audio thread.
*/
void unlockResources();
@@ -322,58 +335,58 @@ private:
#pragma mark Script compatibility
public:
/**
- * Gets the (fake) sample rate of the hardware DAC.
- * For script compatibility only.
+ * Gets the (fake) sample rate of the hardware DAC. For script compatibility
+ * only.
*/
inline uint16 getSampleRate() const {
return _globalSampleRate;
}
/**
- * Sets the (fake) sample rate of the hardware DAC.
- * For script compatibility only.
+ * Sets the (fake) sample rate of the hardware DAC. For script compatibility
+ * only.
*/
void setSampleRate(uint16 rate);
/**
- * Gets the (fake) bit depth of the hardware DAC.
- * For script compatibility only.
+ * Gets the (fake) bit depth of the hardware DAC. For script compatibility
+ * only.
*/
inline uint8 getBitDepth() const {
return _globalBitDepth;
}
/**
- * Sets the (fake) sample rate of the hardware DAC.
- * For script compatibility only.
+ * Sets the (fake) sample rate of the hardware DAC. For script compatibility
+ * only.
*/
void setBitDepth(uint8 depth);
/**
- * Gets the (fake) number of output (speaker) channels
- * of the hardware DAC. For script compatibility only.
+ * Gets the (fake) number of output (speaker) channels of the hardware DAC.
+ * For script compatibility only.
*/
inline uint8 getNumOutputChannels() const {
return _globalNumOutputChannels;
}
/**
- * Sets the (fake) number of output (speaker) channels
- * of the hardware DAC. For script compatibility only.
+ * Sets the (fake) number of output (speaker) channels of the hardware DAC.
+ * For script compatibility only.
*/
void setNumOutputChannels(int16 numChannels);
/**
- * Gets the (fake) number of preloaded channels.
- * For script compatibility only.
+ * Gets the (fake) number of preloaded channels. For script compatibility
+ * only.
*/
inline uint8 getPreload() const {
return _preload;
}
/**
- * Sets the (fake) number of preloaded channels.
- * For script compatibility only.
+ * Sets the (fake) number of preloaded channels. For script compatibility
+ * only.
*/
inline void setPreload(uint8 preload) {
_preload = preload;
@@ -381,49 +394,43 @@ public:
private:
/**
- * The hardware DAC sample rate. Stored only for script
- * compatibility.
+ * The hardware DAC sample rate. Stored only for script compatibility.
*/
uint16 _globalSampleRate;
/**
- * The maximum allowed sample rate of the system mixer.
- * Stored only for script compatibility.
+ * The maximum allowed sample rate of the system mixer. Stored only for
+ * script compatibility.
*/
uint16 _maxAllowedSampleRate;
/**
- * The hardware DAC bit depth. Stored only for script
- * compatibility.
+ * The hardware DAC bit depth. Stored only for script compatibility.
*/
uint8 _globalBitDepth;
/**
- * The maximum allowed bit depth of the system mixer.
- * Stored only for script compatibility.
+ * The maximum allowed bit depth of the system mixer. Stored only for script
+ * compatibility.
*/
uint8 _maxAllowedBitDepth;
/**
- * The hardware DAC output (speaker) channel
- * configuration. Stored only for script compatibility.
+ * The hardware DAC output (speaker) channel configuration. Stored only for
+ * script compatibility.
*/
uint8 _globalNumOutputChannels;
/**
- * The maximum allowed number of output (speaker)
- * channels of the system mixer. Stored only for script
- * compatibility.
+ * The maximum allowed number of output (speaker) channels of the system
+ * mixer. Stored only for script compatibility.
*/
uint8 _maxAllowedOutputChannels;
/**
- * The number of audio channels that should have their
- * data preloaded into memory instead of streaming from
- * disk.
- * 1 = all channels, 2 = 2nd active channel and above,
- * etc.
- * Stored only for script compatibility.
+ * The number of audio channels that should have their data preloaded into
+ * memory instead of streaming from disk. 1 = all channels, 2 = 2nd active
+ * channel and above, etc. Stored only for script compatibility.
*/
uint8 _preload;
@@ -442,8 +449,7 @@ private:
int16 findRobotChannel() const;
/**
- * When true, channels marked as robot audio will not be
- * played.
+ * When true, channels marked as robot audio will not be played.
*/
bool _robotAudioPaused;
@@ -456,8 +462,8 @@ public:
uint16 play(int16 channelIndex, const ResourceId resourceId, const bool autoPlay, const bool loop, const int16 volume, const reg_t soundNode, const bool monitor);
/**
- * Resumes playback of a paused audio channel, or of
- * the entire audio player.
+ * Resumes playback of a paused audio channel, or of the entire audio
+ * player.
*/
bool resume(const int16 channelIndex);
bool resume(const ResourceId resourceId, const reg_t soundNode = NULL_REG) {
@@ -475,8 +481,7 @@ public:
}
/**
- * Stops and unloads an audio channel, or the entire
- * audio player.
+ * Stops and unloads an audio channel, or the entire audio player.
*/
int16 stop(const int16 channelIndex);
int16 stop(const ResourceId resourceId, const reg_t soundNode = NULL_REG) {
@@ -490,8 +495,7 @@ public:
uint16 restart(const ResourceId resourceId, const bool autoPlay, const bool loop, const int16 volume, const reg_t soundNode, const bool monitor);
/**
- * Returns the playback position for the given channel
- * number, in ticks.
+ * Returns the playback position for the given channel number, in ticks.
*/
int16 getPosition(const int16 channelIndex) const;
int16 getPosition(const ResourceId resourceId, const reg_t soundNode = NULL_REG) {
@@ -531,8 +535,8 @@ private:
#pragma mark Effects
public:
/**
- * Gets the volume for a given channel. Passing
- * `kAllChannels` will get the global volume.
+ * Gets the volume for a given channel. Passing `kAllChannels` will get the
+ * global volume.
*/
int16 getVolume(const int16 channelIndex) const;
int16 getVolume(const ResourceId resourceId, const reg_t soundNode) const {
@@ -541,8 +545,8 @@ public:
}
/**
- * Sets the volume of an audio channel. Passing
- * `kAllChannels` will set the global volume.
+ * Sets the volume of an audio channel. Passing `kAllChannels` will set the
+ * global volume.
*/
void setVolume(const int16 channelIndex, int16 volume);
void setVolume(const ResourceId resourceId, const reg_t soundNode, const int16 volume) {
@@ -583,24 +587,21 @@ public:
private:
/**
- * If true, audio will be mixed by reducing the target
- * buffer by half every time a new channel is mixed in.
- * The final channel is not attenuated.
+ * If true, audio will be mixed by reducing the target buffer by half every
+ * time a new channel is mixed in. The final channel is not attenuated.
*/
bool _attenuatedMixing;
/**
- * When true, a modified attenuation algorithm is used
- * (`A/4 + B`) instead of standard linear attenuation
- * (`A/2 + B/2`).
+ * When true, a modified attenuation algorithm is used (`A/4 + B`) instead
+ * of standard linear attenuation (`A/2 + B/2`).
*/
bool _useModifiedAttenuation;
/**
* Processes an audio fade for the given channel.
*
- * @returns true if the fade was completed and the
- * channel was stopped.
+ * @returns true if the fade was completed and the channel was stopped.
*/
bool processFade(const int16 channelIndex);
@@ -608,35 +609,27 @@ private:
#pragma mark Signal monitoring
public:
/**
- * Returns whether the currently monitored audio channel
- * contains any signal within the next audio frame.
+ * Returns whether the currently monitored audio channel contains any signal
+ * within the next audio frame.
*/
bool hasSignal() const;
private:
/**
- * The index of the channel being monitored for signal,
- * or -1 if no channel is monitored. When a channel is
- * monitored, it also causes the engine to play only the
- * monitored channel.
+ * The index of the channel being monitored for signal, or -1 if no channel
+ * is monitored. When a channel is monitored, it also causes the engine to
+ * play only the monitored channel.
*/
int16 _monitoredChannelIndex;
/**
- * The data buffer holding decompressed audio data for
- * the channel that will be monitored for an audio
- * signal.
- */
- Audio::st_sample_t *_monitoredBuffer;
-
- /**
- * The size of the buffer, in bytes.
+ * The data buffer holding decompressed audio data for the channel that will
+ * be monitored for an audio signal.
*/
- size_t _monitoredBufferSize;
+ Common::Array<Audio::st_sample_t> _monitoredBuffer;
/**
- * The number of valid audio samples in the signal
- * monitoring buffer.
+ * The number of valid audio samples in the signal monitoring buffer.
*/
int _numMonitoredSamples;
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 0bb295d..5a1c2c0 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -350,11 +350,9 @@ reg_t SoundCommandParser::kDoSoundPause(EngineState *s, int argc, reg_t *argv) {
}
#ifdef ENABLE_SCI32
- // NOTE: The original engine also expected a global
- // "kernel call" flag to be true in order to perform
- // this action, but the architecture of the ScummVM
- // implementation is so different that it doesn't
- // matter here
+ // SSCI also expected a global "kernel call" flag to be true in order to
+ // perform this action, but the architecture of the ScummVM
+ // implementation is so different that it doesn't matter here
if (_soundVersion >= SCI_VERSION_2_1_EARLY && musicSlot->isSample) {
if (shouldPause) {
g_sci->_audio32->pause(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj);
Commit: 42180527c4d9df920ab1b77c78e9c5e36b93b74d
https://github.com/scummvm/scummvm/commit/42180527c4d9df920ab1b77c78e9c5e36b93b74d
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:11:02-05:00
Commit Message:
SCI32: Fix music volume not being restored after speech in Torin
This was a regression introduced by
d556dcc57bf50a03d81ab7a1ef59a9e5758465bf.
Changed paths:
engines/sci/sound/music.cpp
engines/sci/sound/soundcmd.cpp
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index 5530952..b2bd72e 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -626,13 +626,7 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) {
assert(volume <= MUSIC_VOLUME_MAX);
- if (pSnd->isSample) {
-#ifdef ENABLE_SCI32
- if (_soundVersion >= SCI_VERSION_2_1_EARLY) {
- g_sci->_audio32->setVolume(ResourceId(kResourceTypeAudio, pSnd->resourceId), pSnd->soundObj, volume);
- }
-#endif
- } else if (pSnd->pMidiParser) {
+ if (!pSnd->isSample && pSnd->pMidiParser) {
Common::StackLock lock(_mutex);
pSnd->pMidiParser->mainThreadBegin();
pSnd->pMidiParser->setVolume(volume);
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 5a1c2c0..54fdcf5 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -739,8 +739,8 @@ reg_t SoundCommandParser::kDoSoundSetVolume(EngineState *s, int argc, reg_t *arg
#ifdef ENABLE_SCI32
// SSCI unconditionally sets volume if it is digital audio
if (_soundVersion >= SCI_VERSION_2_1_EARLY && musicSlot->isSample) {
- _music->soundSetVolume(musicSlot, value);
- } else
+ g_sci->_audio32->setVolume(ResourceId(kResourceTypeAudio, musicSlot->resourceId), musicSlot->soundObj, value);
+ }
#endif
if (musicSlot->volume != value) {
musicSlot->volume = value;
Commit: a2c8674252743c451600f53c77df3c7fac6e7786
https://github.com/scummvm/scummvm/commit/a2c8674252743c451600f53c77df3c7fac6e7786
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:11:02-05:00
Commit Message:
SCI32: Clean up GfxText32
* Rewrap comments to 80 columns
* Clarify comments where possible
Changed paths:
engines/sci/graphics/text32.cpp
engines/sci/graphics/text32.h
diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp
index 7399fe0..1fcf292 100644
--- a/engines/sci/graphics/text32.cpp
+++ b/engines/sci/graphics/text32.cpp
@@ -44,7 +44,7 @@ int16 GfxText32::_yResolution = 0;
GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts) :
_segMan(segMan),
_cache(fonts),
- // Not a typo, the original engine did not initialise height, only width
+ // SSCI did not initialise height, so we intentionally do not do so also
_width(0),
_text(""),
_bitmap(NULL_REG) {
@@ -84,8 +84,8 @@ reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect
mulinc(_textRect, scaleX, scaleY);
}
- // _textRect represents where text is drawn inside the
- // bitmap; clipRect is the entire bitmap
+ // `_textRect` represents where text is drawn inside the bitmap; `clipRect`
+ // is the entire bitmap
Common::Rect bitmapRect(_width, _height);
if (_textRect.intersects(bitmapRect)) {
@@ -134,9 +134,9 @@ reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &
SciBitmap &bitmap = *_segMan->allocateBitmap(&_bitmap, _width, _height, _skipColor, 0, 0, _xResolution, _yResolution, 0, false, gc);
- // NOTE: The engine filled the bitmap pixels with 11 here, which is silly
- // because then it just erased the bitmap using the skip color. So we don't
- // fill the bitmap redundantly here.
+ // SSCI filled the bitmap pixels with 11 here, which is silly because then
+ // it just erased the bitmap using the skip color. So we don't fill the
+ // bitmap redundantly here.
_backColor = _skipColor;
erase(bitmapRect, false);
@@ -164,9 +164,10 @@ reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &
}
void GfxText32::setFont(const GuiResourceId fontId) {
- // NOTE: In SCI engine this calls FontMgr::BuildFontTable and then a font
- // table is built on the FontMgr directly; instead, because we already have
- // font resources, this code just grabs a font out of GfxCache.
+ // In SSCI, this calls FontMgr::BuildFontTable, and then a font table is
+ // built on the FontMgr directly; instead, because we already have GfxFont
+ // resources from SCI16 and those resources did not change in SCI32, this
+ // code just grabs those out of GfxCache
if (fontId != _fontId) {
_fontId = fontId;
_font = _cache->getFont(_fontId);
@@ -179,7 +180,7 @@ void GfxText32::drawFrame(const Common::Rect &rect, const int16 size, const uint
SciBitmap &bitmap = *_segMan->lookupBitmap(_bitmap);
byte *pixels = bitmap.getPixels() + rect.top * _width + rect.left;
- // NOTE: Not fully disassembled, but this should be right
+ // Not fully disassembled, but appears to be correct in all cases
int16 rectWidth = targetRect.width();
int16 heightRemaining = targetRect.height();
int16 sidesHeight = heightRemaining - size * 2;
@@ -275,10 +276,9 @@ void GfxText32::drawTextBox(const Common::String &text) {
void GfxText32::drawText(const uint index, uint length) {
assert(index + length <= _text.size());
- // NOTE: This draw loop implementation is somewhat different than the
- // implementation in the actual engine, but should be accurate. Primarily
- // the changes revolve around eliminating some extra temporaries and
- // fixing the logic to match.
+ // This draw loop implementation is somewhat different than the
+ // implementation in SSCI, but is accurate. Primarily the changes revolve
+ // around eliminating some extra temporaries and fixing the logic to match.
const char *text = _text.c_str() + index;
while (length-- > 0) {
char currentChar = *text++;
@@ -341,10 +341,10 @@ void GfxText32::invertRect(const reg_t bitmapId, int16 bitmapStride, const Commo
SciBitmap &bitmap = *_segMan->lookupBitmap(bitmapId);
- // NOTE: SCI code is super weird here; it seems to be trying to look at the
- // entire size of the bitmap including the header, instead of just the pixel
- // data size. We just look at the pixel size. This function generally is an
- // odd duck since the stride dimension for a bitmap is built in to the bitmap
+ // SSCI is super weird here; it seems to be trying to look at the entire
+ // size of the bitmap including the header, instead of just the pixel data
+ // size. We just look at the pixel size. This function generally is an odd
+ // duck since the stride dimension for a bitmap is built in to the bitmap
// header, so perhaps it was once an unheadered bitmap format and this
// function was never updated to match? Or maybe they exploit the
// configurable stride length somewhere else to do stair stepping inverts...
@@ -355,7 +355,7 @@ void GfxText32::invertRect(const reg_t bitmapId, int16 bitmapStride, const Commo
error("InvertRect too big: %u >= %u", invertSize, bitmapSize);
}
- // NOTE: Actual engine just added the bitmap header size hardcoded here
+ // SSCI just added a hardcoded bitmap header size here
byte *pixel = bitmap.getPixels() + bitmapStride * targetRect.top + targetRect.left;
int16 stride = bitmapStride - targetRect.width();
@@ -392,16 +392,17 @@ uint GfxText32::getLongest(uint *charIndex, const int16 width) {
char currentChar;
while ((currentChar = *text++) != '\0') {
- // NOTE: In the original engine, the font, color, and alignment were
- // reset here to their initial values
+ // In SSCI, the font, color, and alignment were reset here to their
+ // initial values; this does not seem to be necessary and really
+ // complicates the font system, so we do not do it
// The text to render contains a line break; stop at the line break
if (currentChar == '\r' || currentChar == '\n') {
- // Skip the rest of the line break if it is a Windows-style
- // \r\n or non-standard \n\r
- // NOTE: In the original engine, the `text` pointer had not been
- // advanced yet so the indexes used to access characters were
- // one higher
+ // Skip the rest of the line break if it is a Windows-style \r\n (or
+ // non-standard \n\r)
+
+ // In SSCI, the `text` pointer had not been advanced yet here, so
+ // the indexes used to access characters were one higher there
if (
(currentChar == '\r' && text[0] == '\n') ||
(currentChar == '\n' && text[0] == '\r' && text[1] != '\n')
@@ -418,16 +419,20 @@ uint GfxText32::getLongest(uint *charIndex, const int16 width) {
}
// Skip the line break and return all text seen up to now
- // NOTE: In original engine, the font, color, and alignment were
- // reset, then getTextWidth was called to use its side-effects to
- // set font, color, and alignment according to the text from
- // `initialCharIndex` to `testLength`
+ // In SSCI, the font, color, and alignment were reset, then
+ // getTextWidth was called to use its side-effects to set font,
+ // color, and alignment according to the text from
+ // `initialCharIndex` to `testLength`. This is complicated and
+ // apparently not necessary for correct operation, so we do not do
+ // it
+
++*charIndex;
return testLength;
} else if (currentChar == ' ') {
- // The last word in the line made it too wide to fit in the text area;
- // return up to the previous word, then collapse the whitespace
- // between that word and its next sibling word into the line break
+ // The last word in the line made it too wide to fit in the text
+ // area; return up to the previous word, then collapse the
+ // whitespace between that word and its next sibling word into the
+ // line break
if (getTextWidth(initialCharIndex, testLength) > width) {
*charIndex = lastWordBreakIndex;
const char *nextChar = _text.c_str() + lastWordBreakIndex;
@@ -435,14 +440,17 @@ uint GfxText32::getLongest(uint *charIndex, const int16 width) {
++*charIndex;
}
- // NOTE: In original engine, the font, color, and alignment were
- // set here to the values that were seen at the last space character
+ // In SSCI, the font, color, and alignment were set here to the
+ // values that were seen at the last space character, but this
+ // is complicated and unnecessary so we do not do it
+
return length;
}
- // NOTE: In the original engine, the values of _fontId, _foreColor,
- // and _alignment were stored for use in the return path mentioned
- // just above here
+ // In SSCI, the values of `_fontId`, `_foreColor`, and `_alignment`
+ // were stored for use in the return path mentioned just above here,
+ // but we do not need to do this because we do not cause
+ // side-effects when calculating text dimensions
// We found a word break that was within the text area, memorise it
// and continue processing. +1 on the character index because it has
@@ -456,8 +464,9 @@ uint GfxText32::getLongest(uint *charIndex, const int16 width) {
++*charIndex;
++testLength;
- // NOTE: In the original engine, the font, color, and alignment were
- // reset here to their initial values
+ // In SSCI, the font, color, and alignment were reset here to their
+ // initial values, but we do not need to do this because we do not cause
+ // side-effects when calculating text dimensions
// The text to render contained no word breaks yet but is already too
// wide for the text area; just split the word in half at the point
@@ -471,10 +480,11 @@ uint GfxText32::getLongest(uint *charIndex, const int16 width) {
// The complete text to render was a single word, or was narrower than
// the text area, so return the entire line
if (length == 0 || getTextWidth(initialCharIndex, testLength) <= width) {
- // NOTE: In original engine, the font, color, and alignment were
- // reset, then getTextWidth was called to use its side-effects to
- // set font, color, and alignment according to the text from
- // `initialCharIndex` to `testLength`
+ // In SSCI, the font, color, and alignment were reset, then getTextWidth
+ // was called to use its side-effects to set font, color, and alignment
+ // according to the text from `initialCharIndex` to `testLength`. This
+ // is not necessary because we do not cause side-effects when
+ // calculating text dimensions
return testLength;
}
@@ -495,14 +505,13 @@ int16 GfxText32::getTextWidth(const uint index, uint length) const {
while (length > 0 && currentChar != '\0') {
// Control codes are in the format `|<code><value>|`
if (currentChar == '|') {
- // NOTE: Original engine code changed the global state of the
- // FontMgr here upon encountering any color, alignment, or
- // font control code.
- // To avoid requiring all callers to manually restore these
- // values on every call, we ignore control codes other than
- // font change (since alignment and color do not change the
- // width of characters), and simply update the font pointer
- // on stack instead of the member property font.
+ // SSCI changed the global state of the FontMgr here upon
+ // encountering any color, alignment, or font control code. To avoid
+ // requiring all callers to manually restore these values on every
+ // call, we ignore control codes other than font change (since
+ // alignment and color do not change the width of characters), and
+ // simply update the font pointer on stack instead of the member
+ // property font to avoid these unnecessary side-effects.
currentChar = *text++;
--length;
@@ -548,12 +557,12 @@ int16 GfxText32::getTextWidth(const Common::String &text, const uint index, cons
}
Common::Rect GfxText32::getTextSize(const Common::String &text, int16 maxWidth, bool doScaling) {
- // NOTE: Like most of the text rendering code, this function was pretty
- // weird in the original engine. The initial result rectangle was actually
- // a 1x1 rectangle (0, 0, 0, 0), which was then "fixed" after the main
- // text size loop finished running by subtracting 1 from the right and
- // bottom edges. Like other functions in SCI32, this has been converted
- // to use exclusive rects with inclusive rounding.
+ // Like most of the text rendering code, this function was pretty weird in
+ // SSCI. The initial result rectangle was actually a 1x1 rectangle
+ // (0, 0, 0, 0), which was then "fixed" after the main text size loop
+ // finished running by subtracting 1 from the right and bottom edges. Like
+ // other functions in SCI32, this has been converted to use exclusive rects
+ // with inclusive rounding.
Common::Rect result;
@@ -598,17 +607,18 @@ Common::Rect GfxText32::getTextSize(const Common::String &text, int16 maxWidth,
if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
result.bottom = 0;
} else {
- // NOTE: In the original engine code, the bottom was not decremented
- // by 1, which means that the rect was actually a pixel taller than
- // the height of the font. This was not the case in the other branch,
- // which decremented the bottom by 1 at the end of the loop.
+ // In SSCI, the bottom was not decremented by 1, which means that
+ // the rect was actually a pixel taller than the height of the font.
+ // This was not the case in the other branch, which decremented the
+ // bottom by 1 at the end of the loop. For accuracy, we do what SSCI
+ // did, even though this means the result is a pixel off
result.bottom = _font->getHeight() + 1;
}
}
if (doScaling) {
- // NOTE: The original engine code also scaled top/left but these are
- // always zero so there is no reason to do that.
+ // SSCI also scaled top/left but these are always zero so there is no
+ // reason to do that
result.right = ((result.right - 1) * scriptWidth + _xResolution - 1) / _xResolution + 1;
result.bottom = ((result.bottom - 1) * scriptHeight + _yResolution - 1) / _yResolution + 1;
}
@@ -700,7 +710,10 @@ void GfxText32::scrollLine(const Common::String &lineText, int numLines, uint8 c
_foreColor = color;
_alignment = align;
- //int fc = _foreColor;
+
+ // As with other font functions, SSCI saved _foreColor here so it could be
+ // restored after the getTextWidth call, but this call is side-effect-free
+ // in our implementation so this is not necessary
setFont(fontId);
@@ -713,8 +726,8 @@ void GfxText32::scrollLine(const Common::String &lineText, int numLines, uint8 c
_drawPosition.x += _textRect.width() - textWidth;
}
- //_foreColor = fc;
- //setFont(fontId);
+ // _foreColor and font were restored here in SSCI due to side-effects of
+ // getTextWidth which do not exist in our implementation
drawText(0, lineText.size());
}
diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h
index c8fafb2..945cc81 100644
--- a/engines/sci/graphics/text32.h
+++ b/engines/sci/graphics/text32.h
@@ -45,11 +45,11 @@ enum ScrollDirection {
class GfxFont;
/**
- * This class handles text calculation and rendering for
- * SCI32 games. The text calculation system in SCI32 is
- * nearly the same as SCI16, which means this class behaves
- * similarly. Notably, GfxText32 maintains drawing
- * parameters across multiple calls.
+ * This class handles text calculation and rendering for SCI32 games. The text
+ * calculation system in SCI32 is nearly the same as SCI16, which means this
+ * class behaves similarly. Notably, GfxText32 maintains drawing parameters
+ * across multiple calls, instead of requiring all text parameters to be
+ * provided on every draw call.
*/
class GfxText32 {
private:
@@ -57,10 +57,10 @@ private:
GfxCache *_cache;
/**
- * The width and height of the currently active text
- * bitmap, in text-system coordinates.
+ * The width and height of the currently active text bitmap, in text-system
+ * coordinates.
*
- * @note These are unsigned in the actual engine.
+ * @note These are unsigned in SSCI.
*/
int16 _width, _height;
@@ -75,20 +75,19 @@ private:
uint8 _backColor;
/**
- * The transparent color of the text box. Used when
- * compositing the bitmap onto the screen.
+ * The transparent color of the text box. Used when compositing the bitmap
+ * onto the screen.
*/
uint8 _skipColor;
/**
- * The rect where the text is drawn within the bitmap.
- * This rect is clipped to the dimensions of the bitmap.
+ * The rect where the text is drawn within the bitmap. This rect is clipped
+ * to the dimensions of the bitmap.
*/
Common::Rect _textRect;
/**
- * The text being drawn to the currently active text
- * bitmap.
+ * The text being drawn to the currently active text bitmap.
*/
Common::String _text;
@@ -103,7 +102,8 @@ private:
int16 _borderColor;
/**
- * TODO: Document
+ * If true, text will be drawn using a dither that draws only every other
+ * pixel of the text.
*/
bool _dimmed;
@@ -123,19 +123,17 @@ private:
void drawText(const uint index, uint length);
/**
- * Gets the length of the longest run of text available
- * within the currently loaded text, starting from the
- * given `charIndex` and running for up to `maxWidth`
- * pixels. Returns the number of characters that can be
- * written, and mutates the value pointed to by
- * `charIndex` to point to the index of the next
- * character to render.
+ * Gets the length of the longest run of text available within the currently
+ * loaded text, starting from the given `charIndex` and running for up to
+ * `maxWidth` pixels. Returns the number of characters that can be written,
+ * and mutates the value pointed to by `charIndex` to point to the index of
+ * the next character to render.
*/
uint getLongest(uint *charIndex, const int16 maxWidth);
/**
- * Gets the pixel width of a substring of the currently
- * loaded text, without scaling.
+ * Gets the pixel width of a substring of the currently loaded text, without
+ * scaling.
*/
int16 getTextWidth(const uint index, uint length) const;
@@ -163,29 +161,27 @@ public:
reg_t _bitmap;
/**
- * The size of the x-dimension of the coordinate system
- * used by the text renderer. Static since it was global in SSCI.
+ * The size of the x-dimension of the coordinate system used by the text
+ * renderer. Static since it was global in SSCI.
*/
static int16 _xResolution;
/**
- * The size of the y-dimension of the coordinate system
- * used by the text renderer. Static since it was global in SSCI.
+ * The size of the y-dimension of the coordinate system used by the text
+ * renderer. Static since it was global in SSCI.
*/
static int16 _yResolution;
/**
- * The currently active font resource used to write text
- * into the bitmap.
+ * The currently active font resource used to write text into the bitmap.
*
- * @note SCI engine builds the font table directly
- * inside of FontMgr; we use GfxFont instead.
+ * @note SSCI builds the font table directly inside of FontMgr; we use
+ * GfxFont instead.
*/
GfxFont *_font;
/**
- * Creates a plain font bitmap with a flat color
- * background.
+ * Creates a plain font bitmap with a flat color background.
*/
reg_t createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, TextAlign alignment, const int16 borderColor, bool dimmed, const bool doScaling, const bool gc);
@@ -212,26 +208,22 @@ public:
/**
* Draws the given text to the bitmap.
*
- * @note The original engine holds a reference to a
- * shared string which lets the text be updated from
- * outside of the font manager. Instead, we give this
- * extra signature to send the text to draw.
- *
- * TODO: Use shared string instead?
+ * @note SSCI holds a reference to a shared string which lets the text be
+ * updated from outside of the font manager. Instead, we use this extra
+ * signature to send the text to draw.
*/
void drawTextBox(const Common::String &text);
/**
- * Erases the given rect by filling with the background
- * color.
+ * Erases the given rect by filling with the background color.
*/
void erase(const Common::Rect &rect, const bool doScaling);
void invertRect(const reg_t bitmap, const int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling);
/**
- * Sets the font to be used for rendering and
- * calculation of text dimensions.
+ * Sets the font to be used for rendering and calculation of text
+ * dimensions.
*/
void setFont(const GuiResourceId fontId);
@@ -251,8 +243,8 @@ public:
Common::Rect getTextSize(const Common::String &text, const int16 maxWidth, bool doScaling);
/**
- * Gets the pixel width of a substring of the currently
- * loaded text, with scaling.
+ * Gets the pixel width of a substring of the currently loaded text, with
+ * scaling.
*/
int16 getTextWidth(const Common::String &text, const uint index, const uint length);
@@ -262,23 +254,21 @@ public:
int16 getStringWidth(const Common::String &text);
/**
- * Gets the number of characters of `text`, starting
- * from `index`, that can be safely rendered into
- * `textRect`.
+ * Gets the number of characters of `text`, starting from `index`, that can
+ * be safely rendered into `textRect`.
*/
int16 getTextCount(const Common::String &text, const uint index, const Common::Rect &textRect, const bool doScaling);
/**
- * Gets the number of characters of `text`, starting
- * from `index`, that can be safely rendered into
- * `textRect` using the given font.
+ * Gets the number of characters of `text`, starting from `index`, that can
+ * be safely rendered into `textRect` using the given font.
*/
int16 getTextCount(const Common::String &text, const uint index, const GuiResourceId fontId, const Common::Rect &textRect, const bool doScaling);
/**
* Scroll up/down one line. `numLines` is the number of the lines in the
- * textarea, and `textLine` contains the text to draw as the newly
- * visible line. Originally FontMgr::DrawOneLine and FontMgr::UpOneLine.
+ * textarea, and `textLine` contains the text to draw as the newly visible
+ * line. Originally FontMgr::DrawOneLine and FontMgr::UpOneLine.
*/
void scrollLine(const Common::String &textLine, int numLines, uint8 color, TextAlign align, GuiResourceId fontId, ScrollDirection dir);
};
Commit: 1b4214695566ccadbe27806f646bed3c4c944809
https://github.com/scummvm/scummvm/commit/1b4214695566ccadbe27806f646bed3c4c944809
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:11:03-05:00
Commit Message:
SCI32: Clean up GfxRemap32
* Rewrap comments to 80 columns
* Clarify comments where possible
Changed paths:
engines/sci/engine/kgraphics32.cpp
engines/sci/graphics/remap32.cpp
engines/sci/graphics/remap32.h
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 1734221..02b2cea 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -1057,9 +1057,9 @@ reg_t kRemapColorsByRange(EngineState *s, int argc, reg_t *argv) {
const int16 from = argv[1].toSint16();
const int16 to = argv[2].toSint16();
const int16 base = argv[3].toSint16();
- // NOTE: There is an optional last parameter after `base`
- // which was only used by the priority map debugger, which
- // does not exist in release versions of SSCI
+ // There is an optional last parameter after `base` which was only used by
+ // the priority map debugger which does not exist in release versions of
+ // SSCI
g_sci->_gfxRemap32->remapByRange(color, from, to, base);
return s->r_acc;
}
@@ -1067,9 +1067,9 @@ reg_t kRemapColorsByRange(EngineState *s, int argc, reg_t *argv) {
reg_t kRemapColorsByPercent(EngineState *s, int argc, reg_t *argv) {
const uint8 color = argv[0].toUint16();
const int16 percent = argv[1].toSint16();
- // NOTE: There is an optional last parameter after `percent`
- // which was only used by the priority map debugger, which
- // does not exist in release versions of SSCI
+ // There is an optional last parameter after `percent` which was only used
+ // by the priority map debugger, which does not exist in release versions of
+ // SSCI
g_sci->_gfxRemap32->remapByPercent(color, percent);
return s->r_acc;
}
@@ -1077,9 +1077,9 @@ reg_t kRemapColorsByPercent(EngineState *s, int argc, reg_t *argv) {
reg_t kRemapColorsToGray(EngineState *s, int argc, reg_t *argv) {
const uint8 color = argv[0].toUint16();
const int16 gray = argv[1].toSint16();
- // NOTE: There is an optional last parameter after `gray`
- // which was only used by the priority map debugger, which
- // does not exist in release versions of SSCI
+ // There is an optional last parameter after `gray` which was only used by
+ // the priority map debugger, which does not exist in release versions of
+ // SSCI
g_sci->_gfxRemap32->remapToGray(color, gray);
return s->r_acc;
}
@@ -1088,9 +1088,9 @@ reg_t kRemapColorsToPercentGray(EngineState *s, int argc, reg_t *argv) {
const uint8 color = argv[0].toUint16();
const int16 gray = argv[1].toSint16();
const int16 percent = argv[2].toSint16();
- // NOTE: There is an optional last parameter after `percent`
- // which was only used by the priority map debugger, which
- // does not exist in release versions of SSCI
+ // There is an optional last parameter after `percent` which was only used
+ // by the priority map debugger, which does not exist in release versions of
+ // SSCI
g_sci->_gfxRemap32->remapToPercentGray(color, gray, percent);
return s->r_acc;
}
diff --git a/engines/sci/graphics/remap32.cpp b/engines/sci/graphics/remap32.cpp
index 9b5ffcd..6fe0a53 100644
--- a/engines/sci/graphics/remap32.cpp
+++ b/engines/sci/graphics/remap32.cpp
@@ -100,9 +100,9 @@ bool SingleRemap::updateBrightness() {
}
if (_percent != _lastPercent || _originalColorsChanged[i]) {
- // NOTE: SSCI checked if percent was over 100 and only
- // then clipped values, but we always unconditionally
- // ensure the result is in the correct range
+ // SSCI checked if percent was over 100 and only then clipped
+ // values, but we always unconditionally ensure the result is in the
+ // correct range for simplicity's sake
color.r = MIN(255, (uint16)color.r * _percent / 100);
color.g = MIN(255, (uint16)color.g * _percent / 100);
color.b = MIN(255, (uint16)color.b * _percent / 100);
@@ -188,8 +188,7 @@ bool SingleRemap::apply() {
const GfxRemap32 *const gfxRemap32 = g_sci->_gfxRemap32;
const uint8 remapStartColor = gfxRemap32->getStartColor();
- // Blocked colors are not allowed to be used as target
- // colors for the remap
+ // Blocked colors are not allowed to be used as target colors for the remap
bool blockedColors[236];
Common::fill(blockedColors, blockedColors + remapStartColor, false);
@@ -207,9 +206,8 @@ bool SingleRemap::apply() {
}
}
- // NOTE: SSCI did a loop over colors here to create a
- // new array of updated, unblocked colors, but then
- // never used it
+ // SSCI did a loop over colors here to create a new array of updated,
+ // unblocked colors, but then never used it
bool updated = false;
for (uint i = 1; i < remapStartColor; ++i) {
@@ -280,8 +278,8 @@ int16 SingleRemap::matchColor(const Color &color, const int minimumDistance, int
bestIndex = i;
}
- // This value is only valid if the last index to
- // perform a distance calculation was the best index
+ // This value is only valid if the last index to perform a distance
+ // calculation was the best index
outDistance = distance;
return bestIndex;
}
@@ -295,10 +293,9 @@ GfxRemap32::GfxRemap32() :
_blockedRangeCount(0),
_remapStartColor(236),
_numActiveRemaps(0) {
- // The `_remapStartColor` seems to always be 236 in SSCI,
- // but if it is ever changed then the various C-style
- // member arrays hard-coded to 236 need to be changed to
- // match the highest possible value of `_remapStartColor`
+ // The `_remapStartColor` seems to always be 236 in SSCI, but if it is ever
+ // changed then the various C-style member arrays hard-coded to 236 need to
+ // be changed to match the highest possible value of `_remapStartColor`
assert(_remapStartColor == 236);
if (g_sci->_features->hasMidPaletteCode()) {
@@ -316,9 +313,8 @@ void GfxRemap32::remapOff(const uint8 color) {
return;
}
- // NOTE: SSCI simply ignored invalid input values, but
- // we at least give a warning so games can be investigated
- // for script bugs
+ // SSCI simply ignored invalid input values, but we at least give a warning
+ // so games can be investigated for script bugs
if (color < _remapStartColor || color > _remapEndColor) {
warning("GfxRemap32::remapOff: %d out of remap range", color);
return;
@@ -341,9 +337,8 @@ void GfxRemap32::remapAllOff() {
}
void GfxRemap32::remapByRange(const uint8 color, const int16 from, const int16 to, const int16 delta) {
- // NOTE: SSCI simply ignored invalid input values, but
- // we at least give a warning so games can be investigated
- // for script bugs
+ // SSCI simply ignored invalid input values, but we at least give a warning
+ // so games can be investigated for script bugs
if (color < _remapStartColor || color > _remapEndColor) {
warning("GfxRemap32::remapByRange: %d out of remap range", color);
return;
@@ -375,9 +370,8 @@ void GfxRemap32::remapByRange(const uint8 color, const int16 from, const int16 t
}
void GfxRemap32::remapByPercent(const uint8 color, const int16 percent) {
- // NOTE: SSCI simply ignored invalid input values, but
- // we at least give a warning so games can be investigated
- // for script bugs
+ // SSCI simply ignored invalid input values, but we at least give a warning
+ // so games can be investigated for script bugs
if (color < _remapStartColor || color > _remapEndColor) {
warning("GfxRemap32::remapByPercent: %d out of remap range", color);
return;
@@ -397,9 +391,8 @@ void GfxRemap32::remapByPercent(const uint8 color, const int16 percent) {
}
void GfxRemap32::remapToGray(const uint8 color, const int8 gray) {
- // NOTE: SSCI simply ignored invalid input values, but
- // we at least give a warning so games can be investigated
- // for script bugs
+ // SSCI simply ignored invalid input values, but we at least give a warning
+ // so games can be investigated for script bugs
if (color < _remapStartColor || color > _remapEndColor) {
warning("GfxRemap32::remapToGray: %d out of remap range", color);
return;
@@ -423,9 +416,8 @@ void GfxRemap32::remapToGray(const uint8 color, const int8 gray) {
}
void GfxRemap32::remapToPercentGray(const uint8 color, const int16 gray, const int16 percent) {
- // NOTE: SSCI simply ignored invalid input values, but
- // we at least give a warning so games can be investigated
- // for script bugs
+ // SSCI simply ignored invalid input values, but we at least give a warning
+ // so games can be investigated for script bugs
if (color < _remapStartColor || color > _remapEndColor) {
warning("GfxRemap32::remapToPercentGray: %d out of remap range", color);
return;
diff --git a/engines/sci/graphics/remap32.h b/engines/sci/graphics/remap32.h
index 407e879..9fc7ef6 100644
--- a/engines/sci/graphics/remap32.h
+++ b/engines/sci/graphics/remap32.h
@@ -55,8 +55,7 @@ public:
RemapType _type;
/**
- * The first color that should be shifted by a range
- * remap.
+ * The first color that should be shifted by a range remap.
*/
uint8 _from;
@@ -66,158 +65,140 @@ public:
uint8 _to;
/**
- * The direction and amount that the colors should be
- * shifted in a range remap.
+ * The direction and amount that the colors should be shifted in a range
+ * remap.
*/
int16 _delta;
/**
- * The difference in brightness that should be
- * applied by a brightness (percent) remap.
+ * The difference in brightness that should be applied by a brightness
+ * (percent) remap.
*
- * This value may be be greater than 100, in
- * which case the color will be oversaturated.
+ * This value may be be greater than 100, in which case the color will be
+ * oversaturated.
*/
int16 _percent;
/**
- * The amount of desaturation that should be
- * applied by a saturation (gray) remap, where
- * 0 is full saturation and 100 is full
- * desaturation.
+ * The amount of desaturation that should be applied by a saturation (gray)
+ * remap, where 0 is full saturation and 100 is full desaturation.
*/
uint8 _gray;
/**
- * The final array used by CelObj renderers to composite
- * remapped pixels to the screen buffer.
+ * The final array used by CelObj renderers to composite remapped pixels to
+ * the screen buffer.
*
* Here is how it works:
*
- * The source bitmap being rendered will have pixels
- * within the remap range (236-245 or 236-254), and the
- * target buffer will have colors in the non-remapped
- * range (0-235).
+ * The source bitmap being rendered will have pixels within the remap range
+ * (236-245 or 236-254), and the target buffer will have colors in the
+ * non-remapped range (0-235).
*
- * To arrive at the correct color, first the source
- * pixel is used to look up the correct SingleRemap for
- * that pixel. Then, the final composited color is
- * looked up in this array using the target's pixel
- * color. In other words,
+ * To arrive at the correct color, first the source pixel is used to look up
+ * the correct SingleRemap for that pixel. Then, the final composited color
+ * is looked up in this array using the target's pixel color. In other
+ * words,
* `target = _remaps[remapEndColor - source].remapColors[target]`.
*/
uint8 _remapColors[236];
/**
- * Resets this SingleRemap's color information to
- * default values.
+ * Resets this SingleRemap's color information to default values.
*/
void reset();
/**
- * Recalculates and reapplies remap colors to the
- * `_remapColors` array.
+ * Recalculates and reapplies remap colors to the `_remapColors` array.
*/
bool update();
private:
/**
- * The previous brightness value. Used to
- * determine whether or not targetColors needs
- * to be updated.
+ * The previous brightness value. Used to determine whether or not
+ * `_idealColors` needs to be updated.
*/
int16 _lastPercent;
/**
- * The previous saturation value. Used to
- * determine whether or not targetColors needs
- * to be updated.
+ * The previous saturation value. Used to determine whether or not
+ * `_idealColors` needs to be updated.
*/
uint8 _lastGray;
/**
- * The colors from the current GfxPalette32 palette
- * before this SingleRemap is applied.
+ * The colors from the current GfxPalette32 palette before this SingleRemap
+ * is applied.
*/
Color _originalColors[236];
/**
- * Map of colors that changed in `_originalColors`
- * when this SingleRemap was updated. This map is
- * transient and gets reset to `false` after the
+ * Map of colors that changed in `_originalColors` when this SingleRemap was
+ * updated. This map is transient and gets reset to `false` after the
* SingleRemap finishes updating.
*/
bool _originalColorsChanged[236];
/**
- * The ideal target RGB color values for each generated
- * remap color.
+ * The ideal target RGB color values for each generated remap color.
*/
Color _idealColors[236];
/**
- * Map of colors that changed in `_idealColors` when
- * this SingleRemap was updated. This map is transient
- * and gets reset to `false` after the SingleRemap
- * finishes applying.
+ * Map of colors that changed in `_idealColors` when this SingleRemap was
+ * updated. This map is transient and gets reset to `false` after the
+ * SingleRemap finishes applying.
*/
bool _idealColorsChanged[236];
/**
- * When applying a SingleRemap, finding an appropriate
- * color in the palette is the responsibility of a
- * distance function. Once a match is found, the
- * distance of that match is stored here so that the
- * next time the SingleRemap is applied, it can check
- * the distance from the previous application and avoid
- * triggering an expensive redraw of the entire screen
+ * When applying a SingleRemap, finding an appropriate color in the palette
+ * is the responsibility of a distance function. Once a match is found, the
+ * distance of that match is stored here so that the next time the
+ * SingleRemap is applied, it can check the distance from the previous
+ * application and avoid triggering an expensive redraw of the entire screen
* if the new palette value only changed slightly.
*/
int _matchDistances[236];
/**
- * Computes the final target values for a range remap
- * and applies them directly to the `_remaps` map.
+ * Computes the final target values for a range remap and applies them
+ * directly to the `_remaps` map.
*
* @note Was ByRange in SSCI.
*/
bool updateRange();
/**
- * Computes the intermediate target values for a
- * brightness remap and applies them indirectly via
- * the `apply` method.
+ * Computes the intermediate target values for a brightness remap and
+ * applies them indirectly via the `apply` method.
*
* @note Was ByPercent in SSCI.
*/
bool updateBrightness();
/**
- * Computes the intermediate target values for a
- * saturation remap and applies them indirectly via
- * the `apply` method.
+ * Computes the intermediate target values for a saturation remap and
+ * applies them indirectly via the `apply` method.
*
* @note Was ToGray in SSCI.
*/
bool updateSaturation();
/**
- * Computes the intermediate target values for a
- * saturation + brightness bitmap and applies them
- * indirectly via the `apply` method.
+ * Computes the intermediate target values for a saturation + brightness
+ * bitmap and applies them indirectly via the `apply` method.
*
* @note Was ToPercentGray in SSCI.
*/
bool updateSaturationAndBrightness();
/**
- * Computes and applies the final values to the
- * `_remaps` map.
+ * Computes and applies the final values to the `_remaps` map.
*
- * @note In SSCI, a boolean array of changed values
- * was passed into this method, but this was done by
- * creating arrays on the stack in the caller. Instead
- * of doing this, we simply add another member property
+ * @note In SSCI, a boolean array of changed values was passed into this
+ * method, but this was done by creating arrays on the stack in the caller.
+ * Instead of doing this, we simply add another member property
* `_idealColorsChanged` and use that instead.
*/
bool apply();
@@ -225,19 +206,18 @@ private:
/**
* Calculates the square distance of two colors.
*
- * @note In SSCI this method is Rgb24::Dist, but it is
- * only used by SingleRemap.
+ * @note In SSCI this method is Rgb24::Dist, but it is only used by
+ * SingleRemap.
*/
int colorDistance(const Color &a, const Color &b) const;
/**
- * Finds the closest index in the next palette matching
- * the given RGB color. Returns -1 if no match can be
- * found that is closer than `minimumDistance`.
+ * Finds the closest index in the next palette matching the given RGB color.
+ * Returns -1 if no match can be found that is closer than
+ * `minimumDistance`.
*
- * @note In SSCI, this method is SOLPalette::Match, but
- * this particular signature is only used by
- * SingleRemap.
+ * @note In SSCI, this method is SOLPalette::Match, but this particular
+ * signature is only used by SingleRemap.
*/
int16 matchColor(const Color &color, const int minimumDistance, int &outDistance, const bool *const blockedIndexes) const;
};
@@ -246,8 +226,7 @@ private:
#pragma mark GfxRemap32
/**
- * This class provides color remapping support for SCI32
- * games.
+ * This class provides color remapping support for SCI32 games.
*/
class GfxRemap32 : public Common::Serializable {
public:
@@ -262,8 +241,8 @@ public:
inline int16 getBlockedRangeCount() const { return _blockedRangeCount; }
/**
- * Turns off remapping of the given color. If `color` is
- * 0, all remaps are turned off.
+ * Turns off remapping of the given color. If `color` is 0, all remaps are
+ * turned off.
*/
void remapOff(const uint8 color);
@@ -273,55 +252,48 @@ public:
void remapAllOff();
/**
- * Configures a SingleRemap for the remap color `color`.
- * The SingleRemap will shift palette colors between
- * `from` and `to` (inclusive) by `delta` palette
- * entries when the remap is applied.
+ * Configures a SingleRemap for the remap color `color`. The SingleRemap
+ * will shift palette colors between `from` and `to` (inclusive) by `delta`
+ * palette entries when the remap is applied.
*/
void remapByRange(const uint8 color, const int16 from, const int16 to, const int16 delta);
/**
- * Configures a SingleRemap for the remap color `color`
- * to modify the brightness of remapped colors by
- * `percent`.
+ * Configures a SingleRemap for the remap color `color` to modify the
+ * brightness of remapped colors by `percent`.
*/
void remapByPercent(const uint8 color, const int16 percent);
/**
- * Configures a SingleRemap for the remap color `color`
- * to modify the saturation of remapped colors by
- * `gray`.
+ * Configures a SingleRemap for the remap color `color` to modify the
+ * saturation of remapped colors by `gray`.
*/
void remapToGray(const uint8 color, const int8 gray);
/**
- * Configures a SingleRemap for the remap color `color`
- * to modify the brightness of remapped colors by
- * `percent`, and saturation of remapped colors by
- * `gray`.
+ * Configures a SingleRemap for the remap color `color` to modify the
+ * brightness of remapped colors by `percent`, and saturation of remapped
+ * colors by `gray`.
*/
void remapToPercentGray(const uint8 color, const int16 gray, const int16 percent);
/**
- * Prevents GfxRemap32 from using the given range of
- * palette entries as potential remap targets.
+ * Prevents GfxRemap32 from using the given range of palette entries as
+ * potential remap targets.
*
* @NOTE Was DontMapToRange in SSCI.
*/
void blockRange(const uint8 from, const int16 count);
/**
- * Determines whether or not the given color has an
- * active remapper. If it does not, it is treated as a
- * skip color and the pixel is not drawn.
+ * Determines whether or not the given color has an active remapper. If it
+ * does not, it is treated as a skip color and the pixel is not drawn.
*
- * @note SSCI uses a boolean array to decide whether a
- * a pixel is remapped, but it is possible to get the
- * same information from `_remaps`, as this function
- * does.
- * Presumably, the separate array was created for
- * performance reasons, since this is called a lot in
- * the most critical section of the renderer.
+ * @note SSCI uses a boolean array to decide whether a pixel is remapped,
+ * but it is possible to get the same information from `_remaps`, as this
+ * function does. Presumably, the separate array was created for performance
+ * reasons, since this is called a lot in the most critical section of the
+ * renderer.
*/
inline bool remapEnabled(uint8 color) const {
const uint8 index = _remapEndColor - color;
@@ -335,10 +307,9 @@ public:
}
/**
- * Calculates the correct color for a target by looking
- * up the target color in the SingleRemap that controls
- * the given sourceColor. If there is no remap for the
- * given color, it will be treated as a skip color.
+ * Calculates the correct color for a target by looking up the target color
+ * in the SingleRemap that controls the given sourceColor. If there is no
+ * remap for the given color, it will be treated as a skip color.
*/
inline uint8 remapColor(const uint8 sourceColor, const uint8 targetColor) const {
const uint8 index = _remapEndColor - sourceColor;
@@ -358,12 +329,11 @@ public:
}
/**
- * Updates all active remaps in response to a palette
- * change or a remap settings change.
+ * Updates all active remaps in response to a palette change or a remap
+ * settings change.
*
- * `paletteChanged` is true if the next palette in
- * GfxPalette32 has been previously modified by other
- * palette operations.
+ * `paletteChanged` is true if the next palette in GfxPalette32 has been
+ * previously modified by other palette operations.
*/
bool remapAllTables(const bool paletteUpdated);
@@ -371,14 +341,12 @@ private:
typedef Common::Array<SingleRemap> SingleRemapsList;
/**
- * The first index of the remap area in the system
- * palette.
+ * The first index of the remap area in the system palette.
*/
const uint8 _remapStartColor;
/**
- * The last index of the remap area in the system
- * palette.
+ * The last index of the remap area in the system palette.
*/
uint8 _remapEndColor;
@@ -393,20 +361,19 @@ private:
SingleRemapsList _remaps;
/**
- * If true, indicates that one or more SingleRemaps were
- * reconfigured and all remaps need to be recalculated.
+ * If true, indicates that one or more SingleRemaps were reconfigured and
+ * all remaps need to be recalculated.
*/
bool _needsUpdate;
/**
- * The first color that is blocked from being used as a
- * remap target color.
+ * The first color that is blocked from being used as a remap target color.
*/
uint8 _blockedRangeStart;
/**
- * The size of the range of blocked colors. If zero,
- * all colors are potential targets for remapping.
+ * The size of the range of blocked colors. If zero, all colors are
+ * potential targets for remapping.
*/
int16 _blockedRangeCount;
};
Commit: 31e1d0932cf4cdba7fdb1d1eec6e349fcc3c0ac0
https://github.com/scummvm/scummvm/commit/31e1d0932cf4cdba7fdb1d1eec6e349fcc3c0ac0
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:11:03-05:00
Commit Message:
SCI32: Clean up Plane
* Rewrap comments to 80 columns
* Clarify comments where possible
Changed paths:
engines/sci/engine/features.h
engines/sci/graphics/plane32.cpp
engines/sci/graphics/plane32.h
diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h
index 92cc45a..7a1c6f5 100644
--- a/engines/sci/engine/features.h
+++ b/engines/sci/engine/features.h
@@ -128,7 +128,7 @@ public:
inline bool hasTransparentPicturePlanes() const {
const SciGameId &gid = g_sci->getGameId();
- // NOTE: MGDX is assumed to not have transparent picture planes since it
+ // MGDX is assumed to not have transparent picture planes since it
// was released before SQ6, but this has not been verified since it
// cannot be disassembled at the moment (Phar Lap Windows-only release)
return getSciVersion() >= SCI_VERSION_2_1_MIDDLE &&
diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp
index 08708f2..77ca620 100644
--- a/engines/sci/graphics/plane32.cpp
+++ b/engines/sci/graphics/plane32.cpp
@@ -320,9 +320,9 @@ void Plane::calcLists(Plane &visiblePlane, const PlaneList &planeList, DrawList
for (ScreenItemList::size_type i = 0; i < screenItemCount; ++i) {
// Items can be added to ScreenItemList and we don't want to process
- // those new items, but the list also can grow smaller, so we need
- // to check that we are still within the upper bound of the list and
- // quit if we aren't any more
+ // those new items, but the list also can grow smaller, so we need to
+ // check that we are still within the upper bound of the list and quit
+ // if we aren't any more
if (i >= _screenItemList.size()) {
break;
}
@@ -332,18 +332,17 @@ void Plane::calcLists(Plane &visiblePlane, const PlaneList &planeList, DrawList
continue;
}
- // NOTE: The original engine used an array without bounds checking
- // so could just get the visible screen item directly; we need to
- // verify that the index is actually within the valid range for
- // the visible plane before accessing the item to avoid a range
- // error.
+ // SSCI used an array without bounds checking so could just get the
+ // visible screen item directly; we need to verify that the index is
+ // actually within the valid range for the visible plane before
+ // accessing the item to avoid a range error.
const ScreenItem *visibleItem = nullptr;
if (i < visiblePlaneItemCount) {
visibleItem = visiblePlane._screenItemList[i];
}
- // Keep erase rects for this screen item from drawing outside
- // of its owner plane
+ // Keep erase rects for this screen item from drawing outside of its
+ // owner plane
Common::Rect visibleItemScreenRect;
if (visibleItem != nullptr) {
visibleItemScreenRect = visibleItem->_screenRect;
@@ -427,8 +426,8 @@ void Plane::calcLists(Plane &visiblePlane, const PlaneList &planeList, DrawList
breakEraseListByPlanes(eraseList, planeList);
breakDrawListByPlanes(drawList, planeList);
- // We store the current size of the drawlist, as we want to loop
- // over the currently inserted entries later.
+ // The current size of the draw list is stored here, as we need to loop over
+ // only the already-inserted entries later.
DrawList::size_type drawListSizePrimary = drawList.size();
const RectList::size_type eraseListCount = eraseList.size();
@@ -823,8 +822,8 @@ void Plane::sync(const Plane *other, const Common::Rect &screenRect) {
convertGameRectToPlaneRect();
_screenRect = _planeRect;
- // NOTE: screenRect originally was retrieved through globals
- // instead of being passed into the function
+ // screenRect was retrieved through globals in SSCI instead of being passed
+ // into the function. We don't do that just to avoid the extra indirection
clipScreenRect(screenRect);
}
diff --git a/engines/sci/graphics/plane32.h b/engines/sci/graphics/plane32.h
index a34df1c..406c3f8 100644
--- a/engines/sci/graphics/plane32.h
+++ b/engines/sci/graphics/plane32.h
@@ -40,8 +40,7 @@ enum PlaneType {
};
enum PlanePictureCodes {
- // NOTE: Any value at or below 65531 means the plane
- // is a kPlaneTypePicture.
+ // Any value at or below 65531 means the plane is a kPlaneTypePicture
kPlanePic = 65531,
kPlanePicTransparentPicture = 65532,
kPlanePicOpaque = 65533,
@@ -104,61 +103,52 @@ class PlaneList;
class Plane {
private:
/**
- * A serial used for planes that are generated inside
- * the graphics engine, rather than the interpreter.
+ * A serial used for planes that are generated inside the graphics engine,
+ * rather than the interpreter.
*/
static uint16 _nextObjectId;
/**
- * A serial used to identify the creation order of
- * planes, to ensure a stable sort order for planes
- * with identical priorities.
+ * A serial used to identify the creation order of planes, to ensure a
+ * stable sort order for planes with identical priorities.
*/
static uint32 _nextCreationId;
/**
- * The creation order number, which ensures a stable
- * sort when planes with identical priorities are added
- * to the plane list.
+ * The creation order number, which ensures a stable sort when planes with
+ * identical priorities are added to the plane list.
*/
uint32 _creationId;
/**
- * For planes that are used to render picture data, the
- * resource ID of the picture to be displayed. This
- * value may also be one of the special
- * PlanePictureCodes, in which case the plane becomes a
- * non-picture plane.
+ * For planes that are used to render picture data, the resource ID of the
+ * picture to be displayed. This value may also be one of the special
+ * PlanePictureCodes, in which case the plane becomes a non-picture plane.
*/
GuiResourceId _pictureId;
/**
- * Whether or not the contents of picture planes should
- * be drawn horizontally mirrored. Only applies to
- * planes of type kPlaneTypePicture.
+ * Whether or not the contents of picture planes should be drawn
+ * horizontally mirrored. Only applies to planes of type kPlaneTypePicture.
*/
bool _mirrored;
/**
- * Whether the picture ID for this plane has changed.
- * This flag is set when the plane is created or updated
- * from a VM object, and is cleared when the plane is
- * synchronised to another plane (which calls
- * changePic).
+ * Whether the picture ID for this plane has changed. This flag is set when
+ * the plane is created or updated from a VM object, and is cleared when the
+ * plane is synchronised to another plane (which calls changePic).
*/
bool _pictureChanged;
/**
- * Converts the dimensions of the game rect used by
- * scripts to the dimensions of the plane rect used to
- * render content to the screen. Coordinates with
- * remainders are rounded up to the next whole pixel.
+ * Converts the dimensions of the game rect used by scripts to the
+ * dimensions of the plane rect used to render content to the screen.
+ * Coordinates with remainders are rounded up to the next whole pixel.
*/
void convertGameRectToPlaneRect();
/**
- * Sets the type of the plane according to its assigned
- * picture resource ID.
+ * Sets the type of the plane according to its assigned picture resource ID.
*/
void setType();
@@ -169,80 +159,73 @@ public:
PlaneType _type;
/**
- * The color to use when erasing the plane. Only
- * applies to planes of type kPlaneTypeColored.
+ * The color to use when erasing the plane. Only applies to planes of type
+ * kPlaneTypeColored.
*/
byte _back;
/**
- * Whether the priority of this plane has changed.
- * This flag is set when the plane is updated from
- * another plane and cleared when draw list calculation
- * occurs.
+ * Whether the priority of this plane has changed. This flag is set when the
+ * plane is updated from another plane and cleared when draw list
+ * calculation occurs.
*/
int _priorityChanged;
/**
- * A handle to the VM object corresponding to this
- * plane. Some planes are generated purely within the
- * graphics engine and have a numeric object value.
+ * A handle to the VM object corresponding to this plane. Some planes are
+ * generated purely within the graphics engine and have a numeric object
+ * value.
*/
reg_t _object;
/**
- * The rendering priority of the plane. Higher
- * priorities are drawn above lower priorities.
+ * The rendering priority of the plane. Higher priorities are drawn above
+ * lower priorities.
*/
int16 _priority;
/**
- * Whether or not all screen items in this plane should
- * be redrawn on the next frameout, instead of just
- * the screen items marked as updated. This is set when
- * visual changes to the plane itself are made that
- * affect the rendering of the entire plane, and cleared
- * once those changes are rendered by `redrawAll`.
+ * Whether or not all screen items in this plane should be redrawn on the
+ * next frameout, instead of just the screen items marked as updated. This
+ * is set when visual changes to the plane itself are made that affect the
+ * rendering of the entire plane, and cleared once those changes are
+ * rendered by `redrawAll`.
*/
int _redrawAllCount;
/**
* Flags indicating the state of the plane.
- * - `created` is set when the plane is first created,
- * either from a VM object or from within the engine
- * itself
- * - `updated` is set when the plane is updated from
- * another plane and the two planes' `planeRect`s do
- * not match
- * - `deleted` is set when the plane is deleted by a
- * kernel call
- * - `moved` is set when the plane has been moved or
- * resized
+ * - `created` is set when the plane is first created, either from a VM
+ * object or from within the engine itself
+ * - `updated` is set when the plane is updated from another plane and the
+ * two planes' `planeRect`s do not match
+ * - `deleted` is set when the plane is deleted by a kernel call
+ * - `moved` is set when the plane has been moved or resized
*/
int _created, _updated, _deleted, _moved;
/**
- * The vanishing point for the plane. Used when
- * automatically calculating the correct scaling of the
- * plane's screen items according to their position.
+ * The vanishing point for the plane. Used when automatically calculating
+ * the correct scaling of the plane's screen items according to their
+ * position.
*/
Common::Point _vanishingPoint;
/**
- * The position & dimensions of the plane in screen
- * coordinates. This rect is not clipped to the screen,
- * so may include coordinates that are offscreen.
+ * The position & dimensions of the plane in screen coordinates. This rect
+ * is not clipped to the screen, so may include coordinates that are
+ * offscreen.
*/
Common::Rect _planeRect;
/**
- * The position & dimensions of the plane in game script
- * coordinates.
+ * The position & dimensions of the plane in game script coordinates.
*/
Common::Rect _gameRect;
/**
- * The position & dimensions of the plane in screen
- * coordinates. This rect is clipped to the screen.
+ * The position & dimensions of the plane in screen coordinates. This rect
+ * is clipped to the screen.
*/
Common::Rect _screenRect;
@@ -257,10 +240,10 @@ public:
*/
static void init();
- // NOTE: This constructor signature originally did not accept a
- // picture ID, but some calls to construct planes with this signature
- // immediately set the picture ID and then called setType again, so
- // it made more sense to just make the picture ID a parameter instead.
+ // In SSCI this constructor signature did not accept a picture ID, but some
+ // calls to construct planes with this signature immediately set the picture
+ // ID and then called setType again, so it made more sense to just make the
+ // picture ID a parameter instead.
Plane(const Common::Rect &gameRect, PlanePictureCodes pictureId = kPlanePicColored);
Plane(const reg_t object);
@@ -284,14 +267,13 @@ public:
}
/**
- * Clips the screen rect of this plane to fit within the
- * given screen rect.
+ * Clips the screen rect of this plane to fit within the given screen rect.
*/
inline void clipScreenRect(const Common::Rect &screenRect) {
- // LSL6 hires creates planes with invalid rects; SSCI does not
- // care about this, but `Common::Rect::clip` does, so we need to
- // check whether or not the rect is actually valid before clipping
- // and only clip valid rects
+ // LSL6 hires creates planes with invalid rects; SSCI does not care
+ // about this, but `Common::Rect::clip` does, so we need to check
+ // whether or not the rect is actually valid before clipping and only
+ // clip valid rects
if (_screenRect.isValidRect() && _screenRect.intersects(screenRect)) {
_screenRect.clip(screenRect);
} else {
@@ -305,30 +287,25 @@ public:
void printDebugInfo(Console *con) const;
/**
- * Compares the properties of the current plane against
- * the properties of the `other` plane (which is the
- * corresponding plane from the visible plane list) to
- * discover which properties have been changed on this
- * plane by a call to `update(reg_t)`.
+ * Compares the properties of the current plane against the properties of
+ * the `other` plane (which is the corresponding plane from the visible
+ * plane list) to discover which properties have been changed on this plane
+ * by a call to `update(reg_t)`.
*
- * @note This method was originally called UpdatePlane
- * in SCI engine.
+ * @note This method was called UpdatePlane in SSCI.
*/
void sync(const Plane *other, const Common::Rect &screenRect);
/**
- * Updates the plane to match the state of the plane
- * object from the virtual machine.
+ * Updates the plane to match the state of the plane object from the VM.
*
- * @note This method was originally called UpdatePlane
- * in SCI engine.
+ * @note This method was called UpdatePlane in SSCI.
*/
void update(const reg_t object);
/**
- * Modifies the position of all non-pic screen items
- * by the given delta. If `scrollPics` is true, pic
- * items are also repositioned.
+ * Modifies the position of all non-pic screen items by the given delta. If
+ * `scrollPics` is true, pic items are also repositioned.
*/
void scrollScreenItems(const int16 deltaX, const int16 deltaY, const bool scrollPics);
@@ -336,47 +313,43 @@ public:
#pragma mark Plane - Pic
private:
/**
- * Adds all cels from the specified picture resource to
- * the plane as screen items. If a position is provided,
- * the screen items will be given that position;
- * otherwise, the default relative positions for each
- * cel will be taken from the picture resource data.
+ * Adds all cels from the specified picture resource to the plane as screen
+ * items. If a position is provided, the screen items will be given that
+ * position; otherwise, the default relative positions for each cel will be
+ * taken from the picture resource data.
*/
inline void addPicInternal(const GuiResourceId pictureId, const Common::Point *position, const bool mirrorX);
/**
- * Marks all screen items to be deleted that are within
- * this plane and match the given picture ID.
+ * Marks all screen items to be deleted that are within this plane and match
+ * the given picture ID.
*/
void deletePic(const GuiResourceId pictureId);
/**
- * Marks all screen items to be deleted that are within
- * this plane and are picture cels.
+ * Marks all screen items to be deleted that are within this plane and are
+ * picture cels.
*/
void deleteAllPics();
public:
/**
- * Marks all existing screen items matching the current
- * picture to be deleted, then adds all cels from the
- * new picture resource to the plane at the given
- * position.
+ * Marks all existing screen items matching the current picture to be
+ * deleted, then adds all cels from the new picture resource to the plane at
+ * the given position.
*/
GuiResourceId addPic(const GuiResourceId pictureId, const Common::Point &position, const bool mirrorX, const bool deleteDuplicate = true);
/**
- * If the plane is a picture plane, re-adds all cels
- * from its picture resource to the plane. Otherwise,
- * just clears the _pictureChanged flag.
+ * If the plane is a picture plane, re-adds all cels from its picture
+ * resource to the plane. Otherwise, just clears the _pictureChanged flag.
*/
void changePic();
/**
- * Marks all screen items to be deleted that are within
- * this plane and match the given picture ID, then sets
- * the picture ID of the plane to the new picture ID
- * without adding any screen items.
+ * Marks all screen items to be deleted that are within this plane and match
+ * the given picture ID, then sets the picture ID of the plane to the new
+ * picture ID without adding any screen items.
*/
void deletePic(const GuiResourceId oldPictureId, const GuiResourceId newPictureId);
@@ -384,120 +357,111 @@ public:
#pragma mark Plane - Rendering
private:
/**
- * Splits all rects in the given draw list at the edges
- * of all higher-priority, non-transparent, intersecting
- * planes.
+ * Splits all rects in the given draw list at the edges of all
+ * higher-priority, non-transparent, intersecting planes.
*/
void breakDrawListByPlanes(DrawList &drawList, const PlaneList &planeList) const;
/**
- * Splits all rects in the given erase list at the
- * edges of higher-priority, non-transparent,
- * intersecting planes.
+ * Splits all rects in the given erase list at the edges of higher-priority,
+ * non-transparent, intersecting planes.
*/
void breakEraseListByPlanes(RectList &eraseList, const PlaneList &planeList) const;
/**
- * Adds the screen item at `index` into `drawList`,
- * ensuring it is only drawn within the bounds of
- * `rect`. If an existing draw list entry exists
- * for this screen item, it will be modified.
- * Otherwise, a new entry will be added.
+ * Adds the screen item at `index` into `drawList`, ensuring it is only
+ * drawn within the bounds of `rect`. If an existing draw list entry exists
+ * for this screen item, it will be modified. Otherwise, a new entry will be
+ * added.
*/
void mergeToDrawList(const DrawList::size_type index, const Common::Rect &rect, DrawList &drawList) const;
/**
- * Merges `rect` with an existing rect in `eraseList`,
- * if possible. Otherwise, adds the rect as a new entry
- * to `eraseList`.
+ * Merges `rect` with an existing rect in `eraseList`, if possible.
+ * Otherwise, adds the rect as a new entry to `eraseList`.
*/
void mergeToRectList(const Common::Rect &rect, RectList &eraseList) const;
public:
/**
- * Calculates the location and dimensions of dirty rects
- * of the screen items in this plane and adds them to
- * the given draw and erase lists, and synchronises this
- * plane's list of screen items to the given visible
+ * Calculates the location and dimensions of dirty rects of the screen items
+ * in this plane and adds them to the given draw and erase lists, and
+ * synchronises this plane's list of screen items to the given visible
* plane.
*/
void calcLists(Plane &visiblePlane, const PlaneList &planeList, DrawList &drawList, RectList &eraseList);
/**
- * Synchronises changes to screen items from the current
- * plane to the visible plane and deletes screen items
- * from the current plane that have been marked as
- * deleted. If `forceUpdate` is true, all screen items
- * on the visible plane will be updated, even if they
- * are not marked as having changed.
+ * Synchronises changes to screen items from the current plane to the
+ * visible plane and deletes screen items from the current plane that have
+ * been marked as deleted. If `forceUpdate` is true, all screen items on the
+ * visible plane will be updated, even if they are not marked as having
+ * changed.
*/
void decrementScreenItemArrayCounts(Plane *visiblePlane, const bool forceUpdate);
/**
- * This method is called from the highest priority plane
- * to the lowest priority plane.
+ * This method is called from the highest priority plane to the lowest
+ * priority plane.
*
- * Adds screen items from this plane to the draw list
- * that must be redrawn because they intersect entries
- * in the `higherEraseList`.
+ * Adds screen items from this plane to the draw list that must be redrawn
+ * because they intersect entries in the `higherEraseList`.
*
- * If this plane is opaque, all intersecting erase rects
- * in `lowerEraseList` are removed, as they would be
- * completely overwritten by the contents of this plane.
+ * If this plane is opaque, all intersecting erase rects in `lowerEraseList`
+ * are removed, as they would be completely overwritten by the contents of
+ * this plane.
*
- * If this plane is transparent, erase rects from the
- * `lowerEraseList` are added to the erase list for this
- * plane, so that lower planes.
+ * If this plane is transparent, erase rects from the `lowerEraseList` are
+ * added to the erase list for this plane, so that lower planes.
*
* @param drawList The draw list for this plane.
* @param eraseList The erase list for this plane.
- * @param higherEraseList The erase list for a plane
- * above this plane.
+ * @param higherEraseList The erase list for a plane above this plane.
*/
void filterDownEraseRects(DrawList &drawList, RectList &eraseList, RectList &higherEraseList) const;
/**
- * This method is called from the lowest priority plane
- * to the highest priority plane.
+ * This method is called from the lowest priority plane to the highest
+ * priority plane.
*
- * Adds screen items from this plane to the draw list
- * that must be drawn because the lower plane is being
- * redrawn and potentially transparent screen items
- * from this plane would draw over the lower priority
- * plane's screen items.
+ * Adds screen items from this plane to the draw list that must be drawn
+ * because the lower plane is being redrawn and potentially transparent
+ * screen items from this plane would draw over the lower priority plane's
+ * screen items.
*
* This method applies only to transparent planes.
*
* @param drawList The draw list for this plane.
- * @param eraseList The erase list for a plane below
- * this plane.
+ * @param eraseList The erase list for a plane below this plane.
*/
void filterUpEraseRects(DrawList &drawList, const RectList &lowerEraseList) const;
/**
- * This method is called from the lowest priority plane
- * to the highest priority plane.
+ * This method is called from the lowest priority plane to the highest
+ * priority plane.
*
- * Adds screen items from this plane to the draw list
- * that must be drawn because the lower plane is being
- * redrawn and potentially transparent screen items
- * from this plane would draw over the lower priority
- * plane's screen items.
+ * Adds screen items from this plane to the draw list that must be drawn
+ * because the lower plane is being redrawn and potentially transparent
+ * screen items from this plane would draw over the lower priority plane's
+ * screen items.
*
* This method applies only to transparent planes.
*
* @param drawList The draw list for this plane.
- * @param lowerDrawList The draw list for a plane below
- * this plane.
+ * @param lowerDrawList The draw list for a plane below this plane.
*/
void filterUpDrawRects(DrawList &drawList, const DrawList &lowerDrawList) const;
/**
- * Updates all of the plane's non-deleted screen items
- * and adds them to the given draw and erase lists.
+ * Updates all of the plane's non-deleted screen items and adds them to the
+ * given draw and erase lists.
*/
void redrawAll(Plane *visiblePlane, const PlaneList &planeList, DrawList &drawList, RectList &eraseList);
+ /**
+ * Marks all non-deleted remapped screen items within the plane as needing
+ * to be updated during the next frameout.
+ */
void remapMarkRedraw();
};
@@ -514,10 +478,9 @@ private:
using PlaneListBase::push_back;
public:
- // A method for finding the index of a plane inside a
- // PlaneList is used because entries in the main plane
- // list and visible plane list of GfxFrameout are
- // synchronised by index
+ // A method for finding the index of a plane inside a PlaneList is used
+ // because entries in the main plane list and visible plane list of
+ // GfxFrameout are synchronised by index
int findIndexByObject(const reg_t object) const;
Plane *findByObject(const reg_t object) const;
@@ -527,8 +490,8 @@ public:
int16 getTopPlanePriority() const;
/**
- * Gets the priority of the top plane in the plane list
- * created by a game script.
+ * Gets the priority of the top plane in the plane list created by a game
+ * script.
*/
int16 getTopSciPlanePriority() const;
Commit: 4521e9774af526b945f550c7607cf1b82d649154
https://github.com/scummvm/scummvm/commit/4521e9774af526b945f550c7607cf1b82d649154
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:11:03-05:00
Commit Message:
SCI32: Clean up GfxPaint32
* Rewrap comments to 80 columns
Changed paths:
engines/sci/graphics/paint32.cpp
diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp
index 8a63365..f4d9c9f 100644
--- a/engines/sci/graphics/paint32.cpp
+++ b/engines/sci/graphics/paint32.cpp
@@ -42,9 +42,9 @@ reg_t GfxPaint32::kernelAddLine(const reg_t planeObject, const Common::Point &st
CelInfo32 celInfo;
celInfo.type = kCelTypeMem;
celInfo.bitmap = bitmapId;
- // SSCI stores the line color on `celInfo`, even though
- // this is not a `kCelTypeColor`, as a hack so that
- // `kUpdateLine` can get the originally used color
+ // SSCI stores the line color on `celInfo`, even though this is not a
+ // `kCelTypeColor`, as a hack so that `kUpdateLine` can get the originally
+ // used color
celInfo.color = color;
ScreenItem *screenItem = new ScreenItem(planeObject, celInfo, gameRect);
@@ -93,7 +93,8 @@ void GfxPaint32::plotter(int x, int y, int color, void *data) {
const uint32 index = bitmapWidth * y + x;
// Only draw the points in the bitmap, and ignore the rest. SSCI scripts
- // can draw lines ending outside the visible area (e.g. negative coordinates)
+ // can draw lines ending outside the visible area (e.g. negative
+ // coordinates)
if (x >= 0 && x < bitmapWidth && y >= 0 && y < bitmapHeight) {
if (properties.solid) {
pixels[index] = (uint8)color;
Commit: d5e09a9f68a8032b1e5887e50df96e16fda827be
https://github.com/scummvm/scummvm/commit/d5e09a9f68a8032b1e5887e50df96e16fda827be
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:56:13-05:00
Commit Message:
SCI32: Rewrap comments to 80 columns in lists32.h
Changed paths:
engines/sci/graphics/lists32.h
diff --git a/engines/sci/graphics/lists32.h b/engines/sci/graphics/lists32.h
index ff0bc6c..82e9e58 100644
--- a/engines/sci/graphics/lists32.h
+++ b/engines/sci/graphics/lists32.h
@@ -28,13 +28,11 @@
namespace Sci {
/**
- * StablePointerArray holds pointers in a fixed-size array
- * that maintains position of erased items until `pack` is
- * called. It is used by DrawList, RectList, and
- * ScreenItemList. StablePointerArray takes ownership of
- * all pointers that are passed to it and deletes them when
- * calling `erase` or when destroying the
- * StablePointerArray.
+ * StablePointerArray holds pointers in a fixed-size array that maintains
+ * position of erased items until `pack` is called. It is used by DrawList,
+ * RectList, and ScreenItemList. StablePointerArray takes ownership of all
+ * pointers that are passed to it and deletes them when calling `erase` or when
+ * destroying the StablePointerArray.
*/
template<class T, uint N>
class StablePointerArray {
Commit: ac0a83a4249089ecfaf47ea4e9e2505057c2d844
https://github.com/scummvm/scummvm/commit/ac0a83a4249089ecfaf47ea4e9e2505057c2d844
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:56:24-05:00
Commit Message:
SCI32: Clean up GfxControls32
* Rewrap comments to 80 columns
* Clarify comments where possible
* Fix whitespace errors
Changed paths:
engines/sci/graphics/controls32.cpp
engines/sci/graphics/controls32.h
diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp
index 52a9dfa..82b99e6 100644
--- a/engines/sci/graphics/controls32.cpp
+++ b/engines/sci/graphics/controls32.cpp
@@ -43,8 +43,8 @@ GfxControls32::GfxControls32(SegManager *segMan, GfxCache *cache, GfxText32 *tex
_gfxText32(text),
_overwriteMode(false),
_nextCursorFlashTick(0),
- // SSCI used a memory handle for a ScrollWindow object
- // as ID. We use a simple numeric handle instead.
+ // SSCI used a memory handle for a ScrollWindow object as ID. We use a
+ // simple numeric handle instead.
_nextScrollWindowId(10000) {}
GfxControls32::~GfxControls32() {
@@ -137,27 +137,27 @@ reg_t GfxControls32::kernelEditText(const reg_t controlObject) {
ScreenItem *screenItem = new ScreenItem(plane->_object, celInfo, Common::Point(), ScaleInfo());
plane->_screenItemList.add(screenItem);
- // frameOut must be called after the screen item is
- // created, and before it is updated at the end of the
- // event loop, otherwise it has both created and updated
- // flags set which crashes the engine (it runs updates
- // before creations)
+ // frameOut must be called after the screen item is created, and before it
+ // is updated at the end of the event loop, otherwise it has both created
+ // and updated flags set which crashes the engine (updates are handled
+ // before creations, but the screen item is not in the correct state for an
+ // update)
g_sci->_gfxFrameout->frameOut(true);
EventManager *eventManager = g_sci->getEventManager();
bool clearTextOnInput = true;
bool textChanged = false;
for (;;) {
- // We peek here because the last event needs to be allowed to
- // dispatch a second time to the normal event handling system.
- // In the actual engine, the event is always consumed and then
- // the last event just gets posted back to the event manager for
- // reprocessing, but instead, we only remove the event from the
- // queue *after* we have determined it is not a defocusing event
+ // We peek here because the last event needs to be allowed to dispatch a
+ // second time to the normal event handling system. In SSCI, the event
+ // is always consumed and then the last event just gets posted back to
+ // the event manager for reprocessing, but instead, we only remove the
+ // event from the queue *after* we have determined it is not a
+ // defocusing event
const SciEvent event = eventManager->getSciEvent(kSciEventAny | kSciEventPeek);
bool focused = true;
- // Original engine did not have a QUIT event but we have to handle it
+ // SSCI did not have a QUIT event, but we do, so we have to handle it
if (event.type == kSciEventQuit) {
focused = false;
} else if (event.type == kSciEventMousePress && !editorPlaneRect.contains(event.mousePosSci)) {
@@ -179,18 +179,16 @@ reg_t GfxControls32::kernelEditText(const reg_t controlObject) {
break;
}
- // Consume the event now that we know it is not one of the
- // defocusing events above
+ // Consume the event now that we know it is not one of the defocusing
+ // events above
if (event.type != kSciEventNone)
eventManager->getSciEvent(kSciEventAny);
- // NOTE: In the original engine, the font and bitmap were
- // reset here on each iteration through the loop, but it
- // doesn't seem like this should be necessary since
- // control is not yielded back to the VM until input is
- // received, which means there is nothing that could modify
- // the GfxText32's state with a different font in the
- // meantime
+ // In SSCI, the font and bitmap were reset here on each iteration
+ // through the loop, but this is not necessary since control is not
+ // yielded back to the VM until input is received, which means there is
+ // nothing that could modify the GfxText32's state with a different font
+ // in the meantime
bool shouldDeleteChar = false;
bool shouldRedrawText = false;
@@ -223,8 +221,8 @@ reg_t GfxControls32::kernelEditText(const reg_t controlObject) {
case kSciKeyInsert:
clearTextOnInput = false;
- // Redrawing also changes the cursor rect to
- // reflect the new insertion mode
+ // Redrawing also changes the cursor rect to reflect the new
+ // insertion mode
shouldRedrawText = true;
_overwriteMode = !_overwriteMode;
break;
@@ -324,10 +322,9 @@ void GfxControls32::drawCursor(TextEditor &editor) {
const int16 scaledFontHeight = _gfxText32->scaleUpHeight(_gfxText32->_font->getHeight());
- // NOTE: The original code branched on borderColor here but
- // the two branches appeared to be identical, differing only
- // because the compiler decided to be differently clever
- // when optimising multiplication in each branch
+ // SSCI branched on borderColor here but the two branches appeared to be
+ // identical, differing only because the compiler decided to be
+ // differently clever when optimising multiplication in each branch
if (_overwriteMode) {
editor.cursorRect.top = editor.textRect.top;
editor.cursorRect.setHeight(scaledFontHeight);
@@ -465,9 +462,8 @@ reg_t ScrollWindow::add(const Common::String &text, const GuiResourceId fontId,
if (_entries.size() == _maxNumEntries) {
ScrollWindowEntry removedEntry = _entries.remove_at(0);
_text.erase(0, removedEntry.text.size());
- // `_firstVisibleChar` will be reset shortly if
- // `scrollTo` is true, so there is no reason to
- // update it
+ // `_firstVisibleChar` will be reset shortly if `scrollTo` is true, so
+ // there is no reason to update it
if (!scrollTo) {
_firstVisibleChar -= removedEntry.text.size();
}
@@ -476,17 +472,17 @@ reg_t ScrollWindow::add(const Common::String &text, const GuiResourceId fontId,
_entries.push_back(ScrollWindowEntry());
ScrollWindowEntry &entry = _entries.back();
- // NOTE: In SSCI the line ID was a memory handle for the
- // string of this line. We use a numeric ID instead.
+ // In SSCI, the line ID was a memory handle for the string of this line. We
+ // use a numeric ID instead.
entry.id = make_reg(0, _nextEntryId++);
if (_nextEntryId > _maxNumEntries) {
_nextEntryId = 1;
}
- // NOTE: In SSCI this was updated after _text was
- // updated, which meant there was an extra unnecessary
- // subtraction operation (subtracting `entry.text` size)
+ // In SSCI, this was updated after _text was updated, which meant there was
+ // an extra unnecessary subtraction operation (subtracting `entry.text`
+ // size)
if (scrollTo) {
_firstVisibleChar = _text.size();
}
@@ -517,9 +513,8 @@ void ScrollWindow::fillEntry(ScrollWindowEntry &entry, const Common::String &tex
// with properties -1 can inherit properties from the previously rendered
// line instead of the defaults.
- // NOTE: SSCI added "|s<lineIndex>|" here, but |s| is
- // not a valid control code, so it just always ended up
- // getting skipped
+ // SSCI added "|s<lineIndex>|" here, but |s| is not a valid control code, so
+ // it just always ended up getting skipped by the text rendering code
if (entry.fontId != -1) {
formattedText += Common::String::format("|f%d|", entry.fontId);
}
@@ -705,9 +700,8 @@ void ScrollWindow::pageDown() {
void ScrollWindow::computeLineIndices() {
_gfxText32.setFont(_fontId);
- // NOTE: Unlike SSCI, foreColor and alignment are not
- // set since these properties do not affect the width of
- // lines
+ // Unlike SSCI, foreColor and alignment are not set since these properties
+ // do not affect the width of lines
if (_gfxText32._font->getHeight() != _pointSize) {
error("Illegal font size font = %d pointSize = %d, should be %d.", _fontId, _gfxText32._font->getHeight(), _pointSize);
@@ -717,8 +711,8 @@ void ScrollWindow::computeLineIndices() {
_startsOfLines.clear();
- // NOTE: The original engine had a 1000-line limit; we
- // do not enforce any limit
+ // SSCI had a 1000-line limit; we do not enforce any limit since we use
+ // dynamic containers
for (uint charIndex = 0; charIndex < _text.size(); ) {
_startsOfLines.push_back(charIndex);
charIndex += _gfxText32.getTextCount(_text, charIndex, lineRect, false);
diff --git a/engines/sci/graphics/controls32.h b/engines/sci/graphics/controls32.h
index 680c70d..de292da 100644
--- a/engines/sci/graphics/controls32.h
+++ b/engines/sci/graphics/controls32.h
@@ -32,8 +32,8 @@ class GfxScreen;
class GfxText32;
enum MessageBoxStyle {
- kMessageBoxOK = 0x0,
- kMessageBoxYesNo = 0x4
+ kMessageBoxOK = 0x0,
+ kMessageBoxYesNo = 0x4
};
struct TextEditor {
@@ -89,14 +89,12 @@ struct TextEditor {
uint16 cursorCharPosition;
/**
- * Whether or not the cursor is currently drawn to the
- * screen.
+ * Whether or not the cursor is currently drawn to the screen.
*/
bool cursorIsDrawn;
/**
- * The rectangle for drawing the input cursor, in bitmap
- * pixels.
+ * The rectangle for drawing the input cursor, in bitmap pixels.
*/
Common::Rect cursorRect;
@@ -111,30 +109,26 @@ struct TextEditor {
*/
struct ScrollWindowEntry {
/**
- * ID of the line. In SSCI this was actually a memory
- * handle for the string of this line. We use a simple
- * numeric ID instead.
+ * ID of the line. In SSCI this was actually a memory handle for the string
+ * of this line. We use a simple numeric ID instead.
*/
reg_t id;
/**
- * The alignment to use when rendering this line of
- * text. If -1, the default alignment from the
- * corresponding ScrollWindow will be used.
+ * The alignment to use when rendering this line of text. If -1, the default
+ * alignment from the corresponding ScrollWindow will be used.
*/
TextAlign alignment;
/**
- * The color to use to render this line of text. If -1,
- * the default foreground color from the corresponding
- * ScrollWindow will be used.
+ * The color to use to render this line of text. If -1, the default
+ * foreground color from the corresponding ScrollWindow will be used.
*/
int16 foreColor;
/**
- * The font to use to render this line of text. If -1,
- * the default font from the corresponding ScrollWindow
- * will be used.
+ * The font to use to render this line of text. If -1, the default font from
+ * the corresponding ScrollWindow will be used.
*/
GuiResourceId fontId;
@@ -155,16 +149,15 @@ public:
~ScrollWindow();
/**
- * Adds a new text entry to the window. If `fontId`,
- * `foreColor`, or `alignment` are `-1`, the
- * ScrollWindow's default values will be used.
+ * Adds a new text entry to the window. If `fontId`, `foreColor`, or
+ * `alignment` are `-1`, the ScrollWindow's default values will be used.
*/
reg_t add(const Common::String &text, const GuiResourceId fontId, const int16 foreColor, const TextAlign alignment, const bool scrollTo);
/**
- * Modifies an existing text entry with the given ID. If
- * `fontId`, `foreColor`, or `alignment` are `-1`, the
- * ScrollWindow's default values will be used.
+ * Modifies an existing text entry with the given ID. If `fontId`,
+ * `foreColor`, or `alignment` are `-1`, the ScrollWindow's default values
+ * will be used.
*/
reg_t modify(const reg_t id, const Common::String &text, const GuiResourceId fontId, const int16 foreColor, const TextAlign alignment, const bool scrollTo);
@@ -179,9 +172,8 @@ public:
void hide();
/**
- * Gets the number of lines that the content of a
- * ScrollWindow is scrolled upward, as a ratio of the
- * total number of lines of content.
+ * Gets the number of lines that the content of a ScrollWindow is scrolled
+ * upward, as a ratio of the total number of lines of content.
*/
Ratio where() const;
@@ -221,8 +213,8 @@ public:
void pageDown();
/**
- * Gets a reference to the in-memory bitmap that
- * is used to render the text in the ScrollWindow.
+ * Gets a reference to the in-memory bitmap that is used to render the text
+ * in the ScrollWindow.
*/
const reg_t getBitmap() const { return _bitmap; }
@@ -232,31 +224,26 @@ private:
typedef Common::Array<ScrollWindowEntry> EntriesList;
/**
- * A convenience function that fills a
- * ScrollWindowEntry's properties.
+ * A convenience function that fills a ScrollWindowEntry's properties.
*/
void fillEntry(ScrollWindowEntry &entry, const Common::String &text, const GuiResourceId fontId, const int16 foreColor, const TextAlign alignment);
/**
- * Rescans the entire text of the ScrollWindow when an
- * entry is added or modified, calculating the character
- * offsets of all line endings, the total number of
- * lines of text, the height of the viewport (in lines
- * of text), the last character visible in the viewport
- * (assuming the viewport is scrolled to the top), and
- * the line index of the bottommost visible line
- * (assuming the viewport is scrolled to the top).
+ * Rescans the entire text of the ScrollWindow when an entry is added or
+ * modified, calculating the character offsets of all line endings, the
+ * total number of lines of text, the height of the viewport (in lines of
+ * text), the last character visible in the viewport (assuming the viewport
+ * is scrolled to the top), and the line index of the bottommost visible
+ * line (assuming the viewport is scrolled to the top).
*/
void computeLineIndices();
/**
- * Calculates which text is visible within the
- * ScrollWindow's viewport and renders the text to the
- * internal bitmap.
+ * Calculates which text is visible within the ScrollWindow's viewport and
+ * renders the text to the internal bitmap.
*
- * If `doFrameOut` is true, the screen will be refreshed
- * immediately instead of waiting for the next call to
- * `kFrameOut`.
+ * If `doFrameOut` is true, the screen will be refreshed immediately instead
+ * of waiting for the next call to `kFrameOut`.
*/
void update(const bool doFrameOut);
@@ -266,21 +253,18 @@ private:
GfxText32 _gfxText32;
/**
- * The individual text entries added to the
- * ScrollWindow.
+ * The individual text entries added to the ScrollWindow.
*/
EntriesList _entries;
/**
- * The maximum number of entries allowed. Once this
- * limit is reached, the oldest entry will be removed
- * when a new entry is added.
+ * The maximum number of entries allowed. Once this limit is reached, the
+ * oldest entry will be removed when a new entry is added.
*/
uint _maxNumEntries;
/**
- * A mapping from a line index to the line's character
- * offset in `_text`.
+ * A mapping from a line index to the line's character offset in `_text`.
*/
Common::Array<int> _startsOfLines;
@@ -300,39 +284,36 @@ private:
int _firstVisibleChar;
/**
- * The index of the line that is at the top of the
- * viewport.
+ * The index of the line that is at the top of the viewport.
*/
int _topVisibleLine;
/**
- * The index of the last visible character in `_text`,
- * or -1 if there is no text.
+ * The index of the last visible character in `_text`, or -1 if there is no
+ * text.
*/
int _lastVisibleChar;
/**
- * The index of the line that is at the bottom of the
- * viewport, or -1 if there is no text.
+ * The index of the line that is at the bottom of the viewport, or -1 if
+ * there is no text.
*/
int _bottomVisibleLine;
/**
- * The total number of lines in the backbuffer. This
- * number may be higher than the total number of entries
- * if an entry contains newlines.
+ * The total number of lines in the backbuffer. This number may be higher
+ * than the total number of entries if an entry contains newlines.
*/
int _numLines;
/**
- * The number of lines that are currently visible in the
- * text area of the window.
+ * The number of lines that are currently visible in the text area of the
+ * window.
*/
int _numVisibleLines;
/**
- * The plane in which the ScrollWindow should be
- * rendered.
+ * The plane in which the ScrollWindow should be rendered.
*/
reg_t _plane;
@@ -347,20 +328,18 @@ private:
uint8 _backColor;
/**
- * The default border color of the text bitmap. If -1,
- * the viewport will have no border.
+ * The default border color of the text bitmap. If -1, the viewport will
+ * have no border.
*/
int16 _borderColor;
/**
- * The default font used for rendering text into the
- * ScrollWindow.
+ * The default font used for rendering text into the ScrollWindow.
*/
GuiResourceId _fontId;
/**
- * The default text alignment used for rendering text
- * into the ScrollWindow.
+ * The default text alignment used for rendering text into the ScrollWindow.
*/
TextAlign _alignment;
@@ -370,22 +349,20 @@ private:
bool _visible;
/**
- * The dimensions of the text box inside the font
- * bitmap, in text-system coordinates.
+ * The dimensions of the text box inside the font bitmap, in text-system
+ * coordinates.
*/
Common::Rect _textRect;
/**
- * The top-left corner of the ScrollWindow's screen
- * item, in game script coordinates, relative to the
- * parent plane.
+ * The top-left corner of the ScrollWindow's screen item, in game script
+ * coordinates, relative to the parent plane.
*/
Common::Point _position;
/**
- * The height of the default font in screen pixels. All
- * fonts rendered into the ScrollWindow must have this
- * same height.
+ * The height of the default font in screen pixels. All fonts rendered into
+ * the ScrollWindow must have this same height.
*/
uint8 _pointSize;
@@ -395,8 +372,8 @@ private:
reg_t _bitmap;
/**
- * A monotonically increasing ID used to identify
- * text entries added to the ScrollWindow.
+ * A monotonically increasing ID used to identify text entries added to the
+ * ScrollWindow.
*/
uint16 _nextEntryId;
@@ -407,7 +384,8 @@ private:
};
/**
- * Controls class, handles drawing of controls in SCI32 (SCI2, SCI2.1, SCI3) games
+ * Controls class, handles drawing of UI controls in SCI32 games that use kernel
+ * controls instead of custom script controls.
*/
class GfxControls32 {
public:
@@ -426,14 +404,13 @@ public:
private:
/**
- * If true, typing will overwrite text that already
- * exists at the text cursor's current position.
+ * If true, typing will overwrite text that already exists at the text
+ * cursor's current position.
*/
bool _overwriteMode;
/**
- * The tick at which the text cursor should be toggled
- * by `flashCursor`.
+ * The tick at which the text cursor should be toggled by `flashCursor`.
*/
uint32 _nextCursorFlashTick;
@@ -448,8 +425,8 @@ private:
void eraseCursor(TextEditor &editor);
/**
- * Toggles the text cursor for the given editor to be
- * either drawn or erased.
+ * Toggles the text cursor for the given editor to be either drawn or
+ * erased.
*/
void flashCursor(TextEditor &editor);
@@ -457,9 +434,8 @@ private:
#pragma mark Scrollable window control
public:
/**
- * Creates a new scrollable window and returns the ID
- * for the new window, which is used by game scripts to
- * interact with scrollable windows.
+ * Creates a new scrollable window and returns the ID for the new window,
+ * which is used by game scripts to interact with scrollable windows.
*/
reg_t makeScrollWindow(const Common::Rect &gameRect, const Common::Point &position, const reg_t plane, const uint8 defaultForeColor, const uint8 defaultBackColor, const GuiResourceId defaultFontId, const TextAlign defaultAlignment, const int16 defaultBorderColor, const uint16 maxNumEntries);
@@ -477,8 +453,7 @@ private:
typedef Common::HashMap<uint16, ScrollWindow *> ScrollWindowMap;
/**
- * Monotonically increasing ID used to identify
- * ScrollWindow instances.
+ * Monotonically increasing ID used to identify ScrollWindow instances.
*/
uint16 _nextScrollWindowId;
@@ -497,8 +472,7 @@ public:
private:
/**
- * Convenience function for creating and showing a
- * message box.
+ * Convenience function for creating and showing a message box.
*/
int16 showMessageBox(const Common::String &message, const char *const okLabel, const char *const altLabel, const int16 okValue, const int16 altValue);
};
Commit: b6c3f0f547f478271a8ecee68654f18ab8de75ce
https://github.com/scummvm/scummvm/commit/b6c3f0f547f478271a8ecee68654f18ab8de75ce
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:56:24-05:00
Commit Message:
SCI32: Clean up CelObj
* Rewrap comments to 80 columns
* Clarify comments where possible
* Use smart pointers where appropriate
* Change view/pic flags detection to always use word-size
(byte-size check for flag 0x80 was a compiler optimisation)
Changed paths:
engines/sci/engine/segment.h
engines/sci/graphics/celobj32.cpp
engines/sci/graphics/celobj32.h
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index d6e2dd3..2a4fd91 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -1102,12 +1102,11 @@ public:
BITMAP_PROPERTY(32, DataOffset, 24);
- // NOTE: This property is used as a "magic number" for
- // validating that a block of memory is a valid bitmap,
- // and so is always set to the size of the header.
+ // This property is used as a "magic number" for validating that a block of
+ // memory is a valid bitmap, and so is always set to the size of the header.
BITMAP_PROPERTY(32, UncompressedDataOffset, 28);
- // NOTE: This property always seems to be zero
+ // This property always seems to be zero in SSCI
BITMAP_PROPERTY(32, ControlOffset, 32);
inline uint16 getXResolution() const {
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index a49690a..c2ae29b 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -35,7 +35,7 @@
namespace Sci {
#pragma mark CelScaler
-CelScaler *CelObj::_scaler = nullptr;
+Common::ScopedPtr<CelScaler> CelObj::_scaler;
void CelScaler::activateScaleTables(const Ratio &scaleX, const Ratio &scaleY) {
for (int i = 0; i < ARRAYSIZE(_scaleTables); ++i) {
@@ -74,9 +74,9 @@ void CelScaler::buildLookupTable(int *table, const Ratio &ratio, const int size)
}
}
-const CelScalerTable *CelScaler::getScalerTable(const Ratio &scaleX, const Ratio &scaleY) {
+const CelScalerTable &CelScaler::getScalerTable(const Ratio &scaleX, const Ratio &scaleY) {
activateScaleTables(scaleX, scaleY);
- return &_scaleTables[_activeIndex];
+ return _scaleTables[_activeIndex];
}
#pragma mark -
@@ -87,21 +87,13 @@ void CelObj::init() {
CelObj::deinit();
_drawBlackLines = false;
_nextCacheId = 1;
- _scaler = new CelScaler();
- _cache = new CelCache;
- _cache->resize(100);
+ _scaler.reset(new CelScaler());
+ _cache.reset(new CelCache(100));
}
void CelObj::deinit() {
- delete _scaler;
- _scaler = nullptr;
- if (_cache != nullptr) {
- for (CelCache::iterator it = _cache->begin(); it != _cache->end(); ++it) {
- delete it->celObj;
- }
- }
- delete _cache;
- _cache = nullptr;
+ _scaler.reset();
+ _cache.reset();
}
#pragma mark -
@@ -172,10 +164,9 @@ struct SCALER_Scale {
_minX(targetRect.left),
_maxX(targetRect.right - 1),
#endif
- // The maximum width of the scaled object may not be as
- // wide as the source data it requires if downscaling,
- // so just always make the reader decompress an entire
- // line of source data when scaling
+ // The maximum width of the scaled object may not be as wide as the source
+ // data it requires if downscaling, so just always make the reader
+ // decompress an entire line of source data when scaling
_reader(celObj, celObj._width) {
#ifndef NDEBUG
assert(_minX <= _maxX);
@@ -203,39 +194,39 @@ struct SCALER_Scale {
// games which use global scaling are the ones that use low-resolution
// script coordinates too.
- const CelScalerTable *table = CelObj::_scaler->getScalerTable(scaleX, scaleY);
+ const CelScalerTable &table = CelObj::_scaler->getScalerTable(scaleX, scaleY);
- if (g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth == kLowResX) {
+ if (g_sci->_gfxFrameout->getScriptWidth() == kLowResX) {
const int16 unscaledX = (scaledPosition.x / scaleX).toInt();
if (FLIP) {
const int lastIndex = celObj._width - 1;
for (int16 x = targetRect.left; x < targetRect.right; ++x) {
- _valuesX[x] = lastIndex - (table->valuesX[x] - unscaledX);
+ _valuesX[x] = lastIndex - (table.valuesX[x] - unscaledX);
}
} else {
for (int16 x = targetRect.left; x < targetRect.right; ++x) {
- _valuesX[x] = table->valuesX[x] - unscaledX;
+ _valuesX[x] = table.valuesX[x] - unscaledX;
}
}
const int16 unscaledY = (scaledPosition.y / scaleY).toInt();
for (int16 y = targetRect.top; y < targetRect.bottom; ++y) {
- _valuesY[y] = table->valuesY[y] - unscaledY;
+ _valuesY[y] = table.valuesY[y] - unscaledY;
}
} else {
if (FLIP) {
const int lastIndex = celObj._width - 1;
for (int16 x = targetRect.left; x < targetRect.right; ++x) {
- _valuesX[x] = lastIndex - table->valuesX[x - scaledPosition.x];
+ _valuesX[x] = lastIndex - table.valuesX[x - scaledPosition.x];
}
} else {
for (int16 x = targetRect.left; x < targetRect.right; ++x) {
- _valuesX[x] = table->valuesX[x - scaledPosition.x];
+ _valuesX[x] = table.valuesX[x - scaledPosition.x];
}
}
for (int16 y = targetRect.top; y < targetRect.bottom; ++y) {
- _valuesY[y] = table->valuesY[y - scaledPosition.y];
+ _valuesY[y] = table.valuesY[y - scaledPosition.y];
}
}
}
@@ -412,8 +403,8 @@ struct MAPPER_NoMDNoSkip {
struct MAPPER_Map {
inline void draw(byte *target, const byte pixel, const uint8 skipColor) const {
if (pixel != skipColor) {
- // NOTE: For some reason, SSCI never checks if the source
- // pixel is *above* the range of remaps.
+ // For some reason, SSCI never checks if the source pixel is *above*
+ // the range of remaps, so we do not either.
if (pixel < g_sci->_gfxRemap32->getStartColor()) {
*target = pixel;
} else if (g_sci->_gfxRemap32->remapEnabled(pixel)) {
@@ -429,8 +420,8 @@ struct MAPPER_Map {
*/
struct MAPPER_NoMap {
inline void draw(byte *target, const byte pixel, const uint8 skipColor) const {
- // NOTE: For some reason, SSCI never checks if the source
- // pixel is *above* the range of remaps.
+ // For some reason, SSCI never checks if the source pixel is *above* the
+ // range of remaps, so we do not either.
if (pixel != skipColor && pixel < g_sci->_gfxRemap32->getStartColor()) {
*target = pixel;
}
@@ -444,9 +435,9 @@ void CelObj::draw(Buffer &target, const ScreenItem &screenItem, const Common::Re
_drawBlackLines = screenItem._drawBlackLines;
if (_remap) {
- // NOTE: In the original code this check was `g_Remap_numActiveRemaps && _remap`,
- // but since we are already in a `_remap` branch, there is no reason to check it
- // again
+ // In SSCI, this check was `g_Remap_numActiveRemaps && _remap`, but
+ // since we are already in a `_remap` branch, there is no reason to
+ // check that again
if (g_sci->_gfxRemap32->getRemapCount()) {
if (scaleX.isOne() && scaleY.isOne()) {
if (_compressionType == kCelCompressionNone) {
@@ -612,7 +603,7 @@ void CelObj::submitPalette() const {
#pragma mark CelObj - Caching
int CelObj::_nextCacheId = 1;
-CelCache *CelObj::_cache = nullptr;
+Common::ScopedPtr<CelCache> CelObj::_cache;
int CelObj::searchCache(const CelInfo32 &celInfo, int *const nextInsertIndex) const {
*nextInsertIndex = -1;
@@ -648,12 +639,7 @@ void CelObj::putCopyInCache(const int cacheIndex) const {
}
CelCacheEntry &entry = (*_cache)[cacheIndex];
-
- if (entry.celObj != nullptr) {
- delete entry.celObj;
- }
-
- entry.celObj = duplicate();
+ entry.celObj.reset(duplicate());
entry.id = ++_nextCacheId;
}
@@ -807,8 +793,8 @@ void CelObj::drawUncompHzFlipNoMDNoSkip(Buffer &target, const Common::Rect &targ
}
void CelObj::scaleDrawNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- // In SSCI the checks are > because their rects are BR-inclusive;
- // our checks are >= because our rects are BR-exclusive
+ // In SSCI the checks are > because their rects are BR-inclusive; our checks
+ // are >= because our rects are BR-exclusive
if (g_sci->_features->hasEmptyScaleDrawHack() &&
(targetRect.left >= targetRect.right ||
targetRect.top >= targetRect.bottom)) {
@@ -822,8 +808,8 @@ void CelObj::scaleDrawNoMD(Buffer &target, const Ratio &scaleX, const Ratio &sca
}
void CelObj::scaleDrawUncompNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- // In SSCI the checks are > because their rects are BR-inclusive;
- // our checks are >= because our rects are BR-exclusive
+ // In SSCI the checks are > because their rects are BR-inclusive; our checks
+ // are >= because our rects are BR-exclusive
if (g_sci->_features->hasEmptyScaleDrawHack() &&
(targetRect.left >= targetRect.right ||
targetRect.top >= targetRect.bottom)) {
@@ -861,11 +847,11 @@ int16 CelObjView::getNumCels(const GuiResourceId viewId, int16 loopNo) {
const uint16 loopCount = data[2];
- // Every version of SCI32 has a logic error in this function that causes
- // random memory to be read if a script requests the cel count for one
- // past the maximum loop index. For example, GK1 room 808 does this, and
- // gets stuck in an infinite loop because the game script expects this
- // method to return a non-zero value.
+ // Every version of SSCI has a logic error in this function that causes
+ // random memory to be read if a script requests the cel count for one past
+ // the maximum loop index. For example, GK1 room 808 does this, and gets
+ // stuck in an infinite loop because the game script expects this method to
+ // return a non-zero value.
// This bug is triggered in basically every SCI32 game and appears to be
// universally fixable simply by always using the next lowest loop instead.
if (loopNo == loopCount) {
@@ -904,7 +890,7 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int
const int cacheIndex = searchCache(_info, &cacheInsertIndex);
if (cacheIndex != -1) {
CelCacheEntry &entry = (*_cache)[cacheIndex];
- const CelObjView *const cachedCelObj = dynamic_cast<CelObjView *>(entry.celObj);
+ const CelObjView *const cachedCelObj = dynamic_cast<CelObjView *>(entry.celObj.get());
if (cachedCelObj == nullptr) {
error("Expected a CelObjView in cache slot %d", cacheIndex);
}
@@ -915,7 +901,7 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int
const Resource *const resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, viewId), false);
- // NOTE: SCI2.1/SQ6 just silently returns here.
+ // SSCI just silently returns here
if (!resource) {
error("View resource %d not found", viewId);
}
@@ -944,8 +930,6 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int
_info.loopNo = loopCount - 1;
}
- // NOTE: This is the actual check, in the actual location,
- // from SCI engine.
if (loopNo < 0) {
error("Loop is less than 0");
}
@@ -1011,10 +995,8 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int
error("Compression type not supported - V: %d L: %d C: %d", _info.resourceId, _info.loopNo, _info.celNo);
}
- if (celHeader[10] & 128) {
- // NOTE: This is correct according to SCI2.1/SQ6/DOS;
- // the engine re-reads the byte value as a word value
- const uint16 flags = celHeader.getUint16SEAt(10);
+ const uint16 flags = celHeader.getUint16SEAt(10);
+ if (flags & 0x80) {
_transparent = flags & 1 ? true : false;
_remap = flags & 2 ? true : false;
} else if (_compressionType == kCelCompressionNone) {
@@ -1096,7 +1078,7 @@ Common::Point CelObjView::getLinkPosition(const int16 linkId) const {
Common::Point point;
point.x = linkTable.getInt16SEAt(0);
if (_mirrorX) {
- // NOTE: SSCI had an off-by-one error here (missing -1)
+ // SSCI had an off-by-one error here (missing -1)
point.x = _width - point.x - 1;
}
point.y = linkTable.getInt16SEAt(2);
@@ -1127,7 +1109,7 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) {
const int cacheIndex = searchCache(_info, &cacheInsertIndex);
if (cacheIndex != -1) {
CelCacheEntry &entry = (*_cache)[cacheIndex];
- const CelObjPic *const cachedCelObj = dynamic_cast<CelObjPic *>(entry.celObj);
+ const CelObjPic *const cachedCelObj = dynamic_cast<CelObjPic *>(entry.celObj.get());
if (cachedCelObj == nullptr) {
error("Expected a CelObjPic in cache slot %d", cacheIndex);
}
@@ -1138,7 +1120,7 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) {
const Resource *const resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypePic, picId), false);
- // NOTE: SCI2.1/SQ6 just silently returns here.
+ // SSCI just silently returns here
if (!resource) {
error("Pic resource %d not found", picId);
}
@@ -1183,10 +1165,9 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) {
_yResolution = 400;
}
- if (celHeader.getUint8At(10) & 128) {
- // NOTE: This is correct according to SCI2.1/SQ6/DOS;
- // the engine re-reads the byte value as a word value
- const uint16 flags = celHeader.getUint16SEAt(10);
+
+ const uint16 flags = celHeader.getUint16SEAt(10);
+ if (flags & 0x80) {
_transparent = flags & 1 ? true : false;
_remap = flags & 2 ? true : false;
} else {
@@ -1251,7 +1232,8 @@ CelObjMem::CelObjMem(const reg_t bitmapObject) {
SciBitmap *bitmap = g_sci->getEngineState()->_segMan->lookupBitmap(bitmapObject);
- // NOTE: SSCI did no error checking here at all.
+ // SSCI did no error checking here at all so would just end up reading
+ // garbage or crashing if this ever happened
if (!bitmap) {
error("Bitmap %04x:%04x not found", PRINT_REG(bitmapObject));
}
@@ -1293,8 +1275,8 @@ CelObjColor::CelObjColor(const uint8 color, const int16 width, const int16 heigh
}
void CelObjColor::draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect, const bool mirrorX) {
- // TODO: The original engine sets this flag but why? One cannot
- // draw a solid color mirrored.
+ // One cannot draw a solid color mirrored, but SSCI sets it anyway, so we do
+ // too
_drawMirrored = mirrorX;
draw(target, targetRect);
}
diff --git a/engines/sci/graphics/celobj32.h b/engines/sci/graphics/celobj32.h
index 6e50f72..02b2859 100644
--- a/engines/sci/graphics/celobj32.h
+++ b/engines/sci/graphics/celobj32.h
@@ -33,14 +33,14 @@ namespace Sci {
typedef Common::Rational Ratio;
// SCI32 has four different coordinate systems:
-// 1. low resolution, 2. game/script resolution,
-// 3. text/bitmap resolution, 4. screen resolution
+// 1. low resolution, 2. game/script resolution, 3. text/bitmap resolution,
+// 4. screen resolution
//
-// In CelObj, these values are used when there is
-// no baked in resolution of cels.
+// In CelObj, these values are used when there is no baked in resolution of
+// cels.
//
-// In ScreenItem, it is used when deciding which
-// path to take to calculate dimensions.
+// In ScreenItem, it is used when deciding which path to take to calculate
+// dimensions.
enum {
kLowResX = 320,
kLowResY = 200
@@ -60,8 +60,7 @@ enum CelCompressionType {
};
/**
- * A CelInfo32 object describes the basic properties of a
- * cel object.
+ * A CelInfo32 object describes the basic properties of a cel object.
*/
struct CelInfo32 {
/**
@@ -70,26 +69,24 @@ struct CelInfo32 {
CelType type;
/**
- * For cel objects that draw from resources, the ID of
- * the resource to load.
+ * For cel objects that draw from resources, the ID of the resource to load.
*/
GuiResourceId resourceId;
/**
- * For CelObjView, the loop number to draw from the
- * view resource.
+ * For CelObjView, the loop number to draw from the view resource.
*/
int16 loopNo;
/**
- * For CelObjView and CelObjPic, the cel number to draw
- * from the view or pic resource.
+ * For CelObjView and CelObjPic, the cel number to draw from the view or pic
+ * resource.
*/
int16 celNo;
/**
- * For CelObjMem, a segment register pointing to a heap
- * resource containing headered bitmap data.
+ * For CelObjMem, a segment register pointing to a heap resource containing
+ * headered bitmap data.
*/
reg_t bitmap;
@@ -98,18 +95,16 @@ struct CelInfo32 {
*/
uint8 color;
- // NOTE: In at least SCI2.1/SQ6, color is left
- // uninitialised.
CelInfo32() :
+ // In SSCI, color is left uninitialised
type(kCelTypeMem),
resourceId(0),
loopNo(0),
celNo(0),
bitmap(NULL_REG) {}
- // NOTE: This is the equivalence criteria used by
- // CelObj::searchCache in at least SCI2.1/SQ6. Notably,
- // it does not check the color field.
+ // This is the equivalence criteria used by CelObj::searchCache in at least
+ // SSCI SQ6. Notably, it does not check the color field.
inline bool operator==(const CelInfo32 &other) {
return (
type == other.type &&
@@ -143,13 +138,12 @@ struct CelInfo32 {
class CelObj;
struct CelCacheEntry {
/**
- * A monotonically increasing cache ID used to identify
- * the least recently used item in the cache for
- * replacement.
+ * A monotonically increasing cache ID used to identify the least recently
+ * used item in the cache for replacement.
*/
int id;
- CelObj *celObj;
- CelCacheEntry() : id(0), celObj(nullptr) {}
+ Common::ScopedPtr<CelObj> celObj;
+ CelCacheEntry() : id(0) {}
};
typedef Common::Array<CelCacheEntry> CelCache;
@@ -166,9 +160,9 @@ enum {
struct CelScalerTable {
/**
- * A lookup table of indexes that should be used to find
- * the correct column to read from the source bitmap
- * when drawing a scaled version of the source bitmap.
+ * A lookup table of indexes that should be used to find the correct column
+ * to read from the source bitmap when drawing a scaled version of the
+ * source bitmap.
*/
int valuesX[kCelScalerTableSize];
@@ -178,9 +172,9 @@ struct CelScalerTable {
Ratio scaleX;
/**
- * A lookup table of indexes that should be used to find
- * the correct row to read from a source bitmap when
- * drawing a scaled version of the source bitmap.
+ * A lookup table of indexes that should be used to find the correct row to
+ * read from a source bitmap when drawing a scaled version of the source
+ * bitmap.
*/
int valuesY[kCelScalerTableSize];
@@ -202,25 +196,23 @@ class CelScaler {
int _activeIndex;
/**
- * Activates a scale table for the given X and Y ratios.
- * If there is no table that matches the given ratios,
- * the least most recently used table will be replaced
- * and activated.
+ * Activates a scale table for the given X and Y ratios. If there is no
+ * table that matches the given ratios, the least most recently used table
+ * will be replaced and activated.
*/
void activateScaleTables(const Ratio &scaleX, const Ratio &scaleY);
/**
- * Builds a pixel lookup table in `table` for the given
- * ratio. The table will be filled up to the specified
- * size, which should be large enough to draw across the
- * entire target buffer.
+ * Builds a pixel lookup table in `table` for the given ratio. The table
+ * will be filled up to the specified size, which should be large enough to
+ * draw across the entire target buffer.
*/
void buildLookupTable(int *table, const Ratio &ratio, const int size);
public:
CelScaler() :
- _scaleTables(),
- _activeIndex(0) {
+ _scaleTables(),
+ _activeIndex(0) {
CelScalerTable &table = _scaleTables[0];
table.scaleX = Ratio();
table.scaleY = Ratio();
@@ -236,7 +228,7 @@ public:
/**
* Retrieves scaler tables for the given X and Y ratios.
*/
- const CelScalerTable *getScalerTable(const Ratio &scaleX, const Ratio &scaleY);
+ const CelScalerTable &getScalerTable(const Ratio &scaleX, const Ratio &scaleY);
};
#pragma mark -
@@ -244,53 +236,47 @@ public:
class ScreenItem;
/**
- * A cel object is the lowest-level rendering primitive in
- * the SCI engine and draws itself directly to a target
- * pixel buffer.
+ * A cel object is the lowest-level rendering primitive in the SCI engine and
+ * draws itself directly to a target pixel buffer.
*/
class CelObj {
protected:
/**
- * When true, every second line of the cel will be
- * rendered as a black line.
+ * When true, every second line of the cel will be rendered as a black line.
*
* @see ScreenItem::_drawBlackLines
- * @note Using a static member because otherwise this
- * would otherwise need to be copied down through
- * several calls. (SSCI did similar, using a global
- * variable.)
+ * @note Using a static member because otherwise this would otherwise need
+ * to be copied down through several calls. (SSCI did similar, using a
+ * global variable.)
*/
static bool _drawBlackLines;
/**
- * When true, this cel will be horizontally mirrored
- * when it is drawn. This is an internal flag that is
- * set by draw methods based on the combination of the
- * cel's `_mirrorX` property and the owner screen item's
- * `_mirrorX` property.
+ * When true, this cel will be horizontally mirrored when it is drawn. This
+ * is an internal flag that is set by draw methods based on the combination
+ * of the cel's `_mirrorX` property and the owner screen item's `_mirrorX`
+ * property.
*/
bool _drawMirrored;
public:
- static CelScaler *_scaler;
+ static Common::ScopedPtr<CelScaler> _scaler;
/**
- * The basic identifying information for this cel. This
- * information effectively acts as a composite key for
- * a cel object, and any cel object can be recreated
- * from this data alone.
+ * The basic identifying information for this cel. This information
+ * effectively acts as a composite key for a cel object, and any cel object
+ * can be recreated from this data alone.
*/
CelInfo32 _info;
/**
- * The offset to the cel header for this cel within the
- * raw resource data.
+ * The offset to the cel header for this cel within the raw resource data.
*/
uint32 _celHeaderOffset;
/**
- * The offset to the embedded palette for this cel
- * within the raw resource data.
+ * The offset to the embedded palette for this cel within the raw resource
+ * data.
*/
uint32 _hunkPaletteOffset;
@@ -300,36 +286,32 @@ public:
uint16 _width, _height;
/**
- * TODO: Documentation
+ * The origin of the cel, relative to the top-left corner, in cel
+ * coordinates.
*/
Common::Point _origin;
/**
- * The dimensions of the original coordinate system for
- * the cel. Used to scale cels from their native size
- * to the correct size on screen.
+ * The dimensions of the original coordinate system for the cel. Used to
+ * scale cels from their native size to the correct size on screen.
*
- * @note This is set to scriptWidth/Height for
- * CelObjColor. For other cel objects, the value comes
- * from the raw resource data. For text bitmaps, this is
- * the width/height of the coordinate system used to
- * generate the text, which also defaults to
- * scriptWidth/Height but seems to typically be changed
- * to more closely match the native screen resolution.
+ * @note This is set to scriptWidth/Height for CelObjColor. For other cel
+ * objects, the value comes from the raw resource data. For text bitmaps,
+ * this is the width/height of the coordinate system used to generate the
+ * text, which also defaults to scriptWidth/Height but seems to typically be
+ * changed to more closely match the native screen resolution.
*/
uint16 _xResolution, _yResolution;
/**
- * The skip (transparent) color for the cel. When
- * compositing, any pixels matching this color will not
- * be copied to the buffer.
+ * The skip (transparent) color for the cel. When compositing, any pixels
+ * matching this color will not be copied to the buffer.
*/
uint8 _skipColor;
/**
- * Whether or not this cel has any transparent regions.
- * This is used for optimised drawing of non-transparent
- * cels.
+ * Whether or not this cel has any transparent regions. This is used for
+ * optimised drawing of non-transparent cels.
*/
bool _transparent;
@@ -339,15 +321,14 @@ public:
CelCompressionType _compressionType;
/**
- * Whether or not this cel should be palette-remapped?
+ * Whether or not this cel contains remap pixels.
*/
bool _remap;
/**
- * If true, the cel contains pre-mirrored picture data.
- * This value comes directly from the resource data and
- * is XORed with the `_mirrorX` property of the owner
- * screen item when rendering.
+ * If true, the cel contains pre-mirrored picture data. This value comes
+ * directly from the resource data and is XORed with the `_mirrorX` property
+ * of the owner screen item when rendering.
*/
bool _mirrorX;
@@ -364,71 +345,63 @@ public:
virtual ~CelObj() {};
/**
- * Draws the cel to the target buffer using the priority
- * and positioning information from the given screen
- * item. The mirroring of the cel will be unchanged from
- * any previous call to draw.
+ * Draws the cel to the target buffer using the priority and positioning
+ * information from the given screen item. The mirroring of the cel will be
+ * unchanged from any previous call to draw.
*/
void draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect) const;
/**
- * Draws the cel to the target buffer using the priority
- * and positioning information from the given screen
- * item and the given mirror flag.
+ * Draws the cel to the target buffer using the priority and positioning
+ * information from the given screen item and the given mirror flag.
*
- * @note In SCI engine, this function was a virtual
- * function, but CelObjView, CelObjPic, and CelObjMem
- * all used the same function and the compiler
- * deduplicated the copies; we deduplicate the source by
- * putting the implementation on CelObj instead of
- * copying it to 3/4 of the subclasses.
+ * @note In SSCI, this function was a virtual function, but CelObjView,
+ * CelObjPic, and CelObjMem all used the same function and the compiler
+ * deduplicated the copies; we deduplicate the source by putting the
+ * implementation on CelObj instead of copying it to 3/4 of the subclasses.
*/
virtual void draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect, const bool mirrorX);
/**
- * Draws the cel to the target buffer using the
- * positioning and mirroring information from the
- * provided arguments.
+ * Draws the cel to the target buffer using the positioning and mirroring
+ * information from the provided arguments.
*
- * @note In SCI engine, this function was a virtual
- * function, but CelObjView, CelObjPic, and CelObjMem
- * all used the same function and the compiler
- * deduplicated the copies; we deduplicate the source by
- * putting the implementation on CelObj instead of
- * copying it to 3/4 of the subclasses.
+ * @note In SSCI, this function was a virtual function, but CelObjView,
+ * CelObjPic, and CelObjMem all used the same function and the compiler
+ * deduplicated the copies; we deduplicate the source by putting the
+ * implementation on CelObj instead of copying it to 3/4 of the subclasses.
*/
virtual void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const bool mirrorX);
/**
- * Draws the cel to the target buffer using the given
- * position and scaling parameters. The mirroring of the
- * cel will be unchanged from any previous call to draw.
+ * Draws the cel to the target buffer using the given position and scaling
+ * parameters. The mirroring of the cel will be unchanged from any previous
+ * call to draw.
*/
void drawTo(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const Ratio &scaleX, const Ratio &scaleY) const;
/**
- * Creates a copy of this cel on the free store and
- * returns a pointer to the new object. The new cel will
- * point to a shared copy of bitmap/resource data.
+ * Creates a copy of this cel on the free store and returns a pointer to the
+ * new object. The new cel will point to a shared copy of bitmap/resource
+ * data.
*/
virtual CelObj *duplicate() const = 0;
/**
- * Retrieves a pointer to the raw resource data for this
- * cel. This method cannot be used with a CelObjColor.
+ * Retrieves a pointer to the raw resource data for this cel. This method
+ * cannot be used with a CelObjColor.
*/
virtual const SciSpan<const byte> getResPointer() const = 0;
/**
- * Reads the pixel at the given coordinates. This method
- * is valid only for CelObjView and CelObjPic.
+ * Reads the pixel at the given coordinates. This method is valid only for
+ * CelObjView and CelObjPic.
*/
virtual uint8 readPixel(const uint16 x, const uint16 y, const bool mirrorX) const;
/**
- * Submits the palette from this cel to the palette
- * manager for integration into the master screen
- * palette.
+ * Submits the palette from this cel to the palette manager for integration
+ * into the master screen palette.
*/
void submitPalette() const;
@@ -454,7 +427,8 @@ private:
void drawUncompHzFlipMap(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
void scaleDrawMap(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
void scaleDrawUncompMap(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
- // NOTE: The original includes versions of the above functions with priority parameters, which were not actually used in SCI32
+ // SSCI includes versions of the above functions with priority parameters
+ // which are not actually used in SCI32
void drawHzFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
void drawNoFlipNoMD(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
@@ -464,37 +438,34 @@ private:
void drawUncompHzFlipNoMDNoSkip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
void scaleDrawNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
void scaleDrawUncompNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const;
- // NOTE: The original includes versions of the above functions with priority parameters, which were not actually used in SCI32
+ // SSCI includes versions of the above functions with priority parameters
+ // which are not actually used in SCI32
#pragma mark -
#pragma mark CelObj - Caching
protected:
/**
- * A monotonically increasing cache ID used to identify
- * the least recently used item in the cache for
- * replacement.
+ * A monotonically increasing cache ID used to identify the least recently
+ * used item in the cache for replacement.
*/
static int _nextCacheId;
/**
- * A cache of cel objects used to avoid reinitialisation
- * overhead for cels with the same CelInfo32.
+ * A cache of cel objects used to avoid reinitialisation overhead for cels
+ * with the same CelInfo32.
*/
- // NOTE: At least SQ6 uses a fixed cache size of 100.
- static CelCache *_cache;
+ static Common::ScopedPtr<CelCache> _cache;
/**
- * Searches the cel cache for a CelObj matching the
- * provided CelInfo32. If not found, -1 is returned.
- * nextInsertIndex will receive the index of the oldest
- * item in the cache, which can be used to replace
- * the oldest item with a newer item.
+ * Searches the cel cache for a CelObj matching the provided CelInfo32. If
+ * not found, -1 is returned. `nextInsertIndex` will receive the index of
+ * the oldest item in the cache, which can be used to replace the oldest
+ * item with a newer item.
*/
int searchCache(const CelInfo32 &celInfo, int *nextInsertIndex) const;
/**
- * Puts a copy of this CelObj into the cache at the
- * given cache index.
+ * Puts a copy of this CelObj into the cache at the given cache index.
*/
void putCopyInCache(int index) const;
};
@@ -503,22 +474,20 @@ protected:
#pragma mark CelObjView
/**
- * A CelObjView is the drawing primitive for a View type
- * resource. Each CelObjView corresponds to a single cel
- * within a single loop of a view.
+ * A CelObjView is the drawing primitive for a View type resource. Each
+ * CelObjView corresponds to a single cel within a single loop of a view.
*/
class CelObjView : public CelObj {
private:
/**
- * Analyses resources without baked-in remap flags
- * to determine whether or not they should be remapped.
+ * Analyses resources without baked-in remap flags to determine whether or
+ * not they should be remapped.
*/
bool analyzeUncompressedForRemap() const;
/**
- * Analyses compressed resources without baked-in remap
- * flags to determine whether or not they should be
- * remapped.
+ * Analyses compressed resources without baked-in remap flags to determine
+ * whether or not they should be remapped.
*/
bool analyzeForRemap() const;
@@ -532,9 +501,8 @@ public:
static int16 getNumCels(const GuiResourceId viewId, const int16 loopNo);
/**
- * Draws the cel to the target buffer using the
- * positioning, mirroring, and scaling information from
- * the provided arguments.
+ * Draws the cel to the target buffer using the positioning, mirroring, and
+ * scaling information from the provided arguments.
*/
void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, bool mirrorX, const Ratio &scaleX, const Ratio &scaleY);
@@ -548,16 +516,14 @@ public:
#pragma mark CelObjPic
/**
- * A CelObjPic is the drawing primitive for a Picture type
- * resource. Each CelObjPic corresponds to a single cel
- * within a picture.
+ * A CelObjPic is the drawing primitive for a Picture type resource. Each
+ * CelObjPic corresponds to a single cel within a picture.
*/
class CelObjPic : public CelObj {
private:
/**
- * Analyses uncompressed resources without baked-in skip
- * flags to determine whether or not they can use fast
- * blitting.
+ * Analyses uncompressed resources without baked-in skip flags to determine
+ * whether or not they can use fast blitting.
*/
bool analyzeUncompressedForSkip() const;
@@ -568,14 +534,13 @@ public:
uint8 _celCount;
/**
- * The position of this cel relative to the top-left
- * corner of the picture.
+ * The position of this cel relative to the top-left corner of the picture.
*/
Common::Point _relativePosition;
/**
- * The z-buffer priority for this cel. Higher prorities
- * are drawn on top of lower priorities.
+ * The z-buffer priority for this cel. Higher prorities are drawn on top of
+ * lower priorities.
*/
int16 _priority;
@@ -593,10 +558,9 @@ public:
#pragma mark CelObjMem
/**
- * A CelObjMem is the drawing primitive for arbitrary
- * bitmaps generated in memory. Generated bitmaps in SCI32
- * include text & vector drawings and per-pixel screen
- * transitions like dissolves.
+ * A CelObjMem is the drawing primitive for arbitrary bitmaps generated in
+ * memory. Generated bitmaps in SCI32 include text & vector drawings and
+ * per-pixel screen transitions like dissolves.
*/
class CelObjMem : public CelObj {
public:
Commit: ce13b1699aa95743573b07064ee27457d0b52968
https://github.com/scummvm/scummvm/commit/ce13b1699aa95743573b07064ee27457d0b52968
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:56:25-05:00
Commit Message:
SCI32: Clean up Robot decoder
* Rewrap comments to 80 columns
* Clarify comments where possible
* Remove resolved TODOs
Changed paths:
engines/sci/video/robot_decoder.cpp
engines/sci/video/robot_decoder.h
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp
index 79079ed..49ca226 100644
--- a/engines/sci/video/robot_decoder.cpp
+++ b/engines/sci/video/robot_decoder.cpp
@@ -112,8 +112,8 @@ bool RobotAudioStream::addPacket(const RobotAudioPacket &packet) {
// 4 (odd).
const int8 bufferIndex = packet.position % 4 ? 1 : 0;
- // Packet 0 is the first primer, packet 2 is the second primer,
- // packet 4+ are regular audio data
+ // Packet 0 is the first primer, packet 2 is the second primer, packet 4+
+ // are regular audio data
if (packet.position <= 2 && _firstPacketPosition == -1) {
_readHead = 0;
_readHeadAbs = 0;
@@ -445,8 +445,8 @@ void RobotDecoder::initVideo(const int16 x, const int16 y, const int16 scale, co
_maxFrameRate = _frameRate + kMaxFrameRateDrift;
if (_xResolution == 0 || _yResolution == 0) {
- // TODO: Default values were taken from RESOURCE.CFG hires property
- // if it exists, so need to check games' configuration files for those
+ // In SSCI, default values were taken from RESOURCE.CFG hires property
+ // if it exists, but no games seem to take advantage of this
_xResolution = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
_yResolution = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
}
@@ -1386,12 +1386,8 @@ void RobotDecoder::doVersion5(const bool shouldSubmitAudio) {
for (RobotScreenItemList::size_type i = 0; i < screenItemCount; ++i) {
Common::Point position(_screenItemX[i], _screenItemY[i]);
-// TODO: Version 6 robot?
-// int scaleXRemainder;
if (_scaleInfo.signal == kScaleSignalManual) {
position.x = (position.x * _scaleInfo.x) / 128;
-// TODO: Version 6 robot?
-// scaleXRemainder = (position.x * _scaleInfo.x) % 128;
position.y = (position.y * _scaleInfo.y) / 128;
}
@@ -1400,8 +1396,6 @@ void RobotDecoder::doVersion5(const bool shouldSubmitAudio) {
celInfo.bitmap = _celHandles[i].bitmapId;
ScreenItem *screenItem = new ScreenItem(_planeId, celInfo, position, _scaleInfo);
_screenItemList[i] = screenItem;
- // TODO: Version 6 robot?
- // screenItem->_field_30 = scaleXRemainder;
if (_priority == -1) {
screenItem->_fixedPriority = false;
@@ -1414,8 +1408,6 @@ void RobotDecoder::doVersion5(const bool shouldSubmitAudio) {
ScreenItem *screenItem = _screenItemList[i];
screenItem->_celInfo.bitmap = _celHandles[i].bitmapId;
screenItem->_position = position;
- // TODO: Version 6 robot?
- // screenItem->_field_30 = scaleXRemainder;
if (_priority == -1) {
screenItem->_fixedPriority = false;
@@ -1570,7 +1562,7 @@ void RobotDecoder::preallocateCelMemory(const byte *rawVideoData, const int16 nu
for (int i = 0; i < numFixedCels; ++i) {
CelHandleInfo &celHandle = _celHandles[i];
- // NOTE: There was a check to see if the cel handle was not allocated
+ // In SSCI, there was a check to see if the cel handle was not allocated
// here, for some reason, which would mean that nothing was ever
// allocated from fixed cels, because the _celHandles array just got
// deleted and recreated...
diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h
index aa1d9da..314628e 100644
--- a/engines/sci/video/robot_decoder.h
+++ b/engines/sci/video/robot_decoder.h
@@ -52,7 +52,10 @@ class SegManager;
// Unlike traditional AV formats, Robot videos almost always require playback
// within the game engine because certain information (like the resolution of
// the Robot coordinates and the background for the video) is dependent on data
-// that does not exist within the Robot file itself.
+// that does not exist within the Robot file itself. In version 6, robots could
+// also participate in palette remapping by drawing remap pixels, and the
+// information for processing these pixels is also not stored within the Robot
+// file.
//
// The Robot container consists of a file header, an optional primer audio
// section, an optional colour palette, a frame seek index, a set of cuepoints,
@@ -66,9 +69,9 @@ class SegManager;
// contiguous data blocks, each of which can be independently compressed with
// LZS or left uncompressed. An entire cel can also be line decimated, where
// lines are deleted from the source bitmap at compression time and are
-// reconstructed by decompression using line doubling. Each cel also includes
-// coordinates where it should be placed within the video frame, relative to the
-// top-left corner of the frame.
+// reconstructed by decompression using line interpolation. Each cel also
+// includes coordinates where it should be placed within the video frame,
+// relative to the top-left corner of the frame.
//
// Audio coding is fixed-length, and all audio blocks except for the primer
// audio are the same size. Audio is encoded with Sierra SOL DPCM16 compression,
@@ -254,8 +257,8 @@ class SegManager;
#pragma mark RobotAudioStream
/**
- * A Robot audio stream is a simple loop buffer
- * that accepts audio blocks from the Robot engine.
+ * A Robot audio stream is a simple loop buffer that accepts audio blocks from
+ * the Robot engine.
*/
class RobotAudioStream : public Audio::AudioStream {
public:
@@ -266,40 +269,34 @@ public:
kRobotSampleRate = 22050,
/**
- * Multiplier for the size of a packet that
- * is being expanded by writing to every other
- * byte of the target buffer.
+ * Multiplier for the size of a packet that is being expanded by writing
+ * to every other byte of the target buffer.
*/
kEOSExpansion = 2
};
/**
- * Playback state information. Used for framerate
- * calculation.
+ * Playback state information. Used for framerate calculation.
*/
struct StreamState {
/**
- * The current position of the read head of
- * the audio stream.
+ * The current position of the read head of the audio stream.
*/
int bytesPlaying;
/**
- * The sample rate of the audio stream.
- * Always 22050.
+ * The sample rate of the audio stream. Always 22050.
*/
uint16 rate;
/**
- * The bit depth of the audio stream.
- * Always 16.
+ * The bit depth of the audio stream. Always 16.
*/
uint8 bits;
};
/**
- * A single packet of compressed audio from a
- * Robot data stream.
+ * A single packet of compressed audio from a Robot data stream.
*/
struct RobotAudioPacket {
/**
@@ -314,8 +311,7 @@ public:
int dataSize;
/**
- * The uncompressed, file-relative position
- * of this audio packet.
+ * The uncompressed, file-relative position of this audio packet.
*/
int position;
@@ -328,20 +324,19 @@ public:
/**
* Adds a new audio packet to the stream.
- * @returns `true` if the audio packet was fully
- * consumed, otherwise `false`.
+ * @returns `true` if the audio packet was fully consumed, otherwise
+ * `false`.
*/
bool addPacket(const RobotAudioPacket &packet);
/**
- * Prevents any additional audio packets from
- * being added to the audio stream.
+ * Prevents any additional audio packets from being added to the audio
+ * stream.
*/
void finish();
/**
- * Returns the current status of the audio
- * stream.
+ * Returns the current status of the audio stream.
*/
StreamState getStatus() const;
@@ -349,8 +344,7 @@ private:
Common::Mutex _mutex;
/**
- * Loop buffer for playback. Contains decompressed
- * 16-bit PCM samples.
+ * Loop buffer for playback. Contains decompressed 16-bit PCM samples.
*/
byte *_loopBuffer;
@@ -360,66 +354,57 @@ private:
int32 _loopBufferSize;
/**
- * The position of the read head within the loop
- * buffer, in bytes.
+ * The position of the read head within the loop buffer, in bytes.
*/
int32 _readHead;
/**
- * The lowest file position that can be buffered,
- * in uncompressed bytes.
+ * The lowest file position that can be buffered, in uncompressed bytes.
*/
int32 _readHeadAbs;
/**
- * The highest file position that can be buffered,
- * in uncompressed bytes.
+ * The highest file position that can be buffered, in uncompressed bytes.
*/
int32 _maxWriteAbs;
/**
- * The highest file position, in uncompressed bytes,
- * that has been written to the stream.
- * Different from `_maxWriteAbs`, which is the highest
- * uncompressed position which *can* be written right
- * now.
+ * The highest file position, in uncompressed bytes, that has been written
+ * to the stream. This is different from `_maxWriteAbs`, which is the
+ * highest uncompressed position which *can* be written right now.
*/
int32 _writeHeadAbs;
/**
- * The highest file position, in uncompressed bytes,
- * that has been written to the even & odd sides of
- * the stream.
+ * The highest file position, in uncompressed bytes, that has been written
+ * to the even & odd sides of the stream.
*
- * Index 0 corresponds to the 'even' side; index
- * 1 correspond to the 'odd' side.
+ * Index 0 corresponds to the 'even' side; index 1 corresponds to the 'odd'
+ * side.
*/
int32 _jointMin[2];
/**
- * When `true`, the stream is waiting for all primer
- * blocks to be received before allowing playback to
- * begin.
+ * When `true`, the stream is waiting for all primer blocks to be received
+ * before allowing playback to begin.
*/
bool _waiting;
/**
- * When `true`, the stream will accept no more audio
- * blocks.
+ * When `true`, the stream will accept no more audio blocks.
*/
bool _finished;
/**
- * The uncompressed position of the first packet of
- * robot data. Used to decide whether all primer
- * blocks have been received and the stream should
+ * The uncompressed position of the first packet of robot data. Used to
+ * decide whether all primer blocks have been received and the stream should
* be started.
*/
int32 _firstPacketPosition;
/**
- * Decompression buffer, used to temporarily store
- * an uncompressed block of audio data.
+ * Decompression buffer, used to temporarily store an uncompressed block of
+ * audio data.
*/
byte *_decompressionBuffer;
@@ -429,23 +414,20 @@ private:
int32 _decompressionBufferSize;
/**
- * The position of the packet currently in the
- * decompression buffer. Used to avoid
- * re-decompressing audio data that has already
- * been decompressed during a partial packet read.
+ * The position of the packet currently in the decompression buffer. Used to
+ * avoid re-decompressing audio data that has already been decompressed
+ * during a partial packet read.
*/
int32 _decompressionBufferPosition;
/**
- * Calculates the absolute ranges for new fills
- * into the loop buffer.
+ * Calculates the absolute ranges for new fills into the loop buffer.
*/
void fillRobotBuffer(const RobotAudioPacket &packet, const int8 bufferIndex);
/**
- * Interpolates `numSamples` samples from the read
- * head, if no true samples were written for one
- * (or both) of the joint channels.
+ * Interpolates `numSamples` samples from the read head, if no true samples
+ * were written for one (or both) of the joint channels.
*/
void interpolateMissingSamples(const int32 numSamples);
@@ -501,9 +483,8 @@ public:
};
enum {
- // Special high value used to represent
- // parameters that should be left unchanged
- // when calling `showFrame`
+ // Special high value used to represent parameters that should be left
+ // unchanged when calling `showFrame`
kUnspecified = 50000
};
@@ -530,8 +511,8 @@ private:
kCueListSize = 256,
/**
- * Maximum number of 'fixed' cels that never
- * change for the duration of a robot.
+ * Maximum number of 'fixed' cels that never change for the duration of
+ * a robot.
*/
kFixedCelListSize = 4,
@@ -541,27 +522,22 @@ private:
kRawPaletteSize = 1200,
/**
- * The size of a frame of Robot data. This
- * value was used to align the first block of
- * data after the main Robot header to the next
- * CD sector.
+ * The size of a frame of Robot data. This value was used to align the
+ * first block of data after the main Robot header to the next CD
+ * sector.
*/
kRobotFrameSize = 2048,
/**
- * The size of a block of zero-compressed
- * audio. Used to fill audio when the size of
- * an audio packet does not match the expected
- * packet size.
+ * The size of a block of zero-compressed audio. Used to fill audio when
+ * the size of an audio packet does not match the expected packet size.
*/
kRobotZeroCompressSize = 2048,
/**
- * The size of the audio block header, in bytes.
- * The audio block header consists of the
- * compressed size of the audio in the record,
- * plus the position of the audio in the
- * compressed data stream.
+ * The size of the audio block header, in bytes. The audio block header
+ * consists of the compressed size of the audio in the record, plus the
+ * position of the audio in the compressed data stream.
*/
kAudioBlockHeaderSize = 8,
@@ -571,23 +547,20 @@ private:
kCelHeaderSize = 22,
/**
- * The maximum amount that the frame rate is
- * allowed to drift from the nominal frame rate
- * in order to correct for AV drift or slow
- * playback.
+ * The maximum amount that the frame rate is allowed to drift from the
+ * nominal frame rate in order to correct for AV drift or slow playback.
*/
kMaxFrameRateDrift = 1
};
/**
- * The version number for the currently loaded
- * robot.
+ * The version number for the currently loaded robot.
*
* There are several known versions of robot:
*
* v2: before Nov 1994; no known examples
* v3: before Nov 1994; no known examples
- * v4: Jan 1995; PQ:SWAT demo
+ * v4: Jan 1995; KQ7 1.65, PQ:SWAT demo
* v5: Mar 1995; SCI2.1 and SCI3 games
* v6: SCI3 games
*/
@@ -625,8 +598,8 @@ private:
#pragma mark Playback
public:
/**
- * Opens a robot file for playback.
- * Newly opened robots are paused by default.
+ * Opens a robot file for playback. Newly opened robots are paused by
+ * default.
*/
void open(const GuiResourceId robotId, const reg_t plane, const int16 priority, const int16 x, const int16 y, const int16 scale);
@@ -636,8 +609,8 @@ public:
void close();
/**
- * Pauses the robot. Once paused, the audio for a robot
- * is disabled until the end of playback.
+ * Pauses the robot. Once paused, the audio for a robot is disabled until
+ * the end of playback.
*/
void pause();
@@ -654,8 +627,7 @@ public:
void showFrame(const uint16 frameNo, const uint16 newX, const uint16 newY, const uint16 newPriority);
/**
- * Retrieves the value associated with the
- * current cue point.
+ * Retrieves the value associated with the current cue point.
*/
int16 getCue() const;
@@ -688,27 +660,23 @@ private:
PositionList _recordPositions;
/**
- * The offset of the Robot file within a
- * resource bundle.
+ * The offset of the Robot file within a resource bundle.
*/
int32 _fileOffset;
/**
- * A list of cue times that is updated to
- * prevent earlier cue values from being
- * given to the game more than once.
+ * A list of cue times that is updated to prevent earlier cue values from
+ * being given to the game more than once.
*/
mutable int32 _cueTimes[kCueListSize];
/**
- * The original list of cue times from the
- * raw Robot data.
+ * The original list of cue times from the raw Robot data.
*/
int32 _masterCueTimes[kCueListSize];
/**
- * The list of values to provide to a game
- * when a cue value is requested.
+ * The list of values to provide to a game when a cue value is requested.
*/
int32 _cueValues[kCueListSize];
@@ -723,23 +691,20 @@ private:
int16 _normalFrameRate;
/**
- * The minimal playback frame rate. Used to
- * correct for AV sync drift when the video
- * is more than one frame ahead of the audio.
+ * The minimal playback frame rate. Used to correct for AV sync drift when
+ * the video is more than one frame ahead of the audio.
*/
int16 _minFrameRate;
/**
- * The maximum playback frame rate. Used to
- * correct for AV sync drift when the video
- * is more than one frame behind the audio.
+ * The maximum playback frame rate. Used to correct for AV sync drift when
+ * the video is more than one frame behind the audio.
*/
int16 _maxFrameRate;
/**
- * The maximum number of record blocks that
- * can be skipped without causing audio to
- * drop out.
+ * The maximum number of record blocks that can be skipped without causing
+ * audio to drop out.
*/
int16 _maxSkippablePackets;
@@ -754,32 +719,28 @@ private:
int _previousFrameNo;
/**
- * The time, in ticks, when the robot was
- * last started or resumed.
+ * The time, in ticks, when the robot was last started or resumed.
*/
int32 _startTime;
/**
- * The first frame displayed when the
- * robot was resumed.
+ * The first frame displayed when the robot was resumed.
*/
int32 _startFrameNo;
/**
- * The last frame displayed when the robot
- * was resumed.
+ * The last frame displayed when the robot was resumed.
*/
int32 _startingFrameNo;
/**
- * Seeks the raw data stream to the record for
- * the given frame number.
+ * Seeks the raw data stream to the record for the given frame number.
*/
bool seekToFrame(const int frameNo);
/**
- * Sets the start time and frame of the robot
- * when the robot is started or resumed.
+ * Sets the start time and frame of the robot when the robot is started or
+ * resumed.
*/
void setRobotTime(const int frameNo);
@@ -787,11 +748,10 @@ private:
#pragma mark Timing
private:
/**
- * This class tracks the amount of time it takes for
- * a frame of robot animation to be rendered. This
- * information is used by the player to speculatively
- * skip rendering of future frames to keep the
- * animation in sync with the robot audio.
+ * This class tracks the amount of time it takes for a frame of robot
+ * animation to be rendered. This information is used by the player to
+ * speculatively skip rendering of future frames to keep the animation in
+ * sync with the robot audio.
*/
class DelayTime {
public:
@@ -808,14 +768,13 @@ private:
void endTiming();
/**
- * Returns whether or not timing is currently in
- * progress.
+ * Returns whether or not timing is currently in progress.
*/
bool timingInProgress() const;
/**
- * Returns the median time, in ticks, of the
- * currently stored timing samples.
+ * Returns the median time, in ticks, of the currently stored timing
+ * samples.
*/
int predictedTicks() const;
@@ -823,24 +782,23 @@ private:
RobotDecoder *_decoder;
/**
- * The start time, in ticks, of the current timing
- * loop. If no loop is in progress, the value is 0.
+ * The start time, in ticks, of the current timing loop. If no loop is
+ * in progress, the value is 0.
*
- * @note This is slightly different than SSCI where
- * the not-timing value was -1.
+ * @note This is slightly different than SSCI where the not-timing value
+ * was -1.
*/
uint32 _startTime;
/**
- * A sorted list containing the timing data for
- * the last `kDelayListSize` frames, in ticks.
+ * A sorted list containing the timing data for the last
+ * `kDelayListSize` frames, in ticks.
*/
int _delays[kDelayListSize];
/**
- * A list of monotonically increasing identifiers
- * used to identify and replace the oldest sample
- * in the `_delays` array when finishing the
+ * A list of monotonically increasing identifiers used to identify and
+ * replace the oldest sample in the `_delays` array when finishing the
* next timing operation.
*/
uint _timestamps[kDelayListSize];
@@ -862,17 +820,14 @@ private:
};
/**
- * Calculates the next frame number that needs
- * to be rendered, using the timing data
- * collected by DelayTime.
+ * Calculates the next frame number that needs to be rendered, using the
+ * timing data collected by DelayTime.
*/
uint16 calculateNextFrameNo(const uint32 extraTicks = 0) const;
/**
- * Calculates and returns the number of frames
- * that should be rendered in `ticks` time,
- * according to the current target frame rate
- * of the robot.
+ * Calculates and returns the number of frames that should be rendered in
+ * `ticks` time, according to the current target frame rate of the robot.
*/
uint32 ticksToFrames(const uint32 ticks) const;
@@ -891,15 +846,13 @@ private:
private:
enum {
/**
- * The number of ticks that should elapse
- * between each AV sync check.
+ * The number of ticks that should elapse between each AV sync check.
*/
kAudioSyncCheckInterval = 5 * 60 /* 5 seconds */
};
/**
- * The status of the audio track of a Robot
- * animation.
+ * The status of the audio track of a Robot animation.
*/
enum RobotAudioStatus {
kRobotAudioReady = 1,
@@ -913,8 +866,7 @@ private:
#pragma mark Audio - AudioList
private:
/**
- * This class manages packetized audio playback
- * for robots.
+ * This class manages packetized audio playback for robots.
*/
class AudioList {
public:
@@ -926,8 +878,8 @@ private:
void startAudioNow();
/**
- * Stops playback of robot audio, allowing
- * any queued audio to finish playing back.
+ * Stops playback of robot audio, allowing any queued audio to finish
+ * playing back.
*/
void stopAudio();
@@ -937,40 +889,36 @@ private:
void stopAudioNow();
/**
- * Submits as many blocks of audio as possible
- * to the audio engine.
+ * Submits as many blocks of audio as possible to the audio engine.
*/
void submitDriverMax();
/**
* Adds a new AudioBlock to the queue.
*
- * @param position The absolute position of the
- * audio for the block, in compressed bytes.
+ * @param position The absolute position of the audio for the block, in
+ * compressed bytes.
* @param size The size of the buffer.
- * @param buffer A pointer to compressed audio
- * data that will be copied into the new
- * AudioBlock.
+ * @param buffer A pointer to compressed audio data that will be copied
+ * into the new AudioBlock.
*/
void addBlock(const int position, const int size, const byte *buffer);
/**
- * Immediately stops any active playback and
- * purges all audio data in the audio list.
+ * Immediately stops any active playback and purges all audio data in
+ * the audio list.
*/
void reset();
/**
- * Pauses the robot audio channel in
- * preparation for the first block of audio
- * data to be read.
+ * Pauses the robot audio channel in preparation for the first block of
+ * audio data to be read.
*/
void prepareForPrimer();
/**
- * Sets the audio offset which is used to
- * offset the position of audio packets
- * sent to the audio stream.
+ * Sets the audio offset which is used to offset the position of audio
+ * packets sent to the audio stream.
*/
void setAudioOffset(const int offset);
@@ -979,8 +927,7 @@ private:
private:
/**
- * AudioBlock represents a block of audio
- * from the Robot's audio track.
+ * AudioBlock represents a block of audio from the Robot's audio track.
*/
class AudioBlock {
public:
@@ -988,44 +935,37 @@ private:
~AudioBlock();
/**
- * Submits the block of audio to the
- * audio manager.
- * @returns true if the block was fully
- * read, or false if the block was not
- * read or only partially read.
+ * Submits the block of audio to the audio manager.
+ * @returns true if the block was fully read, or false if the block
+ * was not read or only partially read.
*/
bool submit(const int startOffset);
private:
/**
- * The absolute position, in compressed
- * bytes, of this audio block's audio
- * data in the audio stream.
+ * The absolute position, in compressed bytes, of this audio block's
+ * audio data in the audio stream.
*/
int _position;
/**
- * The compressed size, in bytes, of
- * this audio block's audio data.
+ * The compressed size, in bytes, of this audio block's audio data.
*/
int _size;
/**
- * A buffer containing raw
- * SOL-compressed audio data.
+ * A buffer containing raw SOL-compressed audio data.
*/
byte *_data;
};
/**
- * The list of compressed audio blocks
- * submitted for playback.
+ * The list of compressed audio blocks submitted for playback.
*/
AudioBlock *_blocks[kAudioListSize];
/**
- * The number of blocks in `_blocks` that are
- * ready to be submitted.
+ * The number of blocks in `_blocks` that are ready to be submitted.
*/
uint8 _blocksSize;
@@ -1040,8 +980,7 @@ private:
uint8 _newestBlockIndex;
/**
- * The offset used when sending packets to the
- * audio stream.
+ * The offset used when sending packets to the audio stream.
*/
int _startOffset;
@@ -1068,46 +1007,42 @@ private:
AudioList _audioList;
/**
- * The size, in bytes, of a block of audio data,
- * excluding the audio block header.
+ * The size, in bytes, of a block of audio data, excluding the audio block
+ * header.
*/
uint16 _audioBlockSize;
/**
- * The expected size of a block of audio data,
- * in bytes, excluding the audio block header.
+ * The expected size of a block of audio data, in bytes, excluding the audio
+ * block header.
*/
int16 _expectedAudioBlockSize;
/**
- * The number of compressed audio bytes that are
- * needed per frame to fill the audio buffer
- * without causing audio to drop out.
+ * The number of compressed audio bytes that are needed per frame to fill
+ * the audio buffer without causing audio to drop out.
*/
int16 _audioRecordInterval;
/**
- * If true, primer audio buffers should be filled
- * with silence instead of trying to read buffers
- * from the Robot data.
+ * If true, primer audio buffers should be filled with silence instead of
+ * trying to read buffers from the Robot data.
*/
uint16 _primerZeroCompressFlag;
/**
- * The size, in bytes, of the primer audio in the
- * Robot, including any extra alignment padding.
+ * The size, in bytes, of the primer audio in the Robot, including any extra
+ * alignment padding.
*/
uint16 _primerReservedSize;
/**
- * The combined size, in bytes, of the even and odd
- * primer channels.
+ * The combined size, in bytes, of the even and odd primer channels.
*/
int32 _totalPrimerSize;
/**
- * The absolute offset of the primer audio data in
- * the robot data stream.
+ * The absolute offset of the primer audio data in the robot data stream.
*/
int32 _primerPosition;
@@ -1122,54 +1057,47 @@ private:
int32 _oddPrimerSize;
/**
- * The absolute position in the audio stream of
- * the first audio packet.
+ * The absolute position in the audio stream of the first audio packet.
*/
int32 _firstAudioRecordPosition;
/**
- * A temporary buffer used to hold one frame of
- * raw (DPCM-compressed) audio when reading audio
- * records from the robot stream.
+ * A temporary buffer used to hold one frame of raw (DPCM-compressed) audio
+ * when reading audio records from the robot stream.
*/
byte *_audioBuffer;
/**
- * The next tick count when AV sync should be
- * checked and framerate adjustments made, if
- * necessary.
+ * The next tick count when AV sync should be checked and framerate
+ * adjustments made, if necessary.
*/
uint32 _checkAudioSyncTime;
/**
- * Primes the audio buffer with the first frame
- * of audio data.
+ * Primes the audio buffer with the first frame of audio data.
*
* @note `primeAudio` was `InitAudio` in SSCI
*/
bool primeAudio(const uint32 startTick);
/**
- * Reads primer data from the robot data stream
- * and puts it into the given buffers.
+ * Reads primer data from the robot data stream and puts it into the given
+ * buffers.
*/
bool readPrimerData(byte *outEvenBuffer, byte *outOddBuffer);
/**
- * Reads audio data for the given frame number
- * into the given buffer.
+ * Reads audio data for the given frame number into the given buffer.
*
- * @param outAudioPosition The position of the
- * audio, in compressed bytes, in the data stream.
- * @param outAudioSize The size of the audio data,
- * in compressed bytes.
+ * @param outAudioPosition The position of the audio, in compressed bytes,
+ * in the data stream.
+ * @param outAudioSize The size of the audio data, in compressed bytes.
*/
bool readAudioDataFromRecord(const int frameNo, byte *outBuffer, int &outAudioPosition, int &outAudioSize);
/**
- * Submits part of the audio packet of the given
- * frame to the audio list, starting `startPosition`
- * bytes into the audio.
+ * Submits part of the audio packet of the given frame to the audio list,
+ * starting `startPosition` bytes into the audio.
*/
bool readPartialAudioRecordAndSubmit(const int startFrame, const int startPosition);
@@ -1198,35 +1126,33 @@ public:
}
/**
- * Puts the current dimensions of the robot, in game script
- * coordinates, into the given rect, and returns the total
- * number of frames in the robot animation.
+ * Puts the current dimensions of the robot, in game script coordinates,
+ * into the given rect, and returns the total number of frames in the robot
+ * animation.
*/
uint16 getFrameSize(Common::Rect &outRect) const;
/**
- * Pumps the robot player for the next frame of video.
- * This is the main rendering function.
+ * Pumps the robot player for the next frame of video. This is the main
+ * rendering function.
*/
void doRobot();
/**
- * Submits any outstanding audio blocks that should
- * be added to the queue before the robot frame
- * becomes visible.
+ * Submits any outstanding audio blocks that should be added to the queue
+ * before the robot frame becomes visible.
*/
void frameAlmostVisible();
/**
- * Evaluates frame drift and makes modifications to
- * the player in order to ensure that future frames
- * will arrive on time.
+ * Evaluates frame drift and makes modifications to the player in order to
+ * ensure that future frames will arrive on time.
*/
void frameNowVisible();
/**
- * Scales a vertically compressed cel to its original
- * uncompressed dimensions.
+ * Scales a vertically compressed cel to its original uncompressed
+ * dimensions.
*/
void expandCel(byte *target, const byte* source, const int16 celWidth, const int16 celHeight) const;
@@ -1258,21 +1184,18 @@ private:
};
/**
- * A reg_t pointer to an in-memory
- * bitmap containing the cel.
+ * A reg_t pointer to an in-memory bitmap containing the cel.
*/
reg_t bitmapId;
/**
- * The lifetime of the cel, either just
- * for this frame or for the entire
+ * The lifetime of the cel, either just for this frame or for the entire
* duration of the robot playback.
*/
CelHandleLifetime status;
/**
- * The size, in pixels, of the decompressed
- * cel.
+ * The size, in pixels, of the decompressed cel.
*/
int area;
@@ -1298,16 +1221,14 @@ private:
void createCels5(const byte *rawVideoData, const int16 numCels, const bool usePalette);
/**
- * Creates a single screen item for a cel in a
- * version 5/6 robot.
+ * Creates a single screen item for a cel in a version 5/6 robot.
*
* Returns the size, in bytes, of the raw cel data.
*/
uint32 createCel5(const byte *rawVideoData, const int16 screenItemIndex, const bool usePalette);
/**
- * Preallocates memory for the next `numCels` cels
- * in the robot data stream.
+ * Preallocates memory for the next `numCels` cels in the robot data stream.
*/
void preallocateCelMemory(const byte *rawVideoData, const int16 numCels);
@@ -1322,8 +1243,7 @@ private:
reg_t _planeId;
/**
- * The origin of the robot animation, in screen
- * coordinates.
+ * The origin of the robot animation, in screen coordinates.
*/
Common::Point _position;
@@ -1338,80 +1258,72 @@ private:
int16 _xResolution, _yResolution;
/**
- * Whether or not the coordinates read from robot
- * data are high resolution.
+ * Whether or not the coordinates read from robot data are high resolution.
*/
bool _isHiRes;
/**
- * The maximum number of cels that will be rendered
- * on any given frame in this robot. Used for
- * preallocation of cel memory.
+ * The maximum number of cels that will be rendered on any given frame in
+ * this robot. Used for preallocation of cel memory.
*/
int16 _maxCelsPerFrame;
/**
- * The maximum areas, in pixels, for each of
- * the fixed cels in the robot. Used for
- * preallocation of cel memory.
+ * The maximum areas, in pixels, for each of the fixed cels in the robot.
+ * Used for preallocation of cel memory.
*/
MaxCelAreaList _maxCelArea;
/**
- * The hunk palette to use when rendering the
- * current frame, if the `usePalette` flag was set
- * in the robot header.
+ * The hunk palette to use when rendering the current frame, if the
+ * `usePalette` flag was set in the robot header.
*/
uint8 *_rawPalette;
/**
- * A list of the raw video data sizes, in bytes,
- * for each frame of the robot.
+ * A list of the raw video data sizes, in bytes, for each frame of the
+ * robot.
*/
VideoSizeList _videoSizes;
/**
- * A list of cels that will be present for the
- * entire duration of the robot animation.
+ * A list of cels that will be present for the entire duration of the robot
+ * animation.
*/
FixedCelsList _fixedCels;
/**
- * A list of handles for each cel in the current
- * frame.
+ * A list of handles for each cel in the current frame.
*/
CelHandleList _celHandles;
/**
- * Scratch memory used to temporarily store
- * decompressed cel data for vertically squashed
- * cels.
+ * Scratch memory used to temporarily store decompressed cel data for
+ * vertically squashed cels.
*/
ScratchMemory _celDecompressionBuffer;
/**
- * The size, in bytes, of the squashed cel
- * decompression buffer.
+ * The size, in bytes, of the squashed cel decompression buffer.
*/
int _celDecompressionArea;
/**
- * If true, the robot just started playing and
- * is awaiting output for the first frame.
+ * If true, the robot just started playing and is awaiting output for the
+ * first frame.
*/
bool _syncFrame;
/**
- * Scratch memory used to store the compressed robot
- * video data for the current frame.
+ * Scratch memory used to store the compressed robot video data for the
+ * current frame.
*/
ScratchMemory _doVersion5Scratch;
/**
- * When set to a non-negative value, forces the next
- * call to doRobot to render the given frame number
- * instead of whatever frame would have normally been
- * rendered.
+ * When set to a non-negative value, forces the next call to doRobot to
+ * render the given frame number instead of whatever frame would have
+ * normally been rendered.
*/
mutable int _cueForceShowFrame;
@@ -1426,14 +1338,14 @@ private:
RobotScreenItemList _screenItemList;
/**
- * The positions of the various screen items in this
- * robot, in screen coordinates.
+ * The positions of the various screen items in this robot, in screen
+ * coordinates.
*/
Common::Array<int16> _screenItemX, _screenItemY;
/**
- * The raw position values from the cel header for
- * each screen item currently on-screen.
+ * The raw position values from the cel header for each screen item
+ * currently on-screen.
*/
Common::Array<int16> _originalScreenItemX, _originalScreenItemY;
@@ -1449,11 +1361,10 @@ private:
int16 _priority;
/**
- * The amount of visual vertical compression applied
- * to the current cel. A value of 100 means no
- * compression; a value above 100 indicates how much
- * the cel needs to be scaled along the y-axis to
- * return to its original dimensions.
+ * The amount of visual vertical compression applied to the current cel. A
+ * value of 100 means no compression; a value above 100 indicates how much
+ * the cel needs to be scaled along the y-axis to return to its original
+ * dimensions.
*/
uint8 _verticalScaleFactor;
};
Commit: 8c9276e75a9097f6eb2856767f9e6a40eab3c5aa
https://github.com/scummvm/scummvm/commit/8c9276e75a9097f6eb2856767f9e6a40eab3c5aa
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:56:25-05:00
Commit Message:
SCI32: Clean up script patch comments
Changed paths:
engines/sci/engine/script_patches.cpp
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 162d97e..3e37d13 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -2289,10 +2289,10 @@ static const uint16 lighthouseFlagResetPatch[] = {
};
// When doing a system check on the portal computer in the lighthouse, the game
-// counts up to 1024MB, one megabyte at a time. In the original engine, this
-// count speed would be video speed dependent, but with our frame rate
-// throttler, it takes 17 seconds. So, replace this slowness with a much faster
-// POST that is more accurate to the original game.
+// counts up to 1024MB, one megabyte at a time. In SSCI, this count speed would
+// be video speed dependent, but with our frame rate throttler, it takes 17
+// seconds. So, replace this slowness with a much faster POST that is more
+// accurate to the original game.
// Applies to at least: US English 1.0c
static const uint16 lighthouseMemoryCountSignature[] = {
SIG_MAGICDWORD,
@@ -6411,13 +6411,12 @@ static const uint16 ramaBenchmarkPatch[] = {
};
// RAMA uses a custom save game format that game scripts read and write
-// manually. The save game format serialises object references, which in the
-// original engine could be done just by writing int16s (since object references
-// were just 16-bit indexes), but in ScummVM we have to write the full 32-bit
-// reg_t. We hijack kFileIOReadWord/kFileIOWriteWord to do this for us, but we
-// need the game to agree to use those kFileIO calls instead of doing raw reads
-// and creating its own numbers, as it tries to do here in
-// `SaveManager::readWord`.
+// manually. The save game format serialises object references, which SSCI could
+// be done just by writing int16s (since object references were just 16-bit
+// indexes), but in ScummVM we have to write the full 32-bit reg_t. We hijack
+// kFileIOReadWord/kFileIOWriteWord to do this for us, but we need the game to
+// agree to use those kFileIO calls instead of doing raw reads and creating its
+// own numbers, as it tries to do here in `SaveManager::readWord`.
static const uint16 ramaSerializeRegTSignature1[] = {
SIG_MAGICDWORD,
0x38, SIG_SELECTOR16(newWith), // pushi $10b (newWith)
Commit: 15f6e6b97edf9bb2c3729078d374c5dfef836c22
https://github.com/scummvm/scummvm/commit/15f6e6b97edf9bb2c3729078d374c5dfef836c22
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:56:25-05:00
Commit Message:
SCI32: Remove resolved TODO in helpers.h
Changed paths:
engines/sci/graphics/helpers.h
diff --git a/engines/sci/graphics/helpers.h b/engines/sci/graphics/helpers.h
index 38da280..9d266fc 100644
--- a/engines/sci/graphics/helpers.h
+++ b/engines/sci/graphics/helpers.h
@@ -240,11 +240,6 @@ struct Buffer : public Graphics::Surface {
Buffer(const uint16 width, const uint16 height, uint8 *const pix) :
screenWidth(width),
screenHeight(height),
- // TODO: These values are not correct for all games. Script
- // dimensions were hard-coded per game in the original
- // interpreter. Search all games for their internal script
- // dimensions and set appropriately. (This code does not
- // appear to exist at all in SCI3, which uses 640x480.)
scriptWidth(320),
scriptHeight(200) {
init(width, height, width, pix, Graphics::PixelFormat::createFormatCLUT8());
Commit: d53e7787391683830f57c77cc8acd87c50444d40
https://github.com/scummvm/scummvm/commit/d53e7787391683830f57c77cc8acd87c50444d40
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:56:26-05:00
Commit Message:
SCI32: Rewrap comments to 80 columns in SOL decoder
Changed paths:
engines/sci/sound/decoders/sol.cpp
engines/sci/sound/decoders/sol.h
diff --git a/engines/sci/sound/decoders/sol.cpp b/engines/sci/sound/decoders/sol.cpp
index 50d353c..a6eb8a4 100644
--- a/engines/sci/sound/decoders/sol.cpp
+++ b/engines/sci/sound/decoders/sol.cpp
@@ -157,11 +157,10 @@ SOLStream<STEREO, S16BIT, OLDDPCM8>::SOLStream(Common::SeekableReadStream *strea
template <bool STEREO, bool S16BIT, bool OLDDPCM8>
bool SOLStream<STEREO, S16BIT, OLDDPCM8>::seek(const Audio::Timestamp &where) {
if (where != 0) {
- // In order to seek in compressed SOL files, all
- // previous bytes must be known since it uses
- // differential compression. Therefore, only seeking
- // to the beginning is supported now (SSCI does not
- // offer seeking anyway)
+ // In order to seek in compressed SOL files, all previous bytes must be
+ // known since it uses differential compression. Therefore, only seeking
+ // to the beginning is supported now (SSCI does not offer seeking
+ // anyway)
return false;
}
diff --git a/engines/sci/sound/decoders/sol.h b/engines/sci/sound/decoders/sol.h
index 1141132..2b84b8b 100644
--- a/engines/sci/sound/decoders/sol.h
+++ b/engines/sci/sound/decoders/sol.h
@@ -47,8 +47,7 @@ private:
uint16 _sampleRate;
/**
- * The raw (possibly-compressed) size of audio data in
- * the stream.
+ * The raw (possibly-compressed) size of audio data in the stream.
*/
int32 _rawDataSize;
Commit: c7c5f28bdb2f393c1290bcac803cf9fc86ac8ed8
https://github.com/scummvm/scummvm/commit/c7c5f28bdb2f393c1290bcac803cf9fc86ac8ed8
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-10-06T22:56:26-05:00
Commit Message:
SCI32: Clean up scriptWidth/scriptHeight/screenWidth/screenHeight
This removes the unnecessary Buffer subclass and stops most places
where the output buffer was being interrogated about dimensions
instead of GfxFrameout.
Changed paths:
engines/sci/engine/kgraphics32.cpp
engines/sci/engine/kvideo.cpp
engines/sci/engine/savegame.cpp
engines/sci/engine/segment.h
engines/sci/event.cpp
engines/sci/graphics/celobj32.cpp
engines/sci/graphics/controls32.cpp
engines/sci/graphics/cursor32.cpp
engines/sci/graphics/frameout.cpp
engines/sci/graphics/frameout.h
engines/sci/graphics/helpers.h
engines/sci/graphics/paint32.cpp
engines/sci/graphics/plane32.cpp
engines/sci/graphics/screen_item32.cpp
engines/sci/graphics/text32.cpp
engines/sci/graphics/text32.h
engines/sci/graphics/transitions32.cpp
engines/sci/graphics/video32.cpp
engines/sci/video/robot_decoder.cpp
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 02b2cea..f9c1ede 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -77,7 +77,7 @@ reg_t kBaseSetter32(EngineState *s, int argc, reg_t *argv) {
Ratio scaleX;
if (getSciVersion() < SCI_VERSION_2_1_LATE) {
- const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
scaleX = Ratio(scriptWidth, celObj._xResolution);
}
@@ -160,11 +160,12 @@ reg_t kShakeScreen32(EngineState *s, int argc, reg_t *argv) {
}
reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) {
- const Buffer &buffer = g_sci->_gfxFrameout->getCurrentBuffer();
- if (buffer.screenWidth < 640 || buffer.screenHeight < 400)
- return make_reg(0, 0);
+ const GfxFrameout *gfxFrameout = g_sci->_gfxFrameout;
+ if (gfxFrameout->getScreenWidth() < 640 || gfxFrameout->getScreenHeight() < 400) {
+ return NULL_REG;
+ }
- return make_reg(0, 1);
+ return TRUE_REG;
}
reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) {
@@ -412,25 +413,25 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) {
}
reg_t kCelHigh32(EngineState *s, int argc, reg_t *argv) {
- GuiResourceId resourceId = argv[0].toUint16();
- int16 loopNo = argv[1].toSint16();
- int16 celNo = argv[2].toSint16();
- CelObjView celObj(resourceId, loopNo, celNo);
+ const GuiResourceId resourceId = argv[0].toUint16();
+ const int16 loopNo = argv[1].toSint16();
+ const int16 celNo = argv[2].toSint16();
+ const CelObjView celObj(resourceId, loopNo, celNo);
int16 height = celObj._height;
if (getSciVersion() < SCI_VERSION_2_1_LATE) {
- height = mulru(height, Ratio(g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight, celObj._yResolution));
+ height = mulru(height, Ratio(g_sci->_gfxFrameout->getScriptHeight(), celObj._yResolution));
}
return make_reg(0, height);
}
reg_t kCelWide32(EngineState *s, int argc, reg_t *argv) {
- GuiResourceId resourceId = argv[0].toUint16();
- int16 loopNo = argv[1].toSint16();
- int16 celNo = argv[2].toSint16();
- CelObjView celObj(resourceId, loopNo, celNo);
+ const GuiResourceId resourceId = argv[0].toUint16();
+ const int16 loopNo = argv[1].toSint16();
+ const int16 celNo = argv[2].toSint16();
+ const CelObjView celObj(resourceId, loopNo, celNo);
int16 width = celObj._width;
if (getSciVersion() < SCI_VERSION_2_1_LATE) {
- width = mulru(width, Ratio(g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth, celObj._xResolution));
+ width = mulru(width, Ratio(g_sci->_gfxFrameout->getScriptWidth(), celObj._xResolution));
}
return make_reg(0, width);
}
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index 98b2ba2..1bd886c 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -460,8 +460,8 @@ reg_t kPlayVMDShowCursor(EngineState *s, int argc, reg_t *argv) {
}
reg_t kPlayVMDSetBlackoutArea(EngineState *s, int argc, reg_t *argv) {
- const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
Common::Rect blackoutArea;
blackoutArea.left = MAX<int16>(0, argv[0].toSint16());
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 06a26ec..a7ebe0b 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -801,7 +801,7 @@ void SciBitmap::saveLoadWithSerializer(Common::Serializer &s) {
s.syncBytes(_data, _dataSize);
if (s.isLoading()) {
- _buffer = Buffer(getWidth(), getHeight(), getPixels());
+ _buffer.init(getWidth(), getHeight(), getWidth(), getPixels(), Graphics::PixelFormat::createFormatCLUT8());
}
}
#endif
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 2a4fd91..14744e3 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -977,7 +977,7 @@ public:
_data = (byte *)malloc(other._dataSize);
memcpy(_data, other._data, other._dataSize);
if (_dataSize) {
- _buffer = Buffer(getWidth(), getHeight(), getPixels());
+ _buffer.init(getWidth(), getHeight(), getWidth(), getPixels(), Graphics::PixelFormat::createFormatCLUT8());
}
_gc = other._gc;
}
@@ -998,7 +998,7 @@ public:
_data = (byte *)malloc(other._dataSize);
memcpy(_data, other._data, _dataSize);
if (_dataSize) {
- _buffer = Buffer(getWidth(), getHeight(), getPixels());
+ _buffer.init(getWidth(), getHeight(), getWidth(), getPixels(), Graphics::PixelFormat::createFormatCLUT8());
}
_gc = other._gc;
@@ -1032,7 +1032,7 @@ public:
setXResolution(xResolution);
setYResolution(yResolution);
- _buffer = Buffer(getWidth(), getHeight(), getPixels());
+ _buffer.init(getWidth(), getHeight(), getWidth(), getPixels(), Graphics::PixelFormat::createFormatCLUT8());
}
inline int getRawSize() const {
diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp
index e69095a..aef84e2 100644
--- a/engines/sci/event.cpp
+++ b/engines/sci/event.cpp
@@ -164,7 +164,7 @@ SciEvent EventManager::getScummVMEvent() {
#if ENABLE_SCI32
if (getSciVersion() >= SCI_VERSION_2) {
- const Buffer &screen = g_sci->_gfxFrameout->getCurrentBuffer();
+ const GfxFrameout *gfxFrameout = g_sci->_gfxFrameout;
// This will clamp `mousePos` according to the restricted zone,
// so any cursor or screen item associated with the mouse position
@@ -172,7 +172,7 @@ SciEvent EventManager::getScummVMEvent() {
g_sci->_gfxCursor32->deviceMoved(mousePos);
Common::Point mousePosSci = mousePos;
- mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight));
+ mulru(mousePosSci, Ratio(gfxFrameout->getScriptWidth(), gfxFrameout->getScreenWidth()), Ratio(gfxFrameout->getScriptHeight(), gfxFrameout->getScreenHeight()));
noEvent.mousePosSci = input.mousePosSci = mousePosSci;
if (_hotRectanglesActive) {
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index c2ae29b..fb7abe8 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -658,9 +658,9 @@ struct RENDERER {
_skipColor(skipColor) {}
inline void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
- byte *targetPixel = (byte *)target.getPixels() + target.screenWidth * targetRect.top + targetRect.left;
+ byte *targetPixel = (byte *)target.getPixels() + target.w * targetRect.top + targetRect.left;
- const int16 skipStride = target.screenWidth - targetRect.width();
+ const int16 skipStride = target.w - targetRect.width();
const int16 targetWidth = targetRect.width();
const int16 targetHeight = targetRect.height();
for (int16 y = 0; y < targetHeight; ++y) {
@@ -1265,8 +1265,8 @@ CelObjColor::CelObjColor(const uint8 color, const int16 width, const int16 heigh
_info.color = color;
_origin.x = 0;
_origin.y = 0;
- _xResolution = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- _yResolution = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ _xResolution = g_sci->_gfxFrameout->getScriptWidth();
+ _yResolution = g_sci->_gfxFrameout->getScriptHeight();
_hunkPaletteOffset = 0;
_mirrorX = false;
_remap = false;
diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp
index 82b99e6..fa4396c 100644
--- a/engines/sci/graphics/controls32.cpp
+++ b/engines/sci/graphics/controls32.cpp
@@ -391,8 +391,8 @@ ScrollWindow::ScrollWindow(SegManager *segMan, const Common::Rect &gameRect, con
_gfxText32.setFont(_fontId);
_pointSize = _gfxText32._font->getHeight();
- const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ const uint16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const uint16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
Common::Rect bitmapRect(gameRect);
mulinc(bitmapRect, Ratio(_gfxText32._xResolution, scriptWidth), Ratio(_gfxText32._yResolution, scriptHeight));
diff --git a/engines/sci/graphics/cursor32.cpp b/engines/sci/graphics/cursor32.cpp
index ae8c014..f401d1b 100644
--- a/engines/sci/graphics/cursor32.cpp
+++ b/engines/sci/graphics/cursor32.cpp
@@ -39,7 +39,7 @@ GfxCursor32::GfxCursor32() :
void GfxCursor32::init(const Buffer &outputBuffer) {
_screen = outputBuffer;
- _screenRegion.rect = Common::Rect(_screen.screenWidth, _screen.screenHeight);
+ _screenRegion.rect = Common::Rect(_screen.w, _screen.h);
_screenRegion.data = static_cast<byte *>(_screen.getPixels());
_restrictedArea = _screenRegion.rect;
}
@@ -151,10 +151,10 @@ void GfxCursor32::show() {
void GfxCursor32::setRestrictedArea(const Common::Rect &rect) {
_restrictedArea = rect;
- const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
- const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
- const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth();
+ const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight();
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
mulru(_restrictedArea, Ratio(screenWidth, scriptWidth), Ratio(screenHeight, scriptHeight), 0);
@@ -259,7 +259,7 @@ void GfxCursor32::setView(const GuiResourceId viewId, const int16 loopNo, const
// threshold size because inventory items usually have a
// high-resolution cursor representation.
bool pixelDouble = false;
- if (g_sci->_gfxFrameout->_isHiRes &&
+ if (g_sci->_gfxFrameout->isHiRes() &&
(g_sci->getGameId() == GID_GK1 ||
(g_sci->getGameId() == GID_PQ4 && _width <= 22 && _height <= 22))) {
@@ -275,7 +275,8 @@ void GfxCursor32::setView(const GuiResourceId viewId, const int16 loopNo, const
memset(_cursor.data, 255, _width * _height);
_cursor.skipColor = 255;
- Buffer target(_width, _height, _cursor.data);
+ Buffer target;
+ target.init(_width, _height, _width, _cursor.data, Graphics::PixelFormat::createFormatCLUT8());
if (pixelDouble) {
view.draw(target, _cursor.rect, Common::Point(0, 0), false, 2, 2);
} else {
@@ -314,10 +315,10 @@ void GfxCursor32::copyFromScreen(DrawRegion &target) {
}
void GfxCursor32::setPosition(const Common::Point &position) {
- const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
- const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
- const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
+ const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth();
+ const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight();
Common::Point newPosition;
newPosition.x = (position.x * Ratio(screenWidth, scriptWidth)).toInt();
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index a8746ee..7fc92a8 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -61,7 +61,7 @@
namespace Sci {
GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor) :
- _isHiRes(gameIsHiRes()),
+ _isHiRes(detectHiRes()),
_palette(palette),
_cursor(cursor),
_segMan(segMan),
@@ -74,15 +74,13 @@ GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitio
_lastScreenUpdateTick(0) {
if (g_sci->getGameId() == GID_PHANTASMAGORIA) {
- _currentBuffer = Buffer(630, 450, nullptr);
+ _currentBuffer.create(630, 450, Graphics::PixelFormat::createFormatCLUT8());
} else if (_isHiRes) {
- _currentBuffer = Buffer(640, 480, nullptr);
+ _currentBuffer.create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
} else {
- _currentBuffer = Buffer(320, 200, nullptr);
+ _currentBuffer.create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
}
- _currentBuffer.setPixels(calloc(1, _currentBuffer.screenWidth * _currentBuffer.screenHeight));
- _screenRect = Common::Rect(_currentBuffer.screenWidth, _currentBuffer.screenHeight);
- initGraphics(_currentBuffer.screenWidth, _currentBuffer.screenHeight, _isHiRes);
+ initGraphics(_currentBuffer.w, _currentBuffer.h, _isHiRes);
switch (g_sci->getGameId()) {
case GID_HOYLE5:
@@ -91,18 +89,20 @@ GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitio
case GID_PHANTASMAGORIA2:
case GID_TORIN:
case GID_RAMA:
- _currentBuffer.scriptWidth = 640;
- _currentBuffer.scriptHeight = 480;
+ _scriptWidth = 640;
+ _scriptHeight = 480;
break;
case GID_GK2:
case GID_PQSWAT:
if (!g_sci->isDemo()) {
- _currentBuffer.scriptWidth = 640;
- _currentBuffer.scriptHeight = 480;
+ _scriptWidth = 640;
+ _scriptHeight = 480;
+ break;
}
- break;
+ // fall through
default:
- // default script width for other games is 320x200
+ _scriptWidth = 320;
+ _scriptHeight = 200;
break;
}
}
@@ -110,7 +110,7 @@ GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitio
GfxFrameout::~GfxFrameout() {
clear();
CelObj::deinit();
- free(_currentBuffer.getPixels());
+ _currentBuffer.free();
}
void GfxFrameout::run() {
@@ -122,7 +122,7 @@ void GfxFrameout::run() {
// This plane is created in SCI::InitPlane in SSCI, and is a background fill
// plane to ensure "hidden" planes (planes with negative priority) are never
// drawn
- Plane *initPlane = new Plane(Common::Rect(_currentBuffer.scriptWidth, _currentBuffer.scriptHeight));
+ Plane *initPlane = new Plane(Common::Rect(_scriptWidth, _scriptHeight));
initPlane->_priority = 0;
_planes.add(initPlane);
}
@@ -133,7 +133,7 @@ void GfxFrameout::clear() {
_showList.clear();
}
-bool GfxFrameout::gameIsHiRes() const {
+bool GfxFrameout::detectHiRes() const {
// QFG4 is always low resolution
if (g_sci->getGameId() == GID_QFG4) {
return false;
@@ -360,7 +360,7 @@ void GfxFrameout::addPlane(Plane *plane) {
error("Plane %04x:%04x already exists", PRINT_REG(plane->_object));
}
- plane->clipScreenRect(_screenRect);
+ plane->clipScreenRect(Common::Rect(_currentBuffer.w, _currentBuffer.h));
_planes.add(plane);
}
@@ -369,7 +369,7 @@ void GfxFrameout::updatePlane(Plane &plane) {
assert(_planes.findByObject(plane._object) == &plane);
Plane *visiblePlane = _visiblePlanes.findByObject(plane._object);
- plane.sync(visiblePlane, _screenRect);
+ plane.sync(visiblePlane, Common::Rect(_currentBuffer.w, _currentBuffer.h));
// updateScreenRect was called a second time here in SSCI, but it is already
// called at the end of the sync call (also in SSCI) so there is no reason
// to do it again
@@ -455,7 +455,7 @@ void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, PlaneShowStyle *show
int16 prevRoom = g_sci->getEngineState()->variables[VAR_GLOBAL][kGlobalVarPreviousRoomNo].toSint16();
- Common::Rect rect(_currentBuffer.screenWidth, _currentBuffer.screenHeight);
+ Common::Rect rect(_currentBuffer.w, _currentBuffer.h);
_showList.add(rect);
showBits();
@@ -557,24 +557,39 @@ void GfxFrameout::directFrameOut(const Common::Rect &showRect) {
}
#ifdef USE_RGB_COLOR
+void GfxFrameout::redrawGameScreen(const Common::Rect &skipRect) const {
+ Common::ScopedPtr<Graphics::Surface> game(_currentBuffer.convertTo(g_system->getScreenFormat(), _palette->getHardwarePalette()));
+ assert(game);
+
+ Common::Rect rects[4];
+ int splitCount = splitRects(Common::Rect(game->w, game->h), skipRect, rects);
+ if (splitCount != -1) {
+ while (splitCount--) {
+ const Common::Rect &drawRect = rects[splitCount];
+ g_system->copyRectToScreen(game->getBasePtr(drawRect.left, drawRect.top), game->pitch, drawRect.left, drawRect.top, drawRect.width(), drawRect.height());
+ }
+ }
+
+ game->free();
+}
+
void GfxFrameout::resetHardware() {
updateMousePositionForRendering();
- _showList.add(Common::Rect(getCurrentBuffer().screenWidth, getCurrentBuffer().screenHeight));
+ _showList.add(Common::Rect(_currentBuffer.w, _currentBuffer.h));
g_system->getPaletteManager()->setPalette(_palette->getHardwarePalette(), 0, 256);
showBits();
}
#endif
/**
- * Determines the parts of `middleRect` that aren't overlapped
- * by `showRect`, optimised for contiguous memory writes.
- * Returns -1 if `middleRect` and `showRect` have no intersection.
- * Returns number of returned parts (in `outRects`) otherwise.
- * (In particular, this returns 0 if `middleRect` is contained
- * in `other`.)
+ * Determines the parts of `middleRect` that aren't overlapped by `showRect`,
+ * optimised for contiguous memory writes.
+ *
+ * `middleRect` is modified directly to extend into the upper and lower rects.
*
- * `middleRect` is modified directly to extend into the upper
- * and lower rects.
+ * @returns -1 if `middleRect` and `showRect` have no intersection, or the
+ * number of returned parts (in `outRects`) otherwise. (In particular, this
+ * returns 0 if `middleRect` is contained in `showRect`.)
*/
int splitRectsForRender(Common::Rect &middleRect, const Common::Rect &showRect, Common::Rect(&outRects)[2]) {
if (!middleRect.intersects(showRect)) {
@@ -998,7 +1013,7 @@ void GfxFrameout::showBits() {
rounded.left &= ~1;
rounded.right = (rounded.right + 1) & ~1;
- byte *sourceBuffer = (byte *)_currentBuffer.getPixels() + rounded.top * _currentBuffer.screenWidth + rounded.left;
+ byte *sourceBuffer = (byte *)_currentBuffer.getPixels() + rounded.top * _currentBuffer.w + rounded.left;
// Sometimes screen items (especially from SCI2.1early transitions, like
// in the asteroids minigame in PQ4) generate zero-dimension show
@@ -1023,7 +1038,7 @@ void GfxFrameout::showBits() {
#else
{
#endif
- g_system->copyRectToScreen(sourceBuffer, _currentBuffer.screenWidth, rounded.left, rounded.top, rounded.width(), rounded.height());
+ g_system->copyRectToScreen(sourceBuffer, _currentBuffer.w, rounded.left, rounded.top, rounded.width(), rounded.height());
}
}
@@ -1083,7 +1098,7 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co
byte *pixels = (byte *)_currentBuffer.getPixels();
- for (int pixelIndex = 0, numPixels = _currentBuffer.screenWidth * _currentBuffer.screenHeight; pixelIndex < numPixels; ++pixelIndex) {
+ for (int pixelIndex = 0, numPixels = _currentBuffer.w * _currentBuffer.h; pixelIndex < numPixels; ++pixelIndex) {
byte currentValue = pixels[pixelIndex];
int8 styleRangeValue = styleRanges[currentValue];
if (styleRangeValue == -1 && styleRangeValue == style) {
@@ -1205,7 +1220,7 @@ reg_t GfxFrameout::kernelIsOnMe(const reg_t object, const Common::Point &positio
bool GfxFrameout::isOnMe(const ScreenItem &screenItem, const Plane &plane, const Common::Point &position, const bool checkPixel) const {
Common::Point scaledPosition(position);
- mulru(scaledPosition, Ratio(_currentBuffer.screenWidth, _currentBuffer.scriptWidth), Ratio(_currentBuffer.screenHeight, _currentBuffer.scriptHeight));
+ mulru(scaledPosition, Ratio(_currentBuffer.w, _scriptWidth), Ratio(_currentBuffer.h, _scriptHeight));
scaledPosition.x += plane._planeRect.left;
scaledPosition.y += plane._planeRect.top;
@@ -1222,7 +1237,7 @@ bool GfxFrameout::isOnMe(const ScreenItem &screenItem, const Plane &plane, const
scaledPosition.y -= screenItem._scaledPosition.y;
if (getSciVersion() < SCI_VERSION_2_1_LATE) {
- mulru(scaledPosition, Ratio(celObj._xResolution, _currentBuffer.screenWidth), Ratio(celObj._yResolution, _currentBuffer.screenHeight));
+ mulru(scaledPosition, Ratio(celObj._xResolution, _currentBuffer.w), Ratio(celObj._yResolution, _currentBuffer.h));
}
if (screenItem._scale.signal != kScaleSignalNone && screenItem._scale.x && screenItem._scale.y) {
diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h
index 78bf2e0..55ba631 100644
--- a/engines/sci/graphics/frameout.h
+++ b/engines/sci/graphics/frameout.h
@@ -47,11 +47,35 @@ public:
GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor);
~GfxFrameout();
- bool _isHiRes;
-
void clear();
void run();
+ /**
+ * Returns true if the game should render at a resolution greater than
+ * 320x240.
+ */
+ inline bool isHiRes() const { return _isHiRes; }
+
+ /**
+ * Gets the x-resolution used by game scripts.
+ */
+ inline int16 getScriptWidth() const { return _scriptWidth; }
+
+ /**
+ * Gets the y-resolution used by game scripts.
+ */
+ inline int16 getScriptHeight() const { return _scriptHeight; }
+
+ /**
+ * Gets the x-resolution of the output buffer.
+ */
+ inline int16 getScreenWidth() const { return _currentBuffer.w; }
+
+ /**
+ * Gets the y-resolution of the output buffer.
+ */
+ inline int16 getScreenHeight() const { return _currentBuffer.h; }
+
private:
GfxCursor32 *_cursor;
GfxPalette32 *_palette;
@@ -59,10 +83,21 @@ private:
SegManager *_segMan;
/**
+ * Whether or not the game should render at a resolution above 320x240.
+ */
+ bool _isHiRes;
+
+ /**
+ * The resolution used by game scripts.
+ * @see celobj32.h comments on kLowResX/kLowResY.
+ */
+ int16 _scriptWidth, _scriptHeight;
+
+ /**
* Determines whether the current game should be rendered in high
* resolution.
*/
- bool gameIsHiRes() const;
+ bool detectHiRes() const;
#pragma mark -
#pragma mark Screen items
@@ -172,7 +207,7 @@ public:
* Resets the pixel format of the hardware surface to the given format.
*/
void setPixelFormat(const Graphics::PixelFormat &format) const {
- initGraphics(_currentBuffer.screenWidth, _currentBuffer.screenHeight, _isHiRes, &format);
+ initGraphics(_currentBuffer.w, _currentBuffer.h, _isHiRes, &format);
}
/**
@@ -216,6 +251,14 @@ public:
*/
void directFrameOut(const Common::Rect &showRect);
+ /**
+ * Redraws the game screen from the internal frame buffer to the system.
+ * Used after pixel format changes.
+ *
+ * @param skipRect An area of the screen that does not need to be redrawn.
+ */
+ void redrawGameScreen(const Common::Rect &skipRect) const;
+
#ifdef USE_RGB_COLOR
/**
* Sends the entire internal screen buffer and palette to hardware.
@@ -271,13 +314,6 @@ private:
bool _remapOccurred;
/**
- * The dimensions of the output buffer, in display coordinates.
- *
- * @note This field is on `GraphicsMgr.screen` in SSCI.
- */
- Common::Rect _screenRect;
-
- /**
* A list of rectangles, in screen coordinates, that represent portions of
* the internal screen buffer that are dirty and should be drawn to the
* hardware display surface.
diff --git a/engines/sci/graphics/helpers.h b/engines/sci/graphics/helpers.h
index 9d266fc..5842bf0 100644
--- a/engines/sci/graphics/helpers.h
+++ b/engines/sci/graphics/helpers.h
@@ -225,42 +225,7 @@ inline int splitRects(Common::Rect r, const Common::Rect &other, Common::Rect(&o
return splitCount;
}
-struct Buffer : public Graphics::Surface {
- uint16 screenWidth;
- uint16 screenHeight;
- uint16 scriptWidth;
- uint16 scriptHeight;
-
- Buffer() :
- screenWidth(0),
- screenHeight(0),
- scriptWidth(320),
- scriptHeight(200) {}
-
- Buffer(const uint16 width, const uint16 height, uint8 *const pix) :
- screenWidth(width),
- screenHeight(height),
- scriptWidth(320),
- scriptHeight(200) {
- init(width, height, width, pix, Graphics::PixelFormat::createFormatCLUT8());
- }
-
- void clear(const uint8 value) {
- memset(pixels, value, w * h);
- }
-
- inline uint8 *getAddress(const uint16 x, const uint16 y) {
- return (uint8 *)getBasePtr(x, y);
- }
-
- inline uint8 *getAddressSimRes(const uint16 x, const uint16 y) {
- return (uint8*)pixels + (y * w * screenHeight / scriptHeight) + (x * screenWidth / scriptWidth);
- }
-
- bool isNull() {
- return pixels == nullptr;
- }
-};
+typedef Graphics::Surface Buffer;
#endif
struct Color {
diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp
index f4d9c9f..f80f115 100644
--- a/engines/sci/graphics/paint32.cpp
+++ b/engines/sci/graphics/paint32.cpp
@@ -126,8 +126,8 @@ reg_t GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common::
thickness = (MAX<uint8>(1, thickness) - 1) | 1;
const uint8 halfThickness = thickness >> 1;
- const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ const uint16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const uint16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
outRect.left = MIN<int16>(startPoint.x, endPoint.x);
outRect.top = MIN<int16>(startPoint.y, endPoint.y);
diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp
index 77ca620..46a8aed 100644
--- a/engines/sci/graphics/plane32.cpp
+++ b/engines/sci/graphics/plane32.cpp
@@ -137,10 +137,10 @@ void Plane::init() {
}
void Plane::convertGameRectToPlaneRect() {
- const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
- const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
- const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth();
+ const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight();
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
const Ratio ratioX = Ratio(screenWidth, scriptWidth);
const Ratio ratioY = Ratio(screenHeight, scriptHeight);
diff --git a/engines/sci/graphics/screen_item32.cpp b/engines/sci/graphics/screen_item32.cpp
index 4e1ed83..0addd77 100644
--- a/engines/sci/graphics/screen_item32.cpp
+++ b/engines/sci/graphics/screen_item32.cpp
@@ -251,10 +251,10 @@ void ScreenItem::setFromObject(SegManager *segMan, const reg_t object, const boo
}
void ScreenItem::calcRects(const Plane &plane) {
- const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
- const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
- const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
+ const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth();
+ const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight();
const CelObj &celObj = getCelObj();
@@ -587,8 +587,8 @@ Common::Rect ScreenItem::getNowSeenRect(const Plane &plane) const {
nsRect = celObjRect;
}
- const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ const uint16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const uint16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
Ratio scaleX, scaleY;
if (_scale.signal == kScaleSignalManual) {
diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp
index 1fcf292..6ebbcc0 100644
--- a/engines/sci/graphics/text32.cpp
+++ b/engines/sci/graphics/text32.cpp
@@ -53,8 +53,8 @@ GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts) :
}
void GfxText32::init() {
- _xResolution = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- _yResolution = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ _xResolution = g_sci->_gfxFrameout->getScriptWidth();
+ _yResolution = g_sci->_gfxFrameout->getScriptHeight();
}
reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, const bool dimmed, const bool doScaling, const bool gc) {
@@ -73,8 +73,8 @@ reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect
setFont(fontId);
if (doScaling) {
- int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
Ratio scaleX(_xResolution, scriptWidth);
Ratio scaleY(_yResolution, scriptHeight);
@@ -115,8 +115,8 @@ reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &
setFont(fontId);
- int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
mulinc(_textRect, Ratio(_xResolution, scriptWidth), Ratio(_yResolution, scriptHeight));
@@ -218,7 +218,7 @@ void GfxText32::drawChar(const char charIndex) {
}
int16 GfxText32::getScaledFontHeight() const {
- const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
return (_font->getHeight() * scriptHeight + _yResolution - 1) / _yResolution;
}
@@ -335,7 +335,7 @@ void GfxText32::drawText(const uint index, uint length) {
void GfxText32::invertRect(const reg_t bitmapId, int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling) {
Common::Rect targetRect = rect;
if (doScaling) {
- bitmapStride = bitmapStride * _xResolution / g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ bitmapStride = bitmapStride * _xResolution / g_sci->_gfxFrameout->getScriptWidth();
targetRect = scaleRect(rect);
}
@@ -566,8 +566,8 @@ Common::Rect GfxText32::getTextSize(const Common::String &text, int16 maxWidth,
Common::Rect result;
- int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
maxWidth = maxWidth * _xResolution / scriptWidth;
@@ -638,8 +638,8 @@ int16 GfxText32::getStringWidth(const Common::String &text) {
}
int16 GfxText32::getTextCount(const Common::String &text, const uint index, const Common::Rect &textRect, const bool doScaling) {
- const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
Common::Rect scaledRect(textRect);
if (doScaling) {
diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h
index 945cc81..f9de3ad 100644
--- a/engines/sci/graphics/text32.h
+++ b/engines/sci/graphics/text32.h
@@ -139,10 +139,10 @@ private:
inline Common::Rect scaleRect(const Common::Rect &rect) {
Common::Rect scaledRect(rect);
- int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
- Ratio scaleX(_xResolution, scriptWidth);
- Ratio scaleY(_yResolution, scriptHeight);
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
+ const Ratio scaleX(_xResolution, scriptWidth);
+ const Ratio scaleY(_yResolution, scriptHeight);
mulinc(scaledRect, scaleX, scaleY);
return scaledRect;
}
@@ -191,12 +191,12 @@ public:
reg_t createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed, const bool gc);
inline int scaleUpWidth(int value) const {
- const int scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ const int scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
return (value * scriptWidth + _xResolution - 1) / _xResolution;
}
inline int scaleUpHeight(int value) const {
- const int scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ const int scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
return (value * scriptHeight + _yResolution - 1) / _yResolution;
}
diff --git a/engines/sci/graphics/transitions32.cpp b/engines/sci/graphics/transitions32.cpp
index 8be9e63..43479a2 100644
--- a/engines/sci/graphics/transitions32.cpp
+++ b/engines/sci/graphics/transitions32.cpp
@@ -544,7 +544,8 @@ void GfxTransitions32::configure21EarlyDissolve(PlaneShowStyle &showStyle, const
showStyle.bitmap = bitmapId;
const Buffer &source = g_sci->_gfxFrameout->getCurrentBuffer();
- Buffer target(showStyle.width, showStyle.height, bitmap.getPixels());
+ Buffer target;
+ target.init(showStyle.width, showStyle.height, showStyle.width, bitmap.getPixels(), Graphics::PixelFormat::createFormatCLUT8());
target.fillRect(Common::Rect(bitmap.getWidth(), bitmap.getHeight()), kDefaultSkipColor);
target.copyRectToSurface(source, 0, 0, gameRect);
@@ -754,7 +755,8 @@ bool GfxTransitions32::processPixelDissolve21Early(PlaneShowStyle &showStyle) {
bool unchanged = true;
SciBitmap &bitmap = *_segMan->lookupBitmap(showStyle.bitmap);
- Buffer buffer(showStyle.width, showStyle.height, bitmap.getPixels());
+ Buffer buffer;
+ buffer.init(showStyle.width, showStyle.height, showStyle.width, bitmap.getPixels(), Graphics::PixelFormat::createFormatCLUT8());
uint32 numPixels = showStyle.width * showStyle.height;
uint32 numPixelsPerDivision = (numPixels + showStyle.divisions) / showStyle.divisions;
diff --git a/engines/sci/graphics/video32.cpp b/engines/sci/graphics/video32.cpp
index c128ba1..8d68c8e 100644
--- a/engines/sci/graphics/video32.cpp
+++ b/engines/sci/graphics/video32.cpp
@@ -307,10 +307,10 @@ void SEQPlayer::play(const Common::String &fileName, const int16 numTicks, const
return;
}
- const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
- const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
- const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
+ const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth();
+ const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight();
const int16 scaledWidth = (_decoder->getWidth() * Ratio(screenWidth, scriptWidth)).toInt();
const int16 scaledHeight = (_decoder->getHeight() * Ratio(screenHeight, scriptHeight)).toInt();
@@ -392,8 +392,8 @@ AVIPlayer::IOStatus AVIPlayer::init(const bool doublePixels) {
height *= 2;
}
- const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
- const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+ const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth();
+ const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight();
// When scaling videos, they must not grow larger than the hardware screen
// or else the engine will crash. This is particularly important for the GK1
@@ -783,20 +783,7 @@ void VMDPlayer::redrawGameScreen() const {
return;
}
- Graphics::Surface *game = g_sci->_gfxFrameout->getCurrentBuffer().convertTo(g_system->getScreenFormat(), g_sci->_gfxPalette32->getHardwarePalette());
- assert(game);
-
- Common::Rect rects[4];
- int splitCount = splitRects(Common::Rect(game->w, game->h), _drawRect, rects);
- if (splitCount != -1) {
- while (splitCount--) {
- const Common::Rect &drawRect = rects[splitCount];
- g_system->copyRectToScreen(game->getBasePtr(drawRect.left, drawRect.top), game->pitch, drawRect.left, drawRect.top, drawRect.width(), drawRect.height());
- }
- }
-
- game->free();
- delete game;
+ g_sci->_gfxFrameout->redrawGameScreen(_drawRect);
}
#endif
@@ -900,8 +887,8 @@ void VMDPlayer::initComposited() {
}
const uint32 hunkPaletteSize = HunkPalette::calculateHunkPaletteSize(256, false);
- const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
- const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+ const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth();
+ const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight();
SciBitmap &vmdBitmap = *_segMan->allocateBitmap(&_bitmapId, _drawRect.width(), _drawRect.height(), 255, 0, 0, screenWidth, screenHeight, hunkPaletteSize, false, false);
vmdBitmap.getBuffer().fillRect(Common::Rect(_drawRect.width(), _drawRect.height()), 0);
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp
index 49ca226..4711a97 100644
--- a/engines/sci/video/robot_decoder.cpp
+++ b/engines/sci/video/robot_decoder.cpp
@@ -447,8 +447,8 @@ void RobotDecoder::initVideo(const int16 x, const int16 y, const int16 scale, co
if (_xResolution == 0 || _yResolution == 0) {
// In SSCI, default values were taken from RESOURCE.CFG hires property
// if it exists, but no games seem to take advantage of this
- _xResolution = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
- _yResolution = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+ _xResolution = g_sci->_gfxFrameout->getScreenWidth();
+ _yResolution = g_sci->_gfxFrameout->getScreenHeight();
}
if (hasPalette) {
@@ -677,10 +677,10 @@ void RobotDecoder::showFrame(const uint16 frameNo, const uint16 newX, const uint
if (_isHiRes) {
SciBitmap &bitmap = *_segMan->lookupBitmap(_celHandles[i].bitmapId);
- const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
- const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
- const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
+ const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth();
+ const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight();
if (scriptWidth == kLowResX && scriptHeight == kLowResY) {
const Ratio lowResToScreenX(screenWidth, kLowResX);
@@ -1453,10 +1453,10 @@ uint32 RobotDecoder::createCel5(const byte *rawVideoData, const int16 screenItem
rawVideoData += kCelHeaderSize;
- const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
- const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
- const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
- const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
+ const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+ const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
+ const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth();
+ const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight();
Common::Point origin;
if (scriptWidth == kLowResX && scriptHeight == kLowResY) {
More information about the Scummvm-git-logs
mailing list