[Scummvm-git-logs] scummvm master -> af99cab986268bfaac9b864e6e45a629a9b1d5ed
AndywinXp
noreply at scummvm.org
Mon Mar 9 16:24:59 UTC 2026
This automated email contains information about 15 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
cd8bd9769e SCUMM: Unify byleRLE's naming
6ba188539b SCUMM: Unify paintCelByleRLE variable naming
295d3511c4 SCUMM: Use compData.boundsRect instead of _out in ClassicCostumeRenderer
b97a2991db SCUMM: Use compData.maskPtr in AkosRenderer
2c23133616 SCUMM: Separate common code from paintCelByleRLE to paintCelByleRLECommon
3c137a1f2d SCUMM: Move AkosRenderer::paintCelByleRLECommon to BaseCostumeRenderer
a05a3f5797 SCUMM: Make startScaleIndexY handling closer to startScaleIndexX
4525d8300f SCUMM: Proper scaling fix for Backyard Basketball
c605127bd1 SCUMM: ClassicCostumeRenderer::paintCelByleRLECommon is not needed anymore
bd9ac56541 SCUMM: Move AkosRenderer::byleRLEDecode to BaseCostumeRenderer
d0aad69548 SCUMM: ClassicCostumeRenderer::byleRLEDecode is not needed anymore
ff7935c0fe SCUMM: Replace lambdas & std::function with virtual ones
a1d5a77f15 SCUMM: Keep original AkosRenderer behavior
9709d724f7 SCUMM: Fix USE_ARM_COSTUME_ASM code
af99cab986 SCUMM: Align with HE source code
Commit: cd8bd9769e40e39d54f92f39ca92f4387edf52df
https://github.com/scummvm/scummvm/commit/cd8bd9769e40e39d54f92f39ca92f4387edf52df
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Unify byleRLE's naming
proc3 -> byleRLEDecode
dataBlock, v1 -> compData
mainRoutine -> paintCelByleRLE
No functional changes.
Changed paths:
engines/scumm/akos.cpp
engines/scumm/akos.h
engines/scumm/costume.cpp
engines/scumm/costume.h
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index e0df022f4ca..b8283b5fc31 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -496,7 +496,7 @@ byte AkosRenderer::drawLimb(const Actor *a, int limb) {
return result;
}
-void AkosRenderer::byleRLEDecode(ByleRLEData &dataBlock) {
+void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
const byte *mask, *src;
byte *dst;
byte len, maskbit;
@@ -506,36 +506,36 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &dataBlock) {
bool masked;
lastColumnX = -1;
- y = dataBlock.y;
+ y = compData.y;
src = _srcPtr;
- dst = dataBlock.destPtr;
- len = dataBlock.repLen;
- color = dataBlock.repColor;
+ dst = compData.destPtr;
+ len = compData.repLen;
+ color = compData.repColor;
height = _height;
- scaleytab = &dataBlock.scaleTable[MAX<int>(0, dataBlock.scaleYIndex)]; // Avoid invalid mem reads in Basketball...
- maskbit = revBitMask(dataBlock.x & 7);
- mask = _vm->getMaskBuffer(dataBlock.x - (_vm->_virtscr[kMainVirtScreen].xstart & 7), dataBlock.y, _zbuf);
+ scaleytab = &compData.scaleTable[MAX<int>(0, compData.scaleYIndex)]; // Avoid invalid mem reads in Basketball...
+ maskbit = revBitMask(compData.x & 7);
+ mask = _vm->getMaskBuffer(compData.x - (_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf);
if (len)
goto StartPos;
do {
len = *src++;
- color = len >> dataBlock.shr;
- len &= dataBlock.mask;
+ color = len >> compData.shr;
+ len &= compData.mask;
if (!len)
len = *src++;
do {
if (_scaleY == 255 || *scaleytab++ < _scaleY) {
if (_actorHitMode) {
- if (color && y == _actorHitY && dataBlock.x == _actorHitX) {
+ if (color && y == _actorHitY && compData.x == _actorHitX) {
_actorHitResult = true;
return;
}
} else {
- masked = (y < dataBlock.boundsRect.top || y >= dataBlock.boundsRect.bottom) || (dataBlock.x < 0 || dataBlock.x >= dataBlock.boundsRect.right) || (*mask & maskbit);
+ masked = (y < compData.boundsRect.top || y >= compData.boundsRect.bottom) || (compData.x < 0 || compData.x >= compData.boundsRect.right) || (*mask & maskbit);
bool skipColumn = false;
if (color && !masked) {
@@ -544,7 +544,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &dataBlock) {
if (pcolor == 13) {
// In shadow mode 1 skipColumn works more or less the same way as in shadow
// mode 3. It is only ever checked and applied if pcolor is 13.
- skipColumn = (lastColumnX == dataBlock.x);
+ skipColumn = (lastColumnX == compData.x);
pcolor = _shadowTable[*dst];
}
} else if (_shadowMode == 2) {
@@ -554,7 +554,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &dataBlock) {
// I add the column skip here, too, although I don't know whether it always
// applies. But this is the only way to prevent recursive shading of pixels.
// This might need more fine tuning...
- skipColumn = (lastColumnX == dataBlock.x);
+ skipColumn = (lastColumnX == compData.x);
uint16 srcColor = (pcolor >> 1) & 0x7DEF;
uint16 dstColor = (READ_UINT16(dst) >> 1) & 0x7DEF;
pcolor = srcColor + dstColor;
@@ -562,14 +562,14 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &dataBlock) {
// I add the column skip here, too, although I don't know whether it always
// applies. But this is the only way to prevent recursive shading of pixels.
// This might need more fine tuning...
- skipColumn = (lastColumnX == dataBlock.x);
+ skipColumn = (lastColumnX == compData.x);
pcolor = (pcolor << 8) + *dst;
pcolor = _xmap[pcolor];
} else if (pcolor < 8) {
// This mode is used in COMI. The column skip only takes place when the shading
// is actually applied (for pcolor < 8). The skip avoids shading of pixels that
// already have been shaded.
- skipColumn = (lastColumnX == dataBlock.x);
+ skipColumn = (lastColumnX == compData.x);
pcolor = (pcolor << 8) + *dst;
pcolor = _shadowTable[pcolor];
}
@@ -588,25 +588,25 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &dataBlock) {
y++;
}
if (!--height) {
- if (!--dataBlock.skipWidth)
+ if (!--compData.skipWidth)
return;
height = _height;
- y = dataBlock.y;
+ y = compData.y;
- scaleytab = &dataBlock.scaleTable[MAX<int>(0, dataBlock.scaleYIndex)]; // Avoid invalid mem reads in Basketball...
- lastColumnX = dataBlock.x;
+ scaleytab = &compData.scaleTable[MAX<int>(0, compData.scaleYIndex)]; // Avoid invalid mem reads in Basketball...
+ lastColumnX = compData.x;
- if (_scaleX == 255 || dataBlock.scaleTable[dataBlock.scaleXIndex] < _scaleX) {
- dataBlock.x += dataBlock.scaleXStep;
- if (dataBlock.x < 0 || dataBlock.x >= dataBlock.boundsRect.right)
+ if (_scaleX == 255 || compData.scaleTable[compData.scaleXIndex] < _scaleX) {
+ compData.x += compData.scaleXStep;
+ if (compData.x < 0 || compData.x >= compData.boundsRect.right)
return;
- maskbit = revBitMask(dataBlock.x & 7);
- dataBlock.destPtr += dataBlock.scaleXStep * _vm->_bytesPerPixel;
+ maskbit = revBitMask(compData.x & 7);
+ compData.destPtr += compData.scaleXStep * _vm->_bytesPerPixel;
}
- dataBlock.scaleXIndex += dataBlock.scaleXStep;
- dst = dataBlock.destPtr;
- mask = _vm->getMaskBuffer(dataBlock.x - (_vm->_virtscr[kMainVirtScreen].xstart & 7), dataBlock.y, _zbuf);
+ compData.scaleXIndex += compData.scaleXStep;
+ dst = compData.destPtr;
+ mask = _vm->getMaskBuffer(compData.x - (_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf);
}
StartPos:;
} while (--len);
diff --git a/engines/scumm/akos.h b/engines/scumm/akos.h
index 14ec3053a9b..851ee417918 100644
--- a/engines/scumm/akos.h
+++ b/engines/scumm/akos.h
@@ -122,8 +122,9 @@ public:
protected:
byte drawLimb(const Actor *a, int limb) override;
+ void byleRLEDecode(ByleRLEData &compData);
+
byte paintCelByleRLE(int xMoveCur, int yMoveCur);
- void byleRLEDecode(ByleRLEData &v1);
byte paintCelCDATRLE(int xMoveCur, int yMoveCur);
byte paintCelMajMin(int xMoveCur, int yMoveCur);
byte paintCelTRLE(int actor, int drawToBack, int celX, int celY, int celWidth, int celHeight, byte tcolor, const byte *shadowTablePtr, int32 specialRenderFlags);
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index d514853c847..757422f99bc 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -71,7 +71,7 @@ static const int v1MMNESLookup[25] = {
0x17, 0x00, 0x01, 0x05, 0x16
};
-byte ClassicCostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) {
+byte ClassicCostumeRenderer::paintCelByleRLE(int xmoveCur, int ymoveCur) {
int i, skip = 0;
byte drawFlag = 1;
bool use_scaling;
@@ -308,13 +308,13 @@ byte ClassicCostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) {
if (_loaded._format == 0x57) {
// The v1 costume renderer needs the actor number, which is
// the same thing as the costume renderer's _actorID.
- procC64(compData, _actorID);
+ byleRLEDecode_C64(compData, _actorID);
} else if (newAmiCost)
- proc3_ami(compData);
+ byleRLEDecode_ami(compData);
else if (pcEngCost)
- procPCEngine(compData);
+ byleRLEDecode_PCEngine(compData);
else
- proc3(compData);
+ byleRLEDecode(compData);
return drawFlag;
}
@@ -339,7 +339,7 @@ static const int v1MMActorPalatte2[25] = {
dst[p + 1] = palette[pcolor]; \
}
-void ClassicCostumeRenderer::procC64(ByleRLEData &compData, int actor) {
+void ClassicCostumeRenderer::byleRLEDecode_C64(ByleRLEData &compData, int actor) {
const byte *mask, *src;
byte *dst;
byte len;
@@ -436,7 +436,7 @@ extern "C" int ClassicProc3RendererShadowARM(int _scaleY,
int _scaleIndexY);
#endif
-void ClassicCostumeRenderer::proc3(ByleRLEData &compData) {
+void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
const byte *mask, *src;
byte *dst;
byte len, maskbit;
@@ -539,7 +539,7 @@ void ClassicCostumeRenderer::proc3(ByleRLEData &compData) {
} while (1);
}
-void ClassicCostumeRenderer::proc3_ami(ByleRLEData &compData) {
+void ClassicCostumeRenderer::byleRLEDecode_ami(ByleRLEData &compData) {
const byte *mask, *src;
byte *dst;
byte maskbit, len, height, width;
@@ -623,7 +623,7 @@ static void PCESetCostumeData(byte block[16][16], int index, byte value) {
}
}
-void ClassicCostumeRenderer::procPCEngine(ByleRLEData &compData) {
+void ClassicCostumeRenderer::byleRLEDecode_PCEngine(ByleRLEData &compData) {
const byte *mask, *src;
byte *dst;
byte maskbit;
@@ -685,7 +685,7 @@ void ClassicCostumeRenderer::procPCEngine(ByleRLEData &compData) {
pcolor = block[row][col];
masked = (compData.y + yPos < 0 || compData.y + yPos >= _out.h) ||
- (compData.x + xPos < 0 || compData.x + xPos >= _out.w) ||
+ (compData.x + xPos < 0 || compData.x + xPos >= _out.w) ||
(compData.maskPtr && (mask[0] & maskbit));
if (pcolor && !masked) {
@@ -961,7 +961,7 @@ byte ClassicCostumeRenderer::drawLimb(const Actor *a, int limb) {
}
}
- byte result = mainRoutine(xmoveCur, ymoveCur);
+ byte result = paintCelByleRLE(xmoveCur, ymoveCur);
_mirror = mirror;
return result;
diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h
index 8ab61e0ae6d..8cacf7ecd0f 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -99,14 +99,12 @@ public:
protected:
byte drawLimb(const Actor *a, int limb) override;
- void proc3(ByleRLEData &v1);
- void proc3_ami(ByleRLEData &v1);
+ byte paintCelByleRLE(int xmoveCur, int ymoveCur);
- void procC64(ByleRLEData &v1, int actor);
-
- void procPCEngine(ByleRLEData &v1);
-
- byte mainRoutine(int xmoveCur, int ymoveCur);
+ void byleRLEDecode_C64(ByleRLEData &compData, int actor);
+ void byleRLEDecode(ByleRLEData &compData);
+ void byleRLEDecode_ami(ByleRLEData &compData);
+ void byleRLEDecode_PCEngine(ByleRLEData &compData);
};
class NESCostumeRenderer : public BaseCostumeRenderer {
Commit: 6ba188539b401971bd2c2ce3fd296146f47f3963
https://github.com/scummvm/scummvm/commit/6ba188539b401971bd2c2ce3fd296146f47f3963
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Unify paintCelByleRLE variable naming
No functional changes.
Changed paths:
engines/scumm/akos.cpp
engines/scumm/costume.cpp
engines/scumm/costume.h
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index b8283b5fc31..320c7df1109 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -776,7 +776,7 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
rect.left = rect.right = compData.x;
j = startScaleIndexX;
- for (i = 0, linesToSkip = 0; i < _width; i++) {
+ for (i = 0; i < _width; i++) {
if (rect.right < 0) {
linesToSkip++;
startScaleIndexX = j;
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 757422f99bc..50835909cf3 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -71,14 +71,15 @@ static const int v1MMNESLookup[25] = {
0x17, 0x00, 0x01, 0x05, 0x16
};
-byte ClassicCostumeRenderer::paintCelByleRLE(int xmoveCur, int ymoveCur) {
- int i, skip = 0;
- byte drawFlag = 1;
- bool use_scaling;
+byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
+ bool actorIsScaled;
+ int i;
+ int linesToSkip = 0;
byte startScaleIndexX;
int ex1, ex2;
Common::Rect rect;
int step;
+ byte drawFlag = 1;
ByleRLEData compData;
const int scaletableSize = 128;
@@ -111,7 +112,7 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xmoveCur, int ymoveCur) {
break;
}
- use_scaling = (_scaleX != 0xFF) || (_scaleY != 0xFF);
+ actorIsScaled = (_scaleX != 0xFF) || (_scaleY != 0xFF);
compData.x = _actorX;
compData.y = _actorY;
@@ -120,12 +121,12 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xmoveCur, int ymoveCur) {
if (_vm->_game.version <= 1)
compData.y += 1;
- if (use_scaling) {
+ if (actorIsScaled) {
/* Scale direction */
compData.scaleXStep = -1;
- if (xmoveCur < 0) {
- xmoveCur = -xmoveCur;
+ if (xMoveCur < 0) {
+ xMoveCur = -xMoveCur;
compData.scaleXStep = 1;
}
@@ -136,8 +137,8 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xmoveCur, int ymoveCur) {
if (_mirror) {
/* Adjust X position */
- startScaleIndexX = _scaleIndexX = scaletableSize - xmoveCur;
- for (i = 0; i < xmoveCur; i++) {
+ startScaleIndexX = _scaleIndexX = scaletableSize - xMoveCur;
+ for (i = 0; i < xMoveCur; i++) {
if (compData.scaleTable[_scaleIndexX++] < _scaleX)
compData.x -= compData.scaleXStep;
}
@@ -147,7 +148,7 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xmoveCur, int ymoveCur) {
_scaleIndexX = startScaleIndexX;
for (i = 0; i < _width; i++) {
if (rect.right < 0) {
- skip++;
+ linesToSkip++;
startScaleIndexX = _scaleIndexX;
}
if (compData.scaleTable[_scaleIndexX++] < _scaleX)
@@ -156,8 +157,8 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xmoveCur, int ymoveCur) {
} else {
/* No mirror */
/* Adjust X position */
- startScaleIndexX = _scaleIndexX = xmoveCur + scaletableSize;
- for (i = 0; i < xmoveCur; i++) {
+ startScaleIndexX = _scaleIndexX = scaletableSize + xMoveCur;
+ for (i = 0; i < xMoveCur; i++) {
if (compData.scaleTable[_scaleIndexX--] < _scaleX)
compData.x += compData.scaleXStep;
}
@@ -168,7 +169,7 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xmoveCur, int ymoveCur) {
for (i = 0; i < _width; i++) {
if (rect.left >= _out.w) {
startScaleIndexX = _scaleIndexX;
- skip++;
+ linesToSkip++;
}
if (compData.scaleTable[_scaleIndexX--] < _scaleX)
rect.left--;
@@ -176,35 +177,35 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xmoveCur, int ymoveCur) {
}
_scaleIndexX = startScaleIndexX;
- if (skip)
- skip--;
+ if (linesToSkip)
+ linesToSkip--;
step = -1;
- if (ymoveCur < 0) {
- ymoveCur = -ymoveCur;
- step = 1;
+ if (yMoveCur < 0) {
+ yMoveCur = -yMoveCur;
+ step = -step;
}
- _scaleIndexY = scaletableSize - ymoveCur;
- for (i = 0; i < ymoveCur; i++) {
+ _scaleIndexY = scaletableSize - yMoveCur;
+ for (i = 0; i < yMoveCur; i++) {
if (compData.scaleTable[_scaleIndexY++] < _scaleY)
compData.y -= step;
}
rect.top = rect.bottom = compData.y;
- _scaleIndexY = scaletableSize - ymoveCur;
+ _scaleIndexY = scaletableSize - yMoveCur;
for (i = 0; i < _height; i++) {
if (compData.scaleTable[_scaleIndexY++] < _scaleY)
rect.bottom++;
}
- _scaleIndexY = scaletableSize - ymoveCur;
+ _scaleIndexY = scaletableSize - yMoveCur;
} else {
if (!_mirror)
- xmoveCur = -xmoveCur;
+ xMoveCur = -xMoveCur;
- compData.x += xmoveCur;
- compData.y += ymoveCur;
+ compData.x += xMoveCur;
+ compData.y += yMoveCur;
if (_mirror) {
rect.left = compData.x;
@@ -237,41 +238,41 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xmoveCur, int ymoveCur) {
compData.repLen = 0;
if (_mirror) {
- if (!use_scaling)
- skip = -compData.x;
- if (skip > 0) {
+ if (!actorIsScaled)
+ linesToSkip = -compData.x;
+ if (linesToSkip > 0) {
if (!newAmiCost && !pcEngCost && _loaded._format != 0x57) {
- compData.skipWidth -= skip;
- skipCelLines(compData, skip);
+ compData.skipWidth -= linesToSkip;
+ skipCelLines(compData, linesToSkip);
compData.x = 0;
}
} else {
- skip = rect.right - _out.w;
- if (skip <= 0) {
+ linesToSkip = rect.right - _out.w;
+ if (linesToSkip <= 0) {
drawFlag = 2;
} else {
- compData.skipWidth -= skip;
+ compData.skipWidth -= linesToSkip;
}
}
} else {
- if (!use_scaling)
- skip = rect.right - _out.w;
- if (skip > 0) {
+ if (!actorIsScaled)
+ linesToSkip = rect.right - _out.w;
+ if (linesToSkip > 0) {
if (!newAmiCost && !pcEngCost && _loaded._format != 0x57) {
- compData.skipWidth -= skip;
- skipCelLines(compData, skip);
+ compData.skipWidth -= linesToSkip;
+ skipCelLines(compData, linesToSkip);
compData.x = _out.w - 1;
}
} else {
// V1 games uses 8 x 8 pixels for actors
if (_loaded._format == 0x57)
- skip = -8 - rect.left;
+ linesToSkip = -8 - rect.left;
else
- skip = -1 - rect.left;
- if (skip <= 0)
+ linesToSkip = -1 - rect.left;
+ if (linesToSkip <= 0)
drawFlag = 2;
else
- compData.skipWidth -= skip;
+ compData.skipWidth -= linesToSkip;
}
}
diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h
index 8cacf7ecd0f..0ca3a1c8ca9 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -99,7 +99,7 @@ public:
protected:
byte drawLimb(const Actor *a, int limb) override;
- byte paintCelByleRLE(int xmoveCur, int ymoveCur);
+ byte paintCelByleRLE(int xMoveCur, int yMoveCur);
void byleRLEDecode_C64(ByleRLEData &compData, int actor);
void byleRLEDecode(ByleRLEData &compData);
Commit: 295d3511c4a7775f22bff58afb68b585cf23f7a3
https://github.com/scummvm/scummvm/commit/295d3511c4a7775f22bff58afb68b585cf23f7a3
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Use compData.boundsRect instead of _out in ClassicCostumeRenderer
This makes it again a bit closer to AkosRenderer.
No functional changes.
Changed paths:
engines/scumm/akos.cpp
engines/scumm/costume.cpp
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index 320c7df1109..66e96f31bd6 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -535,7 +535,9 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
return;
}
} else {
- masked = (y < compData.boundsRect.top || y >= compData.boundsRect.bottom) || (compData.x < 0 || compData.x >= compData.boundsRect.right) || (*mask & maskbit);
+ masked = (y < compData.boundsRect.top || y >= compData.boundsRect.bottom)
+ || (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
+ || (*mask & maskbit);
bool skipColumn = false;
if (color && !masked) {
@@ -598,7 +600,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
if (_scaleX == 255 || compData.scaleTable[compData.scaleXIndex] < _scaleX) {
compData.x += compData.scaleXStep;
- if (compData.x < 0 || compData.x >= compData.boundsRect.right)
+ if (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
return;
maskbit = revBitMask(compData.x & 7);
compData.destPtr += compData.scaleXStep * _vm->_bytesPerPixel;
@@ -900,7 +902,6 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
}
}
-
if (rect.top >= compData.boundsRect.bottom || rect.bottom <= compData.boundsRect.top)
return 0;
@@ -912,7 +913,6 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
if (_mirror) {
if (!actorIsScaled)
linesToSkip = compData.boundsRect.left - compData.x;
-
if (linesToSkip > 0) {
compData.skipWidth -= linesToSkip;
skipCelLines(compData, linesToSkip);
@@ -930,11 +930,10 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
linesToSkip = rect.right - compData.boundsRect.right + 1;
if (linesToSkip > 0) {
compData.skipWidth -= linesToSkip;
- skipCelLines(compData, linesToSkip) ;
+ skipCelLines(compData, linesToSkip);
compData.x = compData.boundsRect.right - 1;
} else {
linesToSkip = (compData.boundsRect.left - 1) - rect.left;
-
if (linesToSkip <= 0)
drawFlag = 2;
else
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 50835909cf3..975f0affa96 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -121,6 +121,11 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
if (_vm->_game.version <= 1)
compData.y += 1;
+ compData.boundsRect.left = 0;
+ compData.boundsRect.top = 0;
+ compData.boundsRect.right = _out.w;
+ compData.boundsRect.bottom = _out.h;
+
if (actorIsScaled) {
/* Scale direction */
@@ -167,7 +172,7 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
_scaleIndexX = startScaleIndexX;
for (i = 0; i < _width; i++) {
- if (rect.left >= _out.w) {
+ if (rect.left >= compData.boundsRect.right) {
startScaleIndexX = _scaleIndexX;
linesToSkip++;
}
@@ -229,25 +234,25 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
else
_vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 1, rect.top, rect.bottom, _actorID);
- if (rect.top >= _out.h || rect.bottom <= 0)
+ if (rect.top >= compData.boundsRect.bottom || rect.bottom <= compData.boundsRect.top)
return 0;
- if (rect.left >= _out.w || rect.right <= 0)
+ if (rect.left >= compData.boundsRect.right || rect.right <= compData.boundsRect.left)
return 0;
compData.repLen = 0;
if (_mirror) {
if (!actorIsScaled)
- linesToSkip = -compData.x;
+ linesToSkip = compData.boundsRect.left - compData.x;
if (linesToSkip > 0) {
if (!newAmiCost && !pcEngCost && _loaded._format != 0x57) {
compData.skipWidth -= linesToSkip;
skipCelLines(compData, linesToSkip);
- compData.x = 0;
+ compData.x = compData.boundsRect.left;
}
} else {
- linesToSkip = rect.right - _out.w;
+ linesToSkip = rect.right - compData.boundsRect.right;
if (linesToSkip <= 0) {
drawFlag = 2;
} else {
@@ -256,19 +261,19 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
}
} else {
if (!actorIsScaled)
- linesToSkip = rect.right - _out.w;
+ linesToSkip = rect.right - compData.boundsRect.right;
if (linesToSkip > 0) {
if (!newAmiCost && !pcEngCost && _loaded._format != 0x57) {
compData.skipWidth -= linesToSkip;
skipCelLines(compData, linesToSkip);
- compData.x = _out.w - 1;
+ compData.x = compData.boundsRect.right - 1;
}
} else {
// V1 games uses 8 x 8 pixels for actors
if (_loaded._format == 0x57)
- linesToSkip = -8 - rect.left;
+ linesToSkip = (compData.boundsRect.left - 8) - rect.left;
else
- linesToSkip = -1 - rect.left;
+ linesToSkip = (compData.boundsRect.left - 1) - rect.left;
if (linesToSkip <= 0)
drawFlag = 2;
else
@@ -279,17 +284,17 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
if (compData.skipWidth <= 0)
return 0;
- if (rect.left < 0)
- rect.left = 0;
+ if (rect.left < compData.boundsRect.left)
+ rect.left = compData.boundsRect.left;
- if (rect.top < 0)
- rect.top = 0;
+ if (rect.top < compData.boundsRect.top)
+ rect.top = compData.boundsRect.top;
- if (rect.top > _out.h)
- rect.top = _out.h;
+ if (rect.top > compData.boundsRect.bottom)
+ rect.top = compData.boundsRect.bottom;
- if (rect.bottom > _out.h)
- rect.bottom = _out.h;
+ if (rect.bottom > compData.boundsRect.bottom)
+ rect.bottom = compData.boundsRect.bottom;
if (_drawTop > rect.top)
_drawTop = rect.top;
@@ -489,7 +494,9 @@ void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
do {
if (_scaleY == 255 || compData.scaleTable[scaleIndexY++] < _scaleY) {
- masked = (y < 0 || y >= _out.h) || (compData.x < 0 || compData.x >= _out.w) || (compData.maskPtr && (mask[0] & maskbit));
+ masked = (y < compData.boundsRect.top || y >= compData.boundsRect.bottom)
+ || (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
+ || (compData.maskPtr && (*mask & maskbit));
if (color && !masked) {
if (_shadowMode & 0x20) {
@@ -515,7 +522,7 @@ void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
if (_scaleX == 255 || compData.scaleTable[_scaleIndexX] < _scaleX) {
compData.x += compData.scaleXStep;
- if (compData.x < 0 || compData.x >= _out.w)
+ if (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
return;
maskbit = revBitMask(compData.x & 7);
compData.destPtr += compData.scaleXStep;
Commit: b97a2991db1a4d0d2e65007f8a000025a7eb3dad
https://github.com/scummvm/scummvm/commit/b97a2991db1a4d0d2e65007f8a000025a7eb3dad
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Use compData.maskPtr in AkosRenderer
_vm->getMaskBuffer(compData.x - (_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf)
basically translates into
_gdi->getMaskBuffer(compData.x - (_vm->_virtscr[kMainVirtScreen].xstart & 7) + _virtscr[kMainVirtScreen].xstart) / 8, y, z)
=
_gdi->getMaskBuffer(-(_vm->_virtscr[kMainVirtScreen].xstart & 7) + _virtscr[kMainVirtScreen].xstart) / 8 + compData.x / 8, y, z)
therefore we can shorten the first part (which is always divisible by 8)
into:
compData.maskPtr = _vm->getMaskBuffer(-(_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf)
and just use
compData.maskPtr + compData.x / 8
similarly as ClassicCostumeRenderer does.
Other than that, no functional changes.
Changed paths:
engines/scumm/akos.cpp
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index 66e96f31bd6..cb5b39357c0 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -515,7 +515,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
scaleytab = &compData.scaleTable[MAX<int>(0, compData.scaleYIndex)]; // Avoid invalid mem reads in Basketball...
maskbit = revBitMask(compData.x & 7);
- mask = _vm->getMaskBuffer(compData.x - (_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf);
+ mask = compData.maskPtr + compData.x / 8;
if (len)
goto StartPos;
@@ -537,7 +537,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
} else {
masked = (y < compData.boundsRect.top || y >= compData.boundsRect.bottom)
|| (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
- || (*mask & maskbit);
+ || (compData.maskPtr && (*mask & maskbit));
bool skipColumn = false;
if (color && !masked) {
@@ -608,7 +608,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
compData.scaleXIndex += compData.scaleXStep;
dst = compData.destPtr;
- mask = _vm->getMaskBuffer(compData.x - (_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf);
+ mask = compData.maskPtr + compData.x / 8;
}
StartPos:;
} while (--len);
@@ -965,6 +965,8 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
compData.height = _out.h;
compData.destPtr = (byte *)_out.getBasePtr(compData.x, compData.y);
+ compData.maskPtr = _vm->getMaskBuffer(-(_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf);
+
byleRLEDecode(compData);
return drawFlag;
Commit: 2c23133616a5e519ff0e5d16b4f238a093000901
https://github.com/scummvm/scummvm/commit/2c23133616a5e519ff0e5d16b4f238a093000901
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Separate common code from paintCelByleRLE to paintCelByleRLECommon
No functional changes.
Changed paths:
engines/scumm/akos.cpp
engines/scumm/akos.h
engines/scumm/costume.cpp
engines/scumm/costume.h
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index cb5b39357c0..edc3ec50cab 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -717,30 +717,85 @@ const byte bigCostumeScaleTable[768] = {
};
byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
- int num_colors;
- bool actorIsScaled;
- int i, j;
- int linesToSkip = 0, startScaleIndexX, startScaleIndexY;
- Common::Rect rect;
- int step;
- byte drawFlag = 1;
ByleRLEData compData;
const int scaletableSize = (_vm->_game.heversion >= 61) ? 128 : 384;
- /* implement custom scale table */
-
compData.scaleTable = (_vm->_game.heversion >= 61) ? smallCostumeScaleTable : bigCostumeScaleTable;
if (_vm->VAR_CUSTOMSCALETABLE != 0xFF && _vm->_res->isResourceLoaded(rtString, _vm->VAR(_vm->VAR_CUSTOMSCALETABLE))) {
compData.scaleTable = _vm->getStringAddressVar(_vm->VAR_CUSTOMSCALETABLE);
}
+ compData.x = _actorX;
+ compData.y = _actorY;
+
+ bool decode = true;
+
+ const auto markAsDirty = [this, &compData, &decode](const Common::Rect &rect) {
+ if (_vm->_game.heversion >= 71) {
+ if (_clipOverride.right > _clipOverride.left && _clipOverride.bottom > _clipOverride.top) {
+ compData.boundsRect = _clipOverride;
+ compData.boundsRect.right += 1;
+ compData.boundsRect.bottom += 1;
+
+ compData.boundsRect.right = CLIP<int16>(compData.boundsRect.right, 0, _vm->_screenWidth);
+ compData.boundsRect.bottom = CLIP<int16>(compData.boundsRect.bottom, 0, _vm->_screenHeight);
+ }
+ }
+
+ if (_actorHitMode) {
+ if (_actorHitX < rect.left || _actorHitX >= rect.right || _actorHitY < rect.top || _actorHitY >= rect.bottom)
+ decode = false;
+ } else {
+ markRectAsDirty(rect);
+
+ if (_vm->_game.heversion >= 71) {
+ ActorHE *a = (ActorHE *)_vm->derefActor(_actorID, "paintCelByleRLE");
+ a->setActorUpdateArea(rect.left, rect.top, rect.right, rect.bottom + 1);
+ }
+ }
+ };
+
+ byte drawFlag = paintCelByleRLECommon(
+ xMoveCur,
+ yMoveCur,
+ _vm->getResourceDataSize(_akpl),
+ scaletableSize,
+ compData,
+ markAsDirty,
+ decode);
+
+ if (!decode)
+ return drawFlag;
+
+ compData.maskPtr = _vm->getMaskBuffer(-(_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf);
+
+ byleRLEDecode(compData);
+
+ return drawFlag;
+}
+
+byte AkosRenderer::paintCelByleRLECommon(
+ int xMoveCur,
+ int yMoveCur,
+ int numColors,
+ int scaletableSize,
+ ByleRLEData &compData,
+ std::function<void(const Common::Rect &)> markAsDirty,
+ bool &decode) {
+
+ bool actorIsScaled;
+ int i, j;
+ int linesToSkip = 0, startScaleIndexX, startScaleIndexY;
+ Common::Rect rect;
+ int step;
+ byte drawFlag = 1;
+
// Setup color decoding variables
- num_colors = _vm->getResourceDataSize(_akpl);
- if (num_colors == 32) {
+ if (numColors == 32) {
compData.mask = 7;
compData.shr = 3;
- } else if (num_colors == 64) {
+ } else if (numColors == 64) {
compData.mask = 3;
compData.shr = 2;
} else {
@@ -750,9 +805,6 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
actorIsScaled = (_scaleX != 0xFF) || (_scaleY != 0xFF);
- compData.x = _actorX;
- compData.y = _actorY;
-
compData.boundsRect.left = 0;
compData.boundsRect.top = 0;
compData.boundsRect.right = _out.w;
@@ -879,34 +931,19 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
compData.skipWidth = _width;
compData.scaleXStep = _mirror ? 1 : -1;
- if (_vm->_game.heversion >= 71) {
- if (_clipOverride.right > _clipOverride.left && _clipOverride.bottom > _clipOverride.top) {
- compData.boundsRect = _clipOverride;
- compData.boundsRect.right += 1;
- compData.boundsRect.bottom += 1;
-
- compData.boundsRect.right = CLIP<int16>(compData.boundsRect.right, 0, _vm->_screenWidth);
- compData.boundsRect.bottom = CLIP<int16>(compData.boundsRect.bottom, 0, _vm->_screenHeight);
- }
- }
-
- if (_actorHitMode) {
- if (_actorHitX < rect.left || _actorHitX >= rect.right || _actorHitY < rect.top || _actorHitY >= rect.bottom)
- return 0;
- } else {
- markRectAsDirty(rect);
-
- if (_vm->_game.heversion >= 71) {
- ActorHE *a = (ActorHE *)_vm->derefActor(_actorID, "paintCelByleRLE");
- a->setActorUpdateArea(rect.left, rect.top, rect.right, rect.bottom + 1);
- }
- }
+ markAsDirty(rect);
+ if (!decode)
+ return 0;
- if (rect.top >= compData.boundsRect.bottom || rect.bottom <= compData.boundsRect.top)
+ if (rect.top >= compData.boundsRect.bottom || rect.bottom <= compData.boundsRect.top) {
+ decode = false;
return 0;
+ }
- if (rect.left >= compData.boundsRect.right || rect.right <= compData.boundsRect.left)
+ if (rect.left >= compData.boundsRect.right || rect.right <= compData.boundsRect.left) {
+ decode = false;
return 0;
+ }
compData.repLen = 0;
@@ -941,8 +978,10 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
}
}
- if (compData.skipWidth <= 0 || _height <= 0)
+ if (compData.skipWidth <= 0 || _height <= 0) {
+ decode = false;
return 0;
+ }
if (rect.left < compData.boundsRect.left)
rect.left = compData.boundsRect.left;
@@ -965,10 +1004,6 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
compData.height = _out.h;
compData.destPtr = (byte *)_out.getBasePtr(compData.x, compData.y);
- compData.maskPtr = _vm->getMaskBuffer(-(_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf);
-
- byleRLEDecode(compData);
-
return drawFlag;
}
diff --git a/engines/scumm/akos.h b/engines/scumm/akos.h
index 851ee417918..22daca48c86 100644
--- a/engines/scumm/akos.h
+++ b/engines/scumm/akos.h
@@ -24,6 +24,7 @@
#include "scumm/base-costume.h"
#include "scumm/he/wiz_he.h"
+#include <functional>
namespace Scumm {
@@ -108,7 +109,6 @@ public:
_akct = nullptr;
_rgbs = nullptr;
_xmap = nullptr;
- _actorHitMode = false;
}
bool _actorHitMode = false;
@@ -125,6 +125,15 @@ protected:
void byleRLEDecode(ByleRLEData &compData);
byte paintCelByleRLE(int xMoveCur, int yMoveCur);
+ byte paintCelByleRLECommon(
+ int xMoveCur,
+ int yMoveCur,
+ int numColors,
+ int scaletableSize,
+ ByleRLEData &compData,
+ std::function<void(const Common::Rect &)> markAsDirty,
+ bool &decode);
+
byte paintCelCDATRLE(int xMoveCur, int yMoveCur);
byte paintCelMajMin(int xMoveCur, int yMoveCur);
byte paintCelTRLE(int actor, int drawToBack, int celX, int celY, int celWidth, int celHeight, byte tcolor, const byte *shadowTablePtr, int32 specialRenderFlags);
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 975f0affa96..ebef1f54f1f 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -72,30 +72,13 @@ static const int v1MMNESLookup[25] = {
};
byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
- bool actorIsScaled;
- int i;
- int linesToSkip = 0;
- byte startScaleIndexX;
int ex1, ex2;
- Common::Rect rect;
- int step;
- byte drawFlag = 1;
ByleRLEData compData;
- const int scaletableSize = 128;
+ const bool c64Cost = _loaded._format == 0x57;
const bool newAmiCost = (_vm->_game.version == 5) && (_vm->_game.platform == Common::kPlatformAmiga);
const bool pcEngCost = (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine);
- compData.scaleTable = smallCostumeScaleTable;
-
- if (_loaded._numColors == 32) {
- compData.mask = 7;
- compData.shr = 3;
- } else {
- compData.mask = 15;
- compData.shr = 4;
- }
-
switch (_loaded._format) {
case 0x60:
case 0x61:
@@ -112,7 +95,7 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
break;
}
- actorIsScaled = (_scaleX != 0xFF) || (_scaleY != 0xFF);
+ compData.scaleTable = smallCostumeScaleTable;
compData.x = _actorX;
compData.y = _actorY;
@@ -121,6 +104,76 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
if (_vm->_game.version <= 1)
compData.y += 1;
+ bool decode = true;
+
+ const auto markAsDirty = [this](const Common::Rect &rect) {
+ if (_vm->_game.version == 1) {
+ // V1 games uses 8 x 8 pixels for actors
+ _vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 8, rect.top, rect.bottom, _actorID);
+ } else {
+ _vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 1, rect.top, rect.bottom, _actorID);
+ }
+ };
+
+ byte drawFlag = paintCelByleRLECommon(
+ xMoveCur,
+ yMoveCur,
+ _loaded._numColors,
+ 128,
+ newAmiCost || pcEngCost,
+ c64Cost,
+ compData,
+ markAsDirty,
+ decode);
+
+ if (!decode)
+ return drawFlag;
+
+ compData.maskPtr = _vm->getMaskBuffer(0, compData.y, _zbuf);
+
+ if (c64Cost) {
+ // The v1 costume renderer needs the actor number, which is
+ // the same thing as the costume renderer's _actorID.
+ byleRLEDecode_C64(compData, _actorID);
+ } else if (newAmiCost)
+ byleRLEDecode_ami(compData);
+ else if (pcEngCost)
+ byleRLEDecode_PCEngine(compData);
+ else
+ byleRLEDecode(compData);
+
+ return drawFlag;
+}
+
+byte ClassicCostumeRenderer::paintCelByleRLECommon(
+ int xMoveCur,
+ int yMoveCur,
+ int numColors,
+ int scaletableSize,
+ bool amiOrPcEngCost,
+ bool c64Cost,
+ ByleRLEData &compData,
+ std::function<void (const Common::Rect &)> markAsDirty,
+ bool &decode) {
+
+ bool actorIsScaled;
+ int i;
+ int linesToSkip = 0;
+ byte startScaleIndexX;
+ Common::Rect rect;
+ int step;
+ byte drawFlag = 1;
+
+ if (numColors == 32) {
+ compData.mask = 7;
+ compData.shr = 3;
+ } else {
+ compData.mask = 15;
+ compData.shr = 4;
+ }
+
+ actorIsScaled = (_scaleX != 0xFF) || (_scaleY != 0xFF);
+
compData.boundsRect.left = 0;
compData.boundsRect.top = 0;
compData.boundsRect.right = _out.w;
@@ -228,17 +281,17 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
compData.skipWidth = _width;
compData.scaleXStep = _mirror ? 1 : -1;
- if (_vm->_game.version == 1)
- // V1 games uses 8 x 8 pixels for actors
- _vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 8, rect.top, rect.bottom, _actorID);
- else
- _vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 1, rect.top, rect.bottom, _actorID);
+ markAsDirty(rect);
- if (rect.top >= compData.boundsRect.bottom || rect.bottom <= compData.boundsRect.top)
+ if (rect.top >= compData.boundsRect.bottom || rect.bottom <= compData.boundsRect.top) {
+ decode = false;
return 0;
+ }
- if (rect.left >= compData.boundsRect.right || rect.right <= compData.boundsRect.left)
+ if (rect.left >= compData.boundsRect.right || rect.right <= compData.boundsRect.left) {
+ decode = false;
return 0;
+ }
compData.repLen = 0;
@@ -246,7 +299,7 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
if (!actorIsScaled)
linesToSkip = compData.boundsRect.left - compData.x;
if (linesToSkip > 0) {
- if (!newAmiCost && !pcEngCost && _loaded._format != 0x57) {
+ if (!amiOrPcEngCost && !c64Cost) {
compData.skipWidth -= linesToSkip;
skipCelLines(compData, linesToSkip);
compData.x = compData.boundsRect.left;
@@ -263,14 +316,14 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
if (!actorIsScaled)
linesToSkip = rect.right - compData.boundsRect.right;
if (linesToSkip > 0) {
- if (!newAmiCost && !pcEngCost && _loaded._format != 0x57) {
+ if (!amiOrPcEngCost && !c64Cost) {
compData.skipWidth -= linesToSkip;
skipCelLines(compData, linesToSkip);
compData.x = compData.boundsRect.right - 1;
}
} else {
// V1 games uses 8 x 8 pixels for actors
- if (_loaded._format == 0x57)
+ if (c64Cost)
linesToSkip = (compData.boundsRect.left - 8) - rect.left;
else
linesToSkip = (compData.boundsRect.left - 1) - rect.left;
@@ -281,8 +334,10 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
}
}
- if (compData.skipWidth <= 0)
+ if (compData.skipWidth <= 0) {
+ decode = false;
return 0;
+ }
if (rect.left < compData.boundsRect.left)
rect.left = compData.boundsRect.left;
@@ -302,6 +357,7 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
_drawBottom = rect.bottom;
if (_height + rect.top >= 256) {
+ decode = false;
return 2;
}
@@ -309,19 +365,6 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
compData.height = _out.h;
compData.destPtr = (byte *)_out.getBasePtr(compData.x, compData.y);
- compData.maskPtr = _vm->getMaskBuffer(0, compData.y, _zbuf);
-
- if (_loaded._format == 0x57) {
- // The v1 costume renderer needs the actor number, which is
- // the same thing as the costume renderer's _actorID.
- byleRLEDecode_C64(compData, _actorID);
- } else if (newAmiCost)
- byleRLEDecode_ami(compData);
- else if (pcEngCost)
- byleRLEDecode_PCEngine(compData);
- else
- byleRLEDecode(compData);
-
return drawFlag;
}
diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h
index 0ca3a1c8ca9..abf49fb5919 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -23,6 +23,7 @@
#define SCUMM_COSTUME_H
#include "scumm/base-costume.h"
+#include <functional>
namespace Scumm {
class ClassicCostumeLoader : public BaseCostumeLoader {
@@ -100,6 +101,16 @@ protected:
byte drawLimb(const Actor *a, int limb) override;
byte paintCelByleRLE(int xMoveCur, int yMoveCur);
+ byte paintCelByleRLECommon(
+ int xMoveCur,
+ int yMoveCur,
+ int numColors,
+ int scaletableSize,
+ bool amiOrPcEngCost,
+ bool c64Cost,
+ ByleRLEData &compData,
+ std::function<void(const Common::Rect &)> markAsDirty,
+ bool &decode);
void byleRLEDecode_C64(ByleRLEData &compData, int actor);
void byleRLEDecode(ByleRLEData &compData);
Commit: 3c137a1f2d046332298fe5e9cfb191c56252a401
https://github.com/scummvm/scummvm/commit/3c137a1f2d046332298fe5e9cfb191c56252a401
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Move AkosRenderer::paintCelByleRLECommon to BaseCostumeRenderer
No functional changes, the function body is identical.
Changed paths:
engines/scumm/akos.cpp
engines/scumm/akos.h
engines/scumm/base-costume.cpp
engines/scumm/base-costume.h
engines/scumm/costume.cpp
engines/scumm/costume.h
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index edc3ec50cab..b02621ea06d 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -761,6 +761,8 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
yMoveCur,
_vm->getResourceDataSize(_akpl),
scaletableSize,
+ false,
+ false,
compData,
markAsDirty,
decode);
@@ -775,238 +777,6 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
return drawFlag;
}
-byte AkosRenderer::paintCelByleRLECommon(
- int xMoveCur,
- int yMoveCur,
- int numColors,
- int scaletableSize,
- ByleRLEData &compData,
- std::function<void(const Common::Rect &)> markAsDirty,
- bool &decode) {
-
- bool actorIsScaled;
- int i, j;
- int linesToSkip = 0, startScaleIndexX, startScaleIndexY;
- Common::Rect rect;
- int step;
- byte drawFlag = 1;
-
- // Setup color decoding variables
- if (numColors == 32) {
- compData.mask = 7;
- compData.shr = 3;
- } else if (numColors == 64) {
- compData.mask = 3;
- compData.shr = 2;
- } else {
- compData.mask = 15;
- compData.shr = 4;
- }
-
- actorIsScaled = (_scaleX != 0xFF) || (_scaleY != 0xFF);
-
- compData.boundsRect.left = 0;
- compData.boundsRect.top = 0;
- compData.boundsRect.right = _out.w;
- compData.boundsRect.bottom = _out.h;
-
- if (actorIsScaled) {
-
- /* Scale direction */
- compData.scaleXStep = -1;
- if (xMoveCur < 0) {
- xMoveCur = -xMoveCur;
- compData.scaleXStep = 1;
- }
-
- if (_mirror) {
- /* Adjust X position */
- startScaleIndexX = j = scaletableSize - xMoveCur;
- for (i = 0; i < xMoveCur; i++) {
- if (compData.scaleTable[j++] < _scaleX)
- compData.x -= compData.scaleXStep;
- }
-
- rect.left = rect.right = compData.x;
-
- j = startScaleIndexX;
- for (i = 0; i < _width; i++) {
- if (rect.right < 0) {
- linesToSkip++;
- startScaleIndexX = j;
- }
- if (compData.scaleTable[j++] < _scaleX)
- rect.right++;
- }
- } else {
- /* No mirror */
- /* Adjust X position */
- startScaleIndexX = j = scaletableSize + xMoveCur;
- for (i = 0; i < xMoveCur; i++) {
- if (compData.scaleTable[j--] < _scaleX)
- compData.x += compData.scaleXStep;
- }
-
- rect.left = rect.right = compData.x;
-
- j = startScaleIndexX;
- for (i = 0; i < _width; i++) {
- if (rect.left >= compData.boundsRect.right) {
- startScaleIndexX = j;
- linesToSkip++;
- }
- if (compData.scaleTable[j--] < _scaleX)
- rect.left--;
- }
- }
-
- if (linesToSkip)
- linesToSkip--;
-
- step = -1;
- if (yMoveCur < 0) {
- yMoveCur = -yMoveCur;
- step = -step;
- }
-
- startScaleIndexY = scaletableSize - yMoveCur;
- for (i = 0; i < yMoveCur; i++) {
- // WORKAROUND: Backyard Basketball sends out yMoveCur values higher than 128!
- // This triggers ASAN, because it tries to reach a negative index of compData.scaleTable[].
- if (startScaleIndexY < 0) {
- debug(8, "AkosRenderer::paintCelByleRLE(): Negative startScaleIndexY: %d; actor (%d), scaletableSize (%d), yMoveCur (%d), working around it...",
- _actorID, startScaleIndexY, scaletableSize, yMoveCur);
- if (compData.scaleTable[0] < _scaleY)
- compData.y -= step;
-
- startScaleIndexY++;
- continue;
- }
-
- if (compData.scaleTable[startScaleIndexY++] < _scaleY)
- compData.y -= step;
- }
-
- rect.top = rect.bottom = compData.y;
- startScaleIndexY = scaletableSize - yMoveCur;
- for (i = 0; i < _height; i++) {
- // WORKAROUND: See above...
- if (startScaleIndexY < 0) {
- if (compData.scaleTable[0] < _scaleY)
- rect.bottom++;
-
- startScaleIndexY++;
- continue;
- }
-
- if (compData.scaleTable[startScaleIndexY++] < _scaleY)
- rect.bottom++;
- }
-
- startScaleIndexY = scaletableSize - yMoveCur;
- } else {
- if (!_mirror)
- xMoveCur = -xMoveCur;
-
- compData.x += xMoveCur;
- compData.y += yMoveCur;
-
- if (_mirror) {
- rect.left = compData.x;
- rect.right = compData.x + _width;
- } else {
- rect.left = compData.x - _width;
- rect.right = compData.x;
- }
-
- rect.top = compData.y;
- rect.bottom = rect.top + _height;
-
- startScaleIndexX = scaletableSize;
- startScaleIndexY = scaletableSize;
- }
-
- compData.scaleXIndex = startScaleIndexX;
- compData.scaleYIndex = startScaleIndexY;
- compData.skipWidth = _width;
- compData.scaleXStep = _mirror ? 1 : -1;
-
- markAsDirty(rect);
- if (!decode)
- return 0;
-
- if (rect.top >= compData.boundsRect.bottom || rect.bottom <= compData.boundsRect.top) {
- decode = false;
- return 0;
- }
-
- if (rect.left >= compData.boundsRect.right || rect.right <= compData.boundsRect.left) {
- decode = false;
- return 0;
- }
-
- compData.repLen = 0;
-
- if (_mirror) {
- if (!actorIsScaled)
- linesToSkip = compData.boundsRect.left - compData.x;
- if (linesToSkip > 0) {
- compData.skipWidth -= linesToSkip;
- skipCelLines(compData, linesToSkip);
- compData.x = compData.boundsRect.left;
- } else {
- linesToSkip = rect.right - compData.boundsRect.right;
- if (linesToSkip <= 0) {
- drawFlag = 2;
- } else {
- compData.skipWidth -= linesToSkip;
- }
- }
- } else {
- if (!actorIsScaled)
- linesToSkip = rect.right - compData.boundsRect.right + 1;
- if (linesToSkip > 0) {
- compData.skipWidth -= linesToSkip;
- skipCelLines(compData, linesToSkip);
- compData.x = compData.boundsRect.right - 1;
- } else {
- linesToSkip = (compData.boundsRect.left - 1) - rect.left;
- if (linesToSkip <= 0)
- drawFlag = 2;
- else
- compData.skipWidth -= linesToSkip;
- }
- }
-
- if (compData.skipWidth <= 0 || _height <= 0) {
- decode = false;
- return 0;
- }
-
- if (rect.left < compData.boundsRect.left)
- rect.left = compData.boundsRect.left;
-
- if (rect.top < compData.boundsRect.top)
- rect.top = compData.boundsRect.top;
-
- if (rect.top > compData.boundsRect.bottom)
- rect.top = compData.boundsRect.bottom;
-
- if (rect.bottom > compData.boundsRect.bottom)
- rect.bottom = compData.boundsRect.bottom;
-
- if (_drawTop > rect.top)
- _drawTop = rect.top;
- if (_drawBottom < rect.bottom)
- _drawBottom = rect.bottom;
-
- compData.width = _out.w;
- compData.height = _out.h;
- compData.destPtr = (byte *)_out.getBasePtr(compData.x, compData.y);
-
- return drawFlag;
-}
-
void AkosRenderer::markRectAsDirty(Common::Rect rect) {
rect.left -= _vm->_virtscr[kMainVirtScreen].xstart & 7;
rect.right -= _vm->_virtscr[kMainVirtScreen].xstart & 7;
diff --git a/engines/scumm/akos.h b/engines/scumm/akos.h
index 22daca48c86..6ddcf16ce68 100644
--- a/engines/scumm/akos.h
+++ b/engines/scumm/akos.h
@@ -24,7 +24,6 @@
#include "scumm/base-costume.h"
#include "scumm/he/wiz_he.h"
-#include <functional>
namespace Scumm {
@@ -125,15 +124,6 @@ protected:
void byleRLEDecode(ByleRLEData &compData);
byte paintCelByleRLE(int xMoveCur, int yMoveCur);
- byte paintCelByleRLECommon(
- int xMoveCur,
- int yMoveCur,
- int numColors,
- int scaletableSize,
- ByleRLEData &compData,
- std::function<void(const Common::Rect &)> markAsDirty,
- bool &decode);
-
byte paintCelCDATRLE(int xMoveCur, int yMoveCur);
byte paintCelMajMin(int xMoveCur, int yMoveCur);
byte paintCelTRLE(int actor, int drawToBack, int celX, int celY, int celWidth, int celHeight, byte tcolor, const byte *shadowTablePtr, int32 specialRenderFlags);
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index 31ae5378b8c..02fbc60492f 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -57,6 +57,240 @@ byte BaseCostumeRenderer::drawCostume(const VirtScreen &vs, int numStrips, const
return result;
}
+byte BaseCostumeRenderer::paintCelByleRLECommon(
+ int xMoveCur,
+ int yMoveCur,
+ int numColors,
+ int scaletableSize,
+ bool amiOrPcEngCost,
+ bool c64Cost,
+ ByleRLEData &compData,
+ std::function<void(const Common::Rect &)> markAsDirty,
+ bool &decode) {
+
+ bool actorIsScaled;
+ int i, j;
+ int linesToSkip = 0, startScaleIndexX, startScaleIndexY;
+ Common::Rect rect;
+ int step;
+ byte drawFlag = 1;
+
+ // Setup color decoding variables
+ if (numColors == 32) {
+ compData.mask = 7;
+ compData.shr = 3;
+ } else if (numColors == 64) {
+ compData.mask = 3;
+ compData.shr = 2;
+ } else {
+ compData.mask = 15;
+ compData.shr = 4;
+ }
+
+ actorIsScaled = (_scaleX != 0xFF) || (_scaleY != 0xFF);
+
+ compData.boundsRect.left = 0;
+ compData.boundsRect.top = 0;
+ compData.boundsRect.right = _out.w;
+ compData.boundsRect.bottom = _out.h;
+
+ if (actorIsScaled) {
+
+ /* Scale direction */
+ compData.scaleXStep = -1;
+ if (xMoveCur < 0) {
+ xMoveCur = -xMoveCur;
+ compData.scaleXStep = 1;
+ }
+
+ if (_mirror) {
+ /* Adjust X position */
+ startScaleIndexX = j = scaletableSize - xMoveCur;
+ for (i = 0; i < xMoveCur; i++) {
+ if (compData.scaleTable[j++] < _scaleX)
+ compData.x -= compData.scaleXStep;
+ }
+
+ rect.left = rect.right = compData.x;
+
+ j = startScaleIndexX;
+ for (i = 0; i < _width; i++) {
+ if (rect.right < 0) {
+ linesToSkip++;
+ startScaleIndexX = j;
+ }
+ if (compData.scaleTable[j++] < _scaleX)
+ rect.right++;
+ }
+ } else {
+ /* No mirror */
+ /* Adjust X position */
+ startScaleIndexX = j = scaletableSize + xMoveCur;
+ for (i = 0; i < xMoveCur; i++) {
+ if (compData.scaleTable[j--] < _scaleX)
+ compData.x += compData.scaleXStep;
+ }
+
+ rect.left = rect.right = compData.x;
+
+ j = startScaleIndexX;
+ for (i = 0; i < _width; i++) {
+ if (rect.left >= compData.boundsRect.right) {
+ startScaleIndexX = j;
+ linesToSkip++;
+ }
+ if (compData.scaleTable[j--] < _scaleX)
+ rect.left--;
+ }
+ }
+
+ if (linesToSkip)
+ linesToSkip--;
+
+ step = -1;
+ if (yMoveCur < 0) {
+ yMoveCur = -yMoveCur;
+ step = -step;
+ }
+
+ startScaleIndexY = scaletableSize - yMoveCur;
+ for (i = 0; i < yMoveCur; i++) {
+ // WORKAROUND: Backyard Basketball sends out yMoveCur values higher than 128!
+ // This triggers ASAN, because it tries to reach a negative index of compData.scaleTable[].
+ if (startScaleIndexY < 0) {
+ debug(8, "AkosRenderer::paintCelByleRLE(): Negative startScaleIndexY: %d; actor (%d), scaletableSize (%d), yMoveCur (%d), working around it...",
+ _actorID, startScaleIndexY, scaletableSize, yMoveCur);
+ if (compData.scaleTable[0] < _scaleY)
+ compData.y -= step;
+
+ startScaleIndexY++;
+ continue;
+ }
+
+ if (compData.scaleTable[startScaleIndexY++] < _scaleY)
+ compData.y -= step;
+ }
+
+ rect.top = rect.bottom = compData.y;
+ startScaleIndexY = scaletableSize - yMoveCur;
+ for (i = 0; i < _height; i++) {
+ // WORKAROUND: See above...
+ if (startScaleIndexY < 0) {
+ if (compData.scaleTable[0] < _scaleY)
+ rect.bottom++;
+
+ startScaleIndexY++;
+ continue;
+ }
+
+ if (compData.scaleTable[startScaleIndexY++] < _scaleY)
+ rect.bottom++;
+ }
+
+ startScaleIndexY = scaletableSize - yMoveCur;
+ } else {
+ if (!_mirror)
+ xMoveCur = -xMoveCur;
+
+ compData.x += xMoveCur;
+ compData.y += yMoveCur;
+
+ if (_mirror) {
+ rect.left = compData.x;
+ rect.right = compData.x + _width;
+ } else {
+ rect.left = compData.x - _width;
+ rect.right = compData.x;
+ }
+
+ rect.top = compData.y;
+ rect.bottom = rect.top + _height;
+
+ startScaleIndexX = scaletableSize;
+ startScaleIndexY = scaletableSize;
+ }
+
+ compData.scaleXIndex = startScaleIndexX;
+ compData.scaleYIndex = startScaleIndexY;
+ compData.skipWidth = _width;
+ compData.scaleXStep = _mirror ? 1 : -1;
+
+ markAsDirty(rect);
+ if (!decode)
+ return 0;
+
+ if (rect.top >= compData.boundsRect.bottom || rect.bottom <= compData.boundsRect.top) {
+ decode = false;
+ return 0;
+ }
+
+ if (rect.left >= compData.boundsRect.right || rect.right <= compData.boundsRect.left) {
+ decode = false;
+ return 0;
+ }
+
+ compData.repLen = 0;
+
+ if (_mirror) {
+ if (!actorIsScaled)
+ linesToSkip = compData.boundsRect.left - compData.x;
+ if (linesToSkip > 0) {
+ compData.skipWidth -= linesToSkip;
+ skipCelLines(compData, linesToSkip);
+ compData.x = compData.boundsRect.left;
+ } else {
+ linesToSkip = rect.right - compData.boundsRect.right;
+ if (linesToSkip <= 0) {
+ drawFlag = 2;
+ } else {
+ compData.skipWidth -= linesToSkip;
+ }
+ }
+ } else {
+ if (!actorIsScaled)
+ linesToSkip = rect.right - compData.boundsRect.right + 1;
+ if (linesToSkip > 0) {
+ compData.skipWidth -= linesToSkip;
+ skipCelLines(compData, linesToSkip);
+ compData.x = compData.boundsRect.right - 1;
+ } else {
+ linesToSkip = (compData.boundsRect.left - 1) - rect.left;
+ if (linesToSkip <= 0)
+ drawFlag = 2;
+ else
+ compData.skipWidth -= linesToSkip;
+ }
+ }
+
+ if (compData.skipWidth <= 0 || _height <= 0) {
+ decode = false;
+ return 0;
+ }
+
+ if (rect.left < compData.boundsRect.left)
+ rect.left = compData.boundsRect.left;
+
+ if (rect.top < compData.boundsRect.top)
+ rect.top = compData.boundsRect.top;
+
+ if (rect.top > compData.boundsRect.bottom)
+ rect.top = compData.boundsRect.bottom;
+
+ if (rect.bottom > compData.boundsRect.bottom)
+ rect.bottom = compData.boundsRect.bottom;
+
+ if (_drawTop > rect.top)
+ _drawTop = rect.top;
+ if (_drawBottom < rect.bottom)
+ _drawBottom = rect.bottom;
+
+ compData.width = _out.w;
+ compData.height = _out.h;
+ compData.destPtr = (byte *)_out.getBasePtr(compData.x, compData.y);
+
+ return drawFlag;
+}
+
void BaseCostumeRenderer::skipCelLines(ByleRLEData &compData, int num) {
num *= _height;
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index e45d6c5c90c..dae4ef4a907 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -25,6 +25,8 @@
#include "common/scummsys.h"
#include "scumm/actor.h" // for CostumeData
+#include <functional>
+
namespace Scumm {
#include "common/pack-start.h" // START STRUCT PACKING
@@ -157,6 +159,17 @@ public:
protected:
virtual byte drawLimb(const Actor *a, int limb) = 0;
+ virtual byte paintCelByleRLECommon(
+ int xMoveCur,
+ int yMoveCur,
+ int numColors,
+ int scaletableSize,
+ bool amiOrPcEngCost,
+ bool c64Cost,
+ ByleRLEData &compData,
+ std::function<void(const Common::Rect &)> markAsDirty,
+ bool &decode);
+
void skipCelLines(ByleRLEData &compData, int num);
};
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index ebef1f54f1f..4896c6fb4e2 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -525,6 +525,7 @@ void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
maskbit = revBitMask(compData.x & 7);
mask = compData.maskPtr + compData.x / 8;
+ // see https://wiki.scummvm.org/index.php/SCUMM/Technical_Reference/Costume_resources#1.3_RLE_compression
if (len)
goto StartPos;
@@ -544,7 +545,7 @@ void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
if (color && !masked) {
if (_shadowMode & 0x20) {
pcolor = _shadowTable[*dst];
- } else {
+ } else { // _shadowMode == 0
pcolor = _palette[color];
if (pcolor == 13 && _shadowTable)
pcolor = _shadowTable[*dst];
diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h
index abf49fb5919..923af43de10 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -23,7 +23,6 @@
#define SCUMM_COSTUME_H
#include "scumm/base-costume.h"
-#include <functional>
namespace Scumm {
class ClassicCostumeLoader : public BaseCostumeLoader {
@@ -110,7 +109,7 @@ protected:
bool c64Cost,
ByleRLEData &compData,
std::function<void(const Common::Rect &)> markAsDirty,
- bool &decode);
+ bool &decode) override;
void byleRLEDecode_C64(ByleRLEData &compData, int actor);
void byleRLEDecode(ByleRLEData &compData);
Commit: a05a3f57976f9a645b8a77610b279e4dc7a1eb53
https://github.com/scummvm/scummvm/commit/a05a3f57976f9a645b8a77610b279e4dc7a1eb53
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Make startScaleIndexY handling closer to startScaleIndexX
This makes it again a bit a closer to ClassicCostumeRenderer and as a
bonus, there's no need to recalculate startScaleIndexY every time.
Changed paths:
engines/scumm/base-costume.cpp
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index 02fbc60492f..93658072c16 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -153,41 +153,40 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
step = -step;
}
- startScaleIndexY = scaletableSize - yMoveCur;
+ startScaleIndexY = j = scaletableSize - yMoveCur;
for (i = 0; i < yMoveCur; i++) {
// WORKAROUND: Backyard Basketball sends out yMoveCur values higher than 128!
// This triggers ASAN, because it tries to reach a negative index of compData.scaleTable[].
- if (startScaleIndexY < 0) {
+ if (j < 0) {
debug(8, "AkosRenderer::paintCelByleRLE(): Negative startScaleIndexY: %d; actor (%d), scaletableSize (%d), yMoveCur (%d), working around it...",
- _actorID, startScaleIndexY, scaletableSize, yMoveCur);
+ _actorID, j, scaletableSize, yMoveCur);
if (compData.scaleTable[0] < _scaleY)
compData.y -= step;
- startScaleIndexY++;
+ j++;
continue;
}
- if (compData.scaleTable[startScaleIndexY++] < _scaleY)
+ if (compData.scaleTable[j++] < _scaleY)
compData.y -= step;
}
rect.top = rect.bottom = compData.y;
- startScaleIndexY = scaletableSize - yMoveCur;
+
+ j = startScaleIndexY;
for (i = 0; i < _height; i++) {
// WORKAROUND: See above...
- if (startScaleIndexY < 0) {
+ if (j < 0) {
if (compData.scaleTable[0] < _scaleY)
rect.bottom++;
- startScaleIndexY++;
+ j++;
continue;
}
- if (compData.scaleTable[startScaleIndexY++] < _scaleY)
+ if (compData.scaleTable[j++] < _scaleY)
rect.bottom++;
}
-
- startScaleIndexY = scaletableSize - yMoveCur;
} else {
if (!_mirror)
xMoveCur = -xMoveCur;
Commit: 4525d8300fc35f1ff00d9dc3e5576a5f80f15e7c
https://github.com/scummvm/scummvm/commit/4525d8300fc35f1ff00d9dc3e5576a5f80f15e7c
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Proper scaling fix for Backyard Basketball
This is the definite closure for ticket #2729: "I also guess that we
have the same potential problem in the AKOS renderer. At least in
code1_genericDecode()."
Commit 8d23d0799dcacdbc68a13094174f9c5dadb6b3ca fixed one specific
behavior (negative values) however I believe it is just a side effect of
not handling the small costume table in AkosRenderer the same way as in
it's done in ClassicCostumeRenderer.
ClassicCostumeRenderer still uses the byte variables and not the mask
but I put the mask value there already for future use.
Changed paths:
engines/scumm/akos.cpp
engines/scumm/base-costume.cpp
engines/scumm/base-costume.h
engines/scumm/costume.cpp
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index b02621ea06d..1e130add684 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -502,7 +502,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
byte len, maskbit;
int lastColumnX, y;
uint16 color, height, pcolor;
- const byte *scaleytab;
+ int scaleIndexY;
bool masked;
lastColumnX = -1;
@@ -513,7 +513,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
color = compData.repColor;
height = _height;
- scaleytab = &compData.scaleTable[MAX<int>(0, compData.scaleYIndex)]; // Avoid invalid mem reads in Basketball...
+ scaleIndexY = compData.scaleYIndex;
maskbit = revBitMask(compData.x & 7);
mask = compData.maskPtr + compData.x / 8;
@@ -528,7 +528,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
len = *src++;
do {
- if (_scaleY == 255 || *scaleytab++ < _scaleY) {
+ if (_scaleY == 255 || compData.scaleTable[scaleIndexY++ & compData.scaleIndexMask] < _scaleY) {
if (_actorHitMode) {
if (color && y == _actorHitY && compData.x == _actorHitX) {
_actorHitResult = true;
@@ -595,7 +595,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
height = _height;
y = compData.y;
- scaleytab = &compData.scaleTable[MAX<int>(0, compData.scaleYIndex)]; // Avoid invalid mem reads in Basketball...
+ scaleIndexY = compData.scaleYIndex;
lastColumnX = compData.x;
if (_scaleX == 255 || compData.scaleTable[compData.scaleXIndex] < _scaleX) {
@@ -606,7 +606,7 @@ void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
compData.destPtr += compData.scaleXStep * _vm->_bytesPerPixel;
}
- compData.scaleXIndex += compData.scaleXStep;
+ compData.scaleXIndex = (compData.scaleXIndex + compData.scaleXStep) & compData.scaleIndexMask;
dst = compData.destPtr;
mask = compData.maskPtr + compData.x / 8;
}
@@ -729,6 +729,9 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
compData.x = _actorX;
compData.y = _actorY;
+ // see ClassicCostumeRenderer::paintCelByleRLE, for smallCostumeScaleTable the same wrapping applies
+ compData.scaleIndexMask = (_vm->_game.heversion >= 61) ? 0xff : -1;
+
bool decode = true;
const auto markAsDirty = [this, &compData, &decode](const Common::Rect &rect) {
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index 93658072c16..f692453934a 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -105,9 +105,9 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
if (_mirror) {
/* Adjust X position */
- startScaleIndexX = j = scaletableSize - xMoveCur;
+ startScaleIndexX = j = (scaletableSize - xMoveCur) & compData.scaleIndexMask;
for (i = 0; i < xMoveCur; i++) {
- if (compData.scaleTable[j++] < _scaleX)
+ if (compData.scaleTable[j++ & compData.scaleIndexMask] < _scaleX)
compData.x -= compData.scaleXStep;
}
@@ -119,15 +119,15 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
linesToSkip++;
startScaleIndexX = j;
}
- if (compData.scaleTable[j++] < _scaleX)
+ if (compData.scaleTable[j++ & compData.scaleIndexMask] < _scaleX)
rect.right++;
}
} else {
/* No mirror */
/* Adjust X position */
- startScaleIndexX = j = scaletableSize + xMoveCur;
+ startScaleIndexX = j = (scaletableSize + xMoveCur) & compData.scaleIndexMask;
for (i = 0; i < xMoveCur; i++) {
- if (compData.scaleTable[j--] < _scaleX)
+ if (compData.scaleTable[j-- & compData.scaleIndexMask] < _scaleX)
compData.x += compData.scaleXStep;
}
@@ -139,7 +139,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
startScaleIndexX = j;
linesToSkip++;
}
- if (compData.scaleTable[j--] < _scaleX)
+ if (compData.scaleTable[j-- & compData.scaleIndexMask] < _scaleX)
rect.left--;
}
}
@@ -153,21 +153,9 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
step = -step;
}
- startScaleIndexY = j = scaletableSize - yMoveCur;
+ startScaleIndexY = j = (scaletableSize - yMoveCur) & compData.scaleIndexMask;
for (i = 0; i < yMoveCur; i++) {
- // WORKAROUND: Backyard Basketball sends out yMoveCur values higher than 128!
- // This triggers ASAN, because it tries to reach a negative index of compData.scaleTable[].
- if (j < 0) {
- debug(8, "AkosRenderer::paintCelByleRLE(): Negative startScaleIndexY: %d; actor (%d), scaletableSize (%d), yMoveCur (%d), working around it...",
- _actorID, j, scaletableSize, yMoveCur);
- if (compData.scaleTable[0] < _scaleY)
- compData.y -= step;
-
- j++;
- continue;
- }
-
- if (compData.scaleTable[j++] < _scaleY)
+ if (compData.scaleTable[j++ & compData.scaleIndexMask] < _scaleY)
compData.y -= step;
}
@@ -175,16 +163,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
j = startScaleIndexY;
for (i = 0; i < _height; i++) {
- // WORKAROUND: See above...
- if (j < 0) {
- if (compData.scaleTable[0] < _scaleY)
- rect.bottom++;
-
- j++;
- continue;
- }
-
- if (compData.scaleTable[j++] < _scaleY)
+ if (compData.scaleTable[j++ & compData.scaleIndexMask] < _scaleY)
rect.bottom++;
}
} else {
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index dae4ef4a907..a2dcf679538 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -125,6 +125,7 @@ public:
// These ones aren't accessed from ARM code.
Common::Rect boundsRect;
int scaleXIndex, scaleYIndex;
+ int scaleIndexMask;
};
BaseCostumeRenderer(ScummEngine *scumm) {
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 4896c6fb4e2..3943a5dd96c 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -104,6 +104,12 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
if (_vm->_game.version <= 1)
compData.y += 1;
+ // It's possible that the scale indexes will overflow and wrap
+ // around to zero, so it's important that we use the same
+ // method of accessing it both when calculating the size of the
+ // scaled costume, and when drawing it. See bug #2729.
+ compData.scaleIndexMask = 0xff;
+
bool decode = true;
const auto markAsDirty = [this](const Common::Rect &rect) {
Commit: c605127bd10463f0d54462b3f1fbcb56accfc138
https://github.com/scummvm/scummvm/commit/c605127bd10463f0d54462b3f1fbcb56accfc138
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: ClassicCostumeRenderer::paintCelByleRLECommon is not needed anymore
Differences between ClassicCostumeRenderer and AkosRenderer are
mentioned in the comments. They should be harmless but the "+1" in
AkosRenderer is suspicious, looks like a bug/typo?
_scaleIndexX and _scaleIndexY had to be replaced with compData values
and mask.
Changed paths:
engines/scumm/base-costume.cpp
engines/scumm/base-costume.h
engines/scumm/costume.cpp
engines/scumm/costume.h
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index f692453934a..a3bf8de2ec9 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -213,9 +213,11 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
if (!actorIsScaled)
linesToSkip = compData.boundsRect.left - compData.x;
if (linesToSkip > 0) {
- compData.skipWidth -= linesToSkip;
- skipCelLines(compData, linesToSkip);
- compData.x = compData.boundsRect.left;
+ if (!amiOrPcEngCost && !c64Cost) {
+ compData.skipWidth -= linesToSkip;
+ skipCelLines(compData, linesToSkip);
+ compData.x = compData.boundsRect.left;
+ }
} else {
linesToSkip = rect.right - compData.boundsRect.right;
if (linesToSkip <= 0) {
@@ -226,13 +228,19 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
}
} else {
if (!actorIsScaled)
- linesToSkip = rect.right - compData.boundsRect.right + 1;
+ linesToSkip = rect.right - compData.boundsRect.right; // AkosRenderer had +1 here, weird
if (linesToSkip > 0) {
- compData.skipWidth -= linesToSkip;
- skipCelLines(compData, linesToSkip);
- compData.x = compData.boundsRect.right - 1;
+ if (!amiOrPcEngCost && !c64Cost) {
+ compData.skipWidth -= linesToSkip;
+ skipCelLines(compData, linesToSkip);
+ compData.x = compData.boundsRect.right - 1;
+ }
} else {
- linesToSkip = (compData.boundsRect.left - 1) - rect.left;
+ // V1 games uses 8 x 8 pixels for actors
+ if (c64Cost)
+ linesToSkip = (compData.boundsRect.left - 8) - rect.left;
+ else
+ linesToSkip = (compData.boundsRect.left - 1) - rect.left;
if (linesToSkip <= 0)
drawFlag = 2;
else
@@ -240,7 +248,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
}
}
- if (compData.skipWidth <= 0 || _height <= 0) {
+ if (compData.skipWidth <= 0 || _height <= 0) { // AkosRenderer added the second check (|| _height <= 0)
decode = false;
return 0;
}
@@ -262,6 +270,11 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
if (_drawBottom < rect.bottom)
_drawBottom = rect.bottom;
+ if (_height + rect.top >= 256) { // AkosRenderer didn't do this check
+ decode = false;
+ return 2;
+ }
+
compData.width = _out.w;
compData.height = _out.h;
compData.destPtr = (byte *)_out.getBasePtr(compData.x, compData.y);
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index a2dcf679538..1d5c5e42371 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -160,7 +160,7 @@ public:
protected:
virtual byte drawLimb(const Actor *a, int limb) = 0;
- virtual byte paintCelByleRLECommon(
+ byte paintCelByleRLECommon(
int xMoveCur,
int yMoveCur,
int numColors,
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 3943a5dd96c..bf5ed3fbbbe 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -151,229 +151,6 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
return drawFlag;
}
-byte ClassicCostumeRenderer::paintCelByleRLECommon(
- int xMoveCur,
- int yMoveCur,
- int numColors,
- int scaletableSize,
- bool amiOrPcEngCost,
- bool c64Cost,
- ByleRLEData &compData,
- std::function<void (const Common::Rect &)> markAsDirty,
- bool &decode) {
-
- bool actorIsScaled;
- int i;
- int linesToSkip = 0;
- byte startScaleIndexX;
- Common::Rect rect;
- int step;
- byte drawFlag = 1;
-
- if (numColors == 32) {
- compData.mask = 7;
- compData.shr = 3;
- } else {
- compData.mask = 15;
- compData.shr = 4;
- }
-
- actorIsScaled = (_scaleX != 0xFF) || (_scaleY != 0xFF);
-
- compData.boundsRect.left = 0;
- compData.boundsRect.top = 0;
- compData.boundsRect.right = _out.w;
- compData.boundsRect.bottom = _out.h;
-
- if (actorIsScaled) {
-
- /* Scale direction */
- compData.scaleXStep = -1;
- if (xMoveCur < 0) {
- xMoveCur = -xMoveCur;
- compData.scaleXStep = 1;
- }
-
- // It's possible that the scale indexes will overflow and wrap
- // around to zero, so it's important that we use the same
- // method of accessing it both when calculating the size of the
- // scaled costume, and when drawing it. See bug #2729.
-
- if (_mirror) {
- /* Adjust X position */
- startScaleIndexX = _scaleIndexX = scaletableSize - xMoveCur;
- for (i = 0; i < xMoveCur; i++) {
- if (compData.scaleTable[_scaleIndexX++] < _scaleX)
- compData.x -= compData.scaleXStep;
- }
-
- rect.left = rect.right = compData.x;
-
- _scaleIndexX = startScaleIndexX;
- for (i = 0; i < _width; i++) {
- if (rect.right < 0) {
- linesToSkip++;
- startScaleIndexX = _scaleIndexX;
- }
- if (compData.scaleTable[_scaleIndexX++] < _scaleX)
- rect.right++;
- }
- } else {
- /* No mirror */
- /* Adjust X position */
- startScaleIndexX = _scaleIndexX = scaletableSize + xMoveCur;
- for (i = 0; i < xMoveCur; i++) {
- if (compData.scaleTable[_scaleIndexX--] < _scaleX)
- compData.x += compData.scaleXStep;
- }
-
- rect.left = rect.right = compData.x;
-
- _scaleIndexX = startScaleIndexX;
- for (i = 0; i < _width; i++) {
- if (rect.left >= compData.boundsRect.right) {
- startScaleIndexX = _scaleIndexX;
- linesToSkip++;
- }
- if (compData.scaleTable[_scaleIndexX--] < _scaleX)
- rect.left--;
- }
- }
- _scaleIndexX = startScaleIndexX;
-
- if (linesToSkip)
- linesToSkip--;
-
- step = -1;
- if (yMoveCur < 0) {
- yMoveCur = -yMoveCur;
- step = -step;
- }
-
- _scaleIndexY = scaletableSize - yMoveCur;
- for (i = 0; i < yMoveCur; i++) {
- if (compData.scaleTable[_scaleIndexY++] < _scaleY)
- compData.y -= step;
- }
-
- rect.top = rect.bottom = compData.y;
- _scaleIndexY = scaletableSize - yMoveCur;
- for (i = 0; i < _height; i++) {
- if (compData.scaleTable[_scaleIndexY++] < _scaleY)
- rect.bottom++;
- }
-
- _scaleIndexY = scaletableSize - yMoveCur;
- } else {
- if (!_mirror)
- xMoveCur = -xMoveCur;
-
- compData.x += xMoveCur;
- compData.y += yMoveCur;
-
- if (_mirror) {
- rect.left = compData.x;
- rect.right = compData.x + _width;
- } else {
- rect.left = compData.x - _width;
- rect.right = compData.x;
- }
-
- rect.top = compData.y;
- rect.bottom = rect.top + _height;
-
- }
-
- compData.skipWidth = _width;
- compData.scaleXStep = _mirror ? 1 : -1;
-
- markAsDirty(rect);
-
- if (rect.top >= compData.boundsRect.bottom || rect.bottom <= compData.boundsRect.top) {
- decode = false;
- return 0;
- }
-
- if (rect.left >= compData.boundsRect.right || rect.right <= compData.boundsRect.left) {
- decode = false;
- return 0;
- }
-
- compData.repLen = 0;
-
- if (_mirror) {
- if (!actorIsScaled)
- linesToSkip = compData.boundsRect.left - compData.x;
- if (linesToSkip > 0) {
- if (!amiOrPcEngCost && !c64Cost) {
- compData.skipWidth -= linesToSkip;
- skipCelLines(compData, linesToSkip);
- compData.x = compData.boundsRect.left;
- }
- } else {
- linesToSkip = rect.right - compData.boundsRect.right;
- if (linesToSkip <= 0) {
- drawFlag = 2;
- } else {
- compData.skipWidth -= linesToSkip;
- }
- }
- } else {
- if (!actorIsScaled)
- linesToSkip = rect.right - compData.boundsRect.right;
- if (linesToSkip > 0) {
- if (!amiOrPcEngCost && !c64Cost) {
- compData.skipWidth -= linesToSkip;
- skipCelLines(compData, linesToSkip);
- compData.x = compData.boundsRect.right - 1;
- }
- } else {
- // V1 games uses 8 x 8 pixels for actors
- if (c64Cost)
- linesToSkip = (compData.boundsRect.left - 8) - rect.left;
- else
- linesToSkip = (compData.boundsRect.left - 1) - rect.left;
- if (linesToSkip <= 0)
- drawFlag = 2;
- else
- compData.skipWidth -= linesToSkip;
- }
- }
-
- if (compData.skipWidth <= 0) {
- decode = false;
- return 0;
- }
-
- if (rect.left < compData.boundsRect.left)
- rect.left = compData.boundsRect.left;
-
- if (rect.top < compData.boundsRect.top)
- rect.top = compData.boundsRect.top;
-
- if (rect.top > compData.boundsRect.bottom)
- rect.top = compData.boundsRect.bottom;
-
- if (rect.bottom > compData.boundsRect.bottom)
- rect.bottom = compData.boundsRect.bottom;
-
- if (_drawTop > rect.top)
- _drawTop = rect.top;
- if (_drawBottom < rect.bottom)
- _drawBottom = rect.bottom;
-
- if (_height + rect.top >= 256) {
- decode = false;
- return 2;
- }
-
- compData.width = _out.w;
- compData.height = _out.h;
- compData.destPtr = (byte *)_out.getBasePtr(compData.x, compData.y);
-
- return drawFlag;
-}
-
// Skin colors
static const int v1MMActorPalatte1[25] = {
8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
@@ -478,17 +255,18 @@ void ClassicCostumeRenderer::byleRLEDecode_C64(ByleRLEData &compData, int actor)
#define ClassicProc3RendererShadowARM _ClassicProc3RendererShadowARM
#endif
-extern "C" int ClassicProc3RendererShadowARM(int _scaleY,
- ClassicCostumeRenderer::ByleRLEData *compData,
- int pitch,
- const byte *src,
- int height,
- int _scaleX,
- int _scaleIndexX,
- byte *_shadowTable,
- uint16 _palette[32],
- int32 _numStrips,
- int _scaleIndexY);
+extern "C" int ClassicProc3RendererShadowARM(
+ int _scaleY,
+ ClassicCostumeRenderer::ByleRLEData *compData,
+ int pitch,
+ const byte *src,
+ int height,
+ int _scaleX,
+ int _scaleIndexX,
+ byte *_shadowTable,
+ uint16 _palette[32],
+ int32 _numStrips,
+ int _scaleIndexY);
#endif
void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
@@ -497,7 +275,7 @@ void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
byte len, maskbit;
int y;
uint color, height, pcolor;
- byte scaleIndexY;
+ int scaleIndexY;
bool masked;
#ifdef USE_ARM_COSTUME_ASM
@@ -505,17 +283,18 @@ void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
(compData.maskPtr != NULL) &&
(_shadowTable != NULL))
{
- _scaleIndexX = ClassicProc3RendererShadowARM(_scaleY,
- &compData,
- _out.pitch,
- _srcPtr,
- _height,
- _scaleX,
- _scaleIndexX,
- _shadowTable,
- _palette,
- _numStrips,
- _scaleIndexY);
+ compData.scaleXIndex = (byte)ClassicProc3RendererShadowARM(
+ _scaleY,
+ &compData,
+ _out.pitch,
+ _srcPtr,
+ _height,
+ _scaleX,
+ compData.scaleXIndex,
+ _shadowTable,
+ _palette,
+ _numStrips,
+ compData.scaleYIndex);
return;
}
#endif /* USE_ARM_COSTUME_ASM */
@@ -527,7 +306,7 @@ void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
color = compData.repColor;
height = _height;
- scaleIndexY = _scaleIndexY;
+ scaleIndexY = compData.scaleYIndex;
maskbit = revBitMask(compData.x & 7);
mask = compData.maskPtr + compData.x / 8;
@@ -543,7 +322,7 @@ void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
len = *src++;
do {
- if (_scaleY == 255 || compData.scaleTable[scaleIndexY++] < _scaleY) {
+ if (_scaleY == 255 || compData.scaleTable[scaleIndexY++ & compData.scaleIndexMask] < _scaleY) {
masked = (y < compData.boundsRect.top || y >= compData.boundsRect.bottom)
|| (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
|| (compData.maskPtr && (*mask & maskbit));
@@ -568,9 +347,9 @@ void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
height = _height;
y = compData.y;
- scaleIndexY = _scaleIndexY;
+ scaleIndexY = compData.scaleYIndex;
- if (_scaleX == 255 || compData.scaleTable[_scaleIndexX] < _scaleX) {
+ if (_scaleX == 255 || compData.scaleTable[compData.scaleXIndex] < _scaleX) {
compData.x += compData.scaleXStep;
if (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
return;
@@ -584,9 +363,9 @@ void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
// Also valid for all other v4 games (this code is
// also in the executable for LOOM CD).
if (_vm->_game.version == 4) {
- _scaleIndexX++;
+ compData.scaleXIndex = (compData.scaleXIndex + 1) & compData.scaleIndexMask;
} else {
- _scaleIndexX += compData.scaleXStep;
+ compData.scaleXIndex = (compData.scaleXIndex + compData.scaleXStep) & compData.scaleIndexMask;
}
dst = compData.destPtr;
@@ -614,7 +393,7 @@ void ClassicCostumeRenderer::byleRLEDecode_ami(ByleRLEData &compData) {
maskbit = revBitMask(compData.x & 7);
y = compData.y;
oldXpos = compData.x;
- oldScaleIndexX = _scaleIndexX;
+ oldScaleIndexX = compData.scaleXIndex;
// Indy4 Amiga always uses the room map to match colors to the currently
// setup palette in the actor code in the original, thus we need to do this
@@ -630,7 +409,7 @@ void ClassicCostumeRenderer::byleRLEDecode_ami(ByleRLEData &compData) {
if (!len)
len = *src++;
do {
- if (_scaleY == 255 || compData.scaleTable[_scaleIndexY] < _scaleY) {
+ if (_scaleY == 255 || compData.scaleTable[compData.scaleYIndex] < _scaleY) {
masked = (y < 0 || y >= _out.h) || (compData.x < 0 || compData.x >= _out.w) || (compData.maskPtr && (mask[0] & maskbit));
if (color && !masked) {
@@ -640,12 +419,12 @@ void ClassicCostumeRenderer::byleRLEDecode_ami(ByleRLEData &compData) {
*dst = _palette[color];
}
- if (_scaleX == 255 || compData.scaleTable[_scaleIndexX] < _scaleX) {
+ if (_scaleX == 255 || compData.scaleTable[compData.scaleXIndex] < _scaleX) {
compData.x += compData.scaleXStep;
dst += compData.scaleXStep;
maskbit = revBitMask(compData.x & 7);
}
- _scaleIndexX += compData.scaleXStep;
+ compData.scaleXIndex = (compData.scaleXIndex + compData.scaleXStep) & compData.scaleIndexMask;
mask = compData.maskPtr + compData.x / 8;
}
if (!--width) {
@@ -664,8 +443,8 @@ void ClassicCostumeRenderer::byleRLEDecode_ami(ByleRLEData &compData) {
}
width = _width;
compData.x = oldXpos;
- _scaleIndexX = oldScaleIndexX;
- _scaleIndexY++;
+ compData.scaleXIndex = oldScaleIndexX;
+ compData.scaleYIndex = (compData.scaleYIndex + 1) & compData.scaleIndexMask;
}
} while (--len);
} while (1);
diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h
index 923af43de10..dde78685652 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -83,12 +83,10 @@ class ClassicCostumeRenderer : public BaseCostumeRenderer {
protected:
ClassicCostumeLoader _loaded;
- byte _scaleIndexX; /* must wrap at 256 */
- byte _scaleIndexY;
uint16 _palette[32];
public:
- ClassicCostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm), _scaleIndexX(0), _scaleIndexY(0) {
+ ClassicCostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {
memset(_palette, 0, sizeof(_palette));
}
@@ -100,16 +98,6 @@ protected:
byte drawLimb(const Actor *a, int limb) override;
byte paintCelByleRLE(int xMoveCur, int yMoveCur);
- byte paintCelByleRLECommon(
- int xMoveCur,
- int yMoveCur,
- int numColors,
- int scaletableSize,
- bool amiOrPcEngCost,
- bool c64Cost,
- ByleRLEData &compData,
- std::function<void(const Common::Rect &)> markAsDirty,
- bool &decode) override;
void byleRLEDecode_C64(ByleRLEData &compData, int actor);
void byleRLEDecode(ByleRLEData &compData);
Commit: bd9ac565417e5174d4adb3bcbf9611b6bbaab857
https://github.com/scummvm/scummvm/commit/bd9ac565417e5174d4adb3bcbf9611b6bbaab857
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Move AkosRenderer::byleRLEDecode to BaseCostumeRenderer
No functional changes, the function body is identical apart from needed
parameters.
Changed paths:
engines/scumm/akos.cpp
engines/scumm/akos.h
engines/scumm/base-costume.cpp
engines/scumm/base-costume.h
engines/scumm/costume.h
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index 1e130add684..67139da6135 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -496,125 +496,6 @@ byte AkosRenderer::drawLimb(const Actor *a, int limb) {
return result;
}
-void AkosRenderer::byleRLEDecode(ByleRLEData &compData) {
- const byte *mask, *src;
- byte *dst;
- byte len, maskbit;
- int lastColumnX, y;
- uint16 color, height, pcolor;
- int scaleIndexY;
- bool masked;
-
- lastColumnX = -1;
- y = compData.y;
- src = _srcPtr;
- dst = compData.destPtr;
- len = compData.repLen;
- color = compData.repColor;
- height = _height;
-
- scaleIndexY = compData.scaleYIndex;
- maskbit = revBitMask(compData.x & 7);
- mask = compData.maskPtr + compData.x / 8;
-
- if (len)
- goto StartPos;
-
- do {
- len = *src++;
- color = len >> compData.shr;
- len &= compData.mask;
- if (!len)
- len = *src++;
-
- do {
- if (_scaleY == 255 || compData.scaleTable[scaleIndexY++ & compData.scaleIndexMask] < _scaleY) {
- if (_actorHitMode) {
- if (color && y == _actorHitY && compData.x == _actorHitX) {
- _actorHitResult = true;
- return;
- }
- } else {
- masked = (y < compData.boundsRect.top || y >= compData.boundsRect.bottom)
- || (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
- || (compData.maskPtr && (*mask & maskbit));
- bool skipColumn = false;
-
- if (color && !masked) {
- pcolor = _palette[color];
- if (_shadowMode == 1) {
- if (pcolor == 13) {
- // In shadow mode 1 skipColumn works more or less the same way as in shadow
- // mode 3. It is only ever checked and applied if pcolor is 13.
- skipColumn = (lastColumnX == compData.x);
- pcolor = _shadowTable[*dst];
- }
- } else if (_shadowMode == 2) {
- error("AkosRenderer::byleRLEDecode(): shadowMode 2 not implemented."); // TODO
- } else if (_shadowMode == 3) {
- if (_vm->_game.features & GF_16BIT_COLOR) {
- // I add the column skip here, too, although I don't know whether it always
- // applies. But this is the only way to prevent recursive shading of pixels.
- // This might need more fine tuning...
- skipColumn = (lastColumnX == compData.x);
- uint16 srcColor = (pcolor >> 1) & 0x7DEF;
- uint16 dstColor = (READ_UINT16(dst) >> 1) & 0x7DEF;
- pcolor = srcColor + dstColor;
- } else if (_vm->_game.heversion >= 90) {
- // I add the column skip here, too, although I don't know whether it always
- // applies. But this is the only way to prevent recursive shading of pixels.
- // This might need more fine tuning...
- skipColumn = (lastColumnX == compData.x);
- pcolor = (pcolor << 8) + *dst;
- pcolor = _xmap[pcolor];
- } else if (pcolor < 8) {
- // This mode is used in COMI. The column skip only takes place when the shading
- // is actually applied (for pcolor < 8). The skip avoids shading of pixels that
- // already have been shaded.
- skipColumn = (lastColumnX == compData.x);
- pcolor = (pcolor << 8) + *dst;
- pcolor = _shadowTable[pcolor];
- }
- }
- if (!skipColumn) {
- if (_vm->_bytesPerPixel == 2) {
- WRITE_UINT16(dst, pcolor);
- } else {
- *dst = pcolor;
- }
- }
- }
- }
- dst += _out.pitch;
- mask += _numStrips;
- y++;
- }
- if (!--height) {
- if (!--compData.skipWidth)
- return;
- height = _height;
- y = compData.y;
-
- scaleIndexY = compData.scaleYIndex;
- lastColumnX = compData.x;
-
- if (_scaleX == 255 || compData.scaleTable[compData.scaleXIndex] < _scaleX) {
- compData.x += compData.scaleXStep;
- if (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
- return;
- maskbit = revBitMask(compData.x & 7);
- compData.destPtr += compData.scaleXStep * _vm->_bytesPerPixel;
- }
-
- compData.scaleXIndex = (compData.scaleXIndex + compData.scaleXStep) & compData.scaleIndexMask;
- dst = compData.destPtr;
- mask = compData.maskPtr + compData.x / 8;
- }
- StartPos:;
- } while (--len);
- } while (true);
-}
-
const byte bigCostumeScaleTable[768] = {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
@@ -775,7 +656,7 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
compData.maskPtr = _vm->getMaskBuffer(-(_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf);
- byleRLEDecode(compData);
+ byleRLEDecode(compData, _actorHitX, _actorHitY, _actorHitMode ? &_actorHitResult : nullptr, _xmap);
return drawFlag;
}
diff --git a/engines/scumm/akos.h b/engines/scumm/akos.h
index 6ddcf16ce68..dcc37b4489e 100644
--- a/engines/scumm/akos.h
+++ b/engines/scumm/akos.h
@@ -66,8 +66,6 @@ class AkosRenderer : public BaseCostumeRenderer {
protected:
uint16 _codec = 0;
- // actor _palette
- uint16 _palette[256] = {};
bool _useBompPalette;
// pointer to various parts of the costume resource
@@ -121,8 +119,6 @@ public:
protected:
byte drawLimb(const Actor *a, int limb) override;
- void byleRLEDecode(ByleRLEData &compData);
-
byte paintCelByleRLE(int xMoveCur, int yMoveCur);
byte paintCelCDATRLE(int xMoveCur, int yMoveCur);
byte paintCelMajMin(int xMoveCur, int yMoveCur);
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index a3bf8de2ec9..c527942ce77 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -21,7 +21,7 @@
#include "scumm/base-costume.h"
-#include "scumm/costume.h"
+#include "scumm/util.h"
namespace Scumm {
@@ -282,6 +282,125 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
return drawFlag;
}
+void BaseCostumeRenderer::byleRLEDecode(ByleRLEData &compData, int16 actorHitX, int16 actorHitY, bool *actorHitResult, const uint8 *xmap) {
+ const byte *mask, *src;
+ byte *dst;
+ byte len, maskbit;
+ int lastColumnX, y;
+ uint16 color, height, pcolor;
+ int scaleIndexY;
+ bool masked;
+
+ lastColumnX = -1;
+ y = compData.y;
+ src = _srcPtr;
+ dst = compData.destPtr;
+ len = compData.repLen;
+ color = compData.repColor;
+ height = _height;
+
+ scaleIndexY = compData.scaleYIndex;
+ maskbit = revBitMask(compData.x & 7);
+ mask = compData.maskPtr + compData.x / 8;
+
+ if (len)
+ goto StartPos;
+
+ do {
+ len = *src++;
+ color = len >> compData.shr;
+ len &= compData.mask;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (_scaleY == 255 || compData.scaleTable[scaleIndexY++ & compData.scaleIndexMask] < _scaleY) {
+ if (actorHitResult) {
+ if (color && y == actorHitY && compData.x == actorHitX) {
+ *actorHitResult = true;
+ return;
+ }
+ } else {
+ masked = (y < compData.boundsRect.top || y >= compData.boundsRect.bottom)
+ || (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
+ || (compData.maskPtr && (*mask & maskbit));
+ bool skipColumn = false;
+
+ if (color && !masked) {
+ pcolor = _palette[color];
+ if (_shadowMode == 1) {
+ if (pcolor == 13) {
+ // In shadow mode 1 skipColumn works more or less the same way as in shadow
+ // mode 3. It is only ever checked and applied if pcolor is 13.
+ skipColumn = (lastColumnX == compData.x);
+ pcolor = _shadowTable[*dst];
+ }
+ } else if (_shadowMode == 2) {
+ error("AkosRenderer::byleRLEDecode(): shadowMode 2 not implemented."); // TODO
+ } else if (_shadowMode == 3) {
+ if (_vm->_game.features & GF_16BIT_COLOR) {
+ // I add the column skip here, too, although I don't know whether it always
+ // applies. But this is the only way to prevent recursive shading of pixels.
+ // This might need more fine tuning...
+ skipColumn = (lastColumnX == compData.x);
+ uint16 srcColor = (pcolor >> 1) & 0x7DEF;
+ uint16 dstColor = (READ_UINT16(dst) >> 1) & 0x7DEF;
+ pcolor = srcColor + dstColor;
+ } else if (_vm->_game.heversion >= 90) {
+ // I add the column skip here, too, although I don't know whether it always
+ // applies. But this is the only way to prevent recursive shading of pixels.
+ // This might need more fine tuning...
+ skipColumn = (lastColumnX == compData.x);
+ pcolor = (pcolor << 8) + *dst;
+ pcolor = xmap[pcolor];
+ } else if (pcolor < 8) {
+ // This mode is used in COMI. The column skip only takes place when the shading
+ // is actually applied (for pcolor < 8). The skip avoids shading of pixels that
+ // already have been shaded.
+ skipColumn = (lastColumnX == compData.x);
+ pcolor = (pcolor << 8) + *dst;
+ pcolor = _shadowTable[pcolor];
+ }
+ }
+ if (!skipColumn) {
+ if (_vm->_bytesPerPixel == 2) {
+ WRITE_UINT16(dst, pcolor);
+ } else {
+ *dst = pcolor;
+ }
+ }
+ }
+ }
+ dst += _out.pitch;
+ mask += _numStrips;
+ y++;
+ }
+ if (!--height) {
+ if (!--compData.skipWidth)
+ return;
+ height = _height;
+ y = compData.y;
+
+ scaleIndexY = compData.scaleYIndex;
+ lastColumnX = compData.x;
+
+ if (_scaleX == 255 || compData.scaleTable[compData.scaleXIndex] < _scaleX) {
+ compData.x += compData.scaleXStep;
+ if (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
+ return;
+ maskbit = revBitMask(compData.x & 7);
+ compData.destPtr += compData.scaleXStep * _vm->_bytesPerPixel;
+ }
+
+ compData.scaleXIndex = (compData.scaleXIndex + compData.scaleXStep) & compData.scaleIndexMask;
+ dst = compData.destPtr;
+ mask = compData.maskPtr + compData.x / 8;
+ }
+ StartPos:;
+ } while (--len);
+ } while (true);
+}
+
void BaseCostumeRenderer::skipCelLines(ByleRLEData &compData, int num) {
num *= _height;
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index 1d5c5e42371..ccca811ccc0 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -106,6 +106,9 @@ protected:
// width and height of cel to decode
int _width, _height;
+ // actor _palette
+ uint16 _palette[256] = {};
+
public:
struct ByleRLEData {
// Parameters for the original ("V1") costume codec.
@@ -171,6 +174,8 @@ protected:
std::function<void(const Common::Rect &)> markAsDirty,
bool &decode);
+ void byleRLEDecode(ByleRLEData &compData, int16 actorHitX = 0, int16 actorHitY = 0, bool *actorHitResult = nullptr, const uint8 *xmap = nullptr);
+
void skipCelLines(ByleRLEData &compData, int num);
};
diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h
index dde78685652..be84e6a4dfd 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -83,12 +83,8 @@ class ClassicCostumeRenderer : public BaseCostumeRenderer {
protected:
ClassicCostumeLoader _loaded;
- uint16 _palette[32];
-
public:
- ClassicCostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {
- memset(_palette, 0, sizeof(_palette));
- }
+ ClassicCostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {}
void setPalette(uint16 *palette) override;
void setFacing(const Actor *a) override;
Commit: d0aad695489562d8c08cb2e9b3bdd9286f8824cf
https://github.com/scummvm/scummvm/commit/d0aad695489562d8c08cb2e9b3bdd9286f8824cf
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: ClassicCostumeRenderer::byleRLEDecode is not needed anymore
As ClassicCostumeRenderer must not skip columns, I had to separate its _shadowMode from AkosRenderer's.
Changed paths:
engines/scumm/akos.cpp
engines/scumm/base-costume.cpp
engines/scumm/costume.cpp
engines/scumm/costume.h
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index 67139da6135..1c01e48c6b9 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -656,6 +656,9 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
compData.maskPtr = _vm->getMaskBuffer(-(_vm->_virtscr[kMainVirtScreen].xstart & 7), compData.y, _zbuf);
+ // The 5th bit is set by ClassicCostumeRenderer so make sure that there's no collision in the shared code
+ assert(!(_shadowMode & 0x20));
+
byleRLEDecode(compData, _actorHitX, _actorHitY, _actorHitMode ? &_actorHitResult : nullptr, _xmap);
return drawFlag;
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index c527942ce77..e285c8bec31 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -282,6 +282,26 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
return drawFlag;
}
+#ifdef USE_ARM_COSTUME_ASM
+
+#ifndef IPHONE
+#define ClassicProc3RendererShadowARM _ClassicProc3RendererShadowARM
+#endif
+
+extern "C" int ClassicProc3RendererShadowARM(
+ int _scaleY,
+ ClassicCostumeRenderer::ByleRLEData *compData,
+ int pitch,
+ const byte *src,
+ int height,
+ int _scaleX,
+ int _scaleIndexX,
+ byte *_shadowTable,
+ uint16 _palette[32],
+ int32 _numStrips,
+ int _scaleIndexY);
+#endif
+
void BaseCostumeRenderer::byleRLEDecode(ByleRLEData &compData, int16 actorHitX, int16 actorHitY, bool *actorHitResult, const uint8 *xmap) {
const byte *mask, *src;
byte *dst;
@@ -291,6 +311,27 @@ void BaseCostumeRenderer::byleRLEDecode(ByleRLEData &compData, int16 actorHitX,
int scaleIndexY;
bool masked;
+#ifdef USE_ARM_COSTUME_ASM
+ if ((_shadowMode == 0xff) &&
+ (compData.maskPtr != NULL) &&
+ (_shadowTable != NULL))
+ {
+ compData.scaleXIndex = (byte)ClassicProc3RendererShadowARM(
+ _scaleY,
+ &compData,
+ _out.pitch,
+ _srcPtr,
+ _height,
+ _scaleX,
+ compData.scaleXIndex,
+ _shadowTable,
+ _palette,
+ _numStrips,
+ compData.scaleYIndex);
+ return;
+ }
+#endif /* USE_ARM_COSTUME_ASM */
+
lastColumnX = -1;
y = compData.y;
src = _srcPtr;
@@ -328,7 +369,14 @@ void BaseCostumeRenderer::byleRLEDecode(ByleRLEData &compData, int16 actorHitX,
if (color && !masked) {
pcolor = _palette[color];
- if (_shadowMode == 1) {
+ if (_shadowMode == 0xff) {
+ // classic costume, skipColumn = false
+ if (pcolor == 13 && _shadowTable)
+ pcolor = _shadowTable[*dst];
+ } else if (_shadowMode & 0x20) {
+ // classic costume, skipColumn = false
+ pcolor = _shadowTable[*dst];
+ } else if (_shadowMode == 1) {
if (pcolor == 13) {
// In shadow mode 1 skipColumn works more or less the same way as in shadow
// mode 3. It is only ever checked and applied if pcolor is 13.
@@ -392,7 +440,17 @@ void BaseCostumeRenderer::byleRLEDecode(ByleRLEData &compData, int16 actorHitX,
compData.destPtr += compData.scaleXStep * _vm->_bytesPerPixel;
}
- compData.scaleXIndex = (compData.scaleXIndex + compData.scaleXStep) & compData.scaleIndexMask;
+ // From MONKEY1 EGA disasm: we only increment by 1.
+ // This accurately produces the original wonky scaling
+ // for the floppy editions of Monkey Island 1.
+ // Also valid for all other v4 games (this code is
+ // also in the executable for LOOM CD).
+ if (_vm->_game.version == 4) {
+ compData.scaleXIndex = (compData.scaleXIndex + 1) & compData.scaleIndexMask;
+ } else {
+ compData.scaleXIndex = (compData.scaleXIndex + compData.scaleXStep) & compData.scaleIndexMask;
+ }
+
dst = compData.destPtr;
mask = compData.maskPtr + compData.x / 8;
}
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index bf5ed3fbbbe..c5ef15aa8c9 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -137,6 +137,12 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
compData.maskPtr = _vm->getMaskBuffer(0, compData.y, _zbuf);
+ // temporarily replace _shadowMode to distinguish from AkosRenderer's _shadowMode
+ byte oldShadowMode = _shadowMode;
+ if (!(_shadowMode & 0x20)) {
+ _shadowMode = 0xff;
+ }
+
if (c64Cost) {
// The v1 costume renderer needs the actor number, which is
// the same thing as the costume renderer's _actorID.
@@ -148,6 +154,8 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
else
byleRLEDecode(compData);
+ _shadowMode = oldShadowMode;
+
return drawFlag;
}
@@ -249,133 +257,6 @@ void ClassicCostumeRenderer::byleRLEDecode_C64(ByleRLEData &compData, int actor)
#undef LINE
#undef MASK_AT
-#ifdef USE_ARM_COSTUME_ASM
-
-#ifndef IPHONE
-#define ClassicProc3RendererShadowARM _ClassicProc3RendererShadowARM
-#endif
-
-extern "C" int ClassicProc3RendererShadowARM(
- int _scaleY,
- ClassicCostumeRenderer::ByleRLEData *compData,
- int pitch,
- const byte *src,
- int height,
- int _scaleX,
- int _scaleIndexX,
- byte *_shadowTable,
- uint16 _palette[32],
- int32 _numStrips,
- int _scaleIndexY);
-#endif
-
-void ClassicCostumeRenderer::byleRLEDecode(ByleRLEData &compData) {
- const byte *mask, *src;
- byte *dst;
- byte len, maskbit;
- int y;
- uint color, height, pcolor;
- int scaleIndexY;
- bool masked;
-
-#ifdef USE_ARM_COSTUME_ASM
- if (((_shadowMode & 0x20) == 0) &&
- (compData.maskPtr != NULL) &&
- (_shadowTable != NULL))
- {
- compData.scaleXIndex = (byte)ClassicProc3RendererShadowARM(
- _scaleY,
- &compData,
- _out.pitch,
- _srcPtr,
- _height,
- _scaleX,
- compData.scaleXIndex,
- _shadowTable,
- _palette,
- _numStrips,
- compData.scaleYIndex);
- return;
- }
-#endif /* USE_ARM_COSTUME_ASM */
-
- y = compData.y;
- src = _srcPtr;
- dst = compData.destPtr;
- len = compData.repLen;
- color = compData.repColor;
- height = _height;
-
- scaleIndexY = compData.scaleYIndex;
- maskbit = revBitMask(compData.x & 7);
- mask = compData.maskPtr + compData.x / 8;
-
- // see https://wiki.scummvm.org/index.php/SCUMM/Technical_Reference/Costume_resources#1.3_RLE_compression
- if (len)
- goto StartPos;
-
- do {
- len = *src++;
- color = len >> compData.shr;
- len &= compData.mask;
- if (!len)
- len = *src++;
-
- do {
- if (_scaleY == 255 || compData.scaleTable[scaleIndexY++ & compData.scaleIndexMask] < _scaleY) {
- masked = (y < compData.boundsRect.top || y >= compData.boundsRect.bottom)
- || (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
- || (compData.maskPtr && (*mask & maskbit));
-
- if (color && !masked) {
- if (_shadowMode & 0x20) {
- pcolor = _shadowTable[*dst];
- } else { // _shadowMode == 0
- pcolor = _palette[color];
- if (pcolor == 13 && _shadowTable)
- pcolor = _shadowTable[*dst];
- }
- *dst = pcolor;
- }
- dst += _out.pitch;
- mask += _numStrips;
- y++;
- }
- if (!--height) {
- if (!--compData.skipWidth)
- return;
- height = _height;
- y = compData.y;
-
- scaleIndexY = compData.scaleYIndex;
-
- if (_scaleX == 255 || compData.scaleTable[compData.scaleXIndex] < _scaleX) {
- compData.x += compData.scaleXStep;
- if (compData.x < compData.boundsRect.left || compData.x >= compData.boundsRect.right)
- return;
- maskbit = revBitMask(compData.x & 7);
- compData.destPtr += compData.scaleXStep;
- }
-
- // From MONKEY1 EGA disasm: we only increment by 1.
- // This accurately produces the original wonky scaling
- // for the floppy editions of Monkey Island 1.
- // Also valid for all other v4 games (this code is
- // also in the executable for LOOM CD).
- if (_vm->_game.version == 4) {
- compData.scaleXIndex = (compData.scaleXIndex + 1) & compData.scaleIndexMask;
- } else {
- compData.scaleXIndex = (compData.scaleXIndex + compData.scaleXStep) & compData.scaleIndexMask;
- }
-
- dst = compData.destPtr;
- mask = compData.maskPtr + compData.x / 8;
- }
- StartPos:;
- } while (--len);
- } while (1);
-}
-
void ClassicCostumeRenderer::byleRLEDecode_ami(ByleRLEData &compData) {
const byte *mask, *src;
byte *dst;
diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h
index be84e6a4dfd..d1ddb6a2b37 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -96,7 +96,6 @@ protected:
byte paintCelByleRLE(int xMoveCur, int yMoveCur);
void byleRLEDecode_C64(ByleRLEData &compData, int actor);
- void byleRLEDecode(ByleRLEData &compData);
void byleRLEDecode_ami(ByleRLEData &compData);
void byleRLEDecode_PCEngine(ByleRLEData &compData);
};
Commit: ff7935c0fe89e8e90c7217fd25c7af5d84aaed3a
https://github.com/scummvm/scummvm/commit/ff7935c0fe89e8e90c7217fd25c7af5d84aaed3a
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Replace lambdas & std::function with virtual ones
This makes ScummVM happy as std::function tends to drag a lot of
forbidden symbols in.
Changed paths:
engines/scumm/akos.cpp
engines/scumm/akos.h
engines/scumm/base-costume.cpp
engines/scumm/base-costume.h
engines/scumm/costume.cpp
engines/scumm/costume.h
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index 1c01e48c6b9..6dff81023e8 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -615,31 +615,6 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
bool decode = true;
- const auto markAsDirty = [this, &compData, &decode](const Common::Rect &rect) {
- if (_vm->_game.heversion >= 71) {
- if (_clipOverride.right > _clipOverride.left && _clipOverride.bottom > _clipOverride.top) {
- compData.boundsRect = _clipOverride;
- compData.boundsRect.right += 1;
- compData.boundsRect.bottom += 1;
-
- compData.boundsRect.right = CLIP<int16>(compData.boundsRect.right, 0, _vm->_screenWidth);
- compData.boundsRect.bottom = CLIP<int16>(compData.boundsRect.bottom, 0, _vm->_screenHeight);
- }
- }
-
- if (_actorHitMode) {
- if (_actorHitX < rect.left || _actorHitX >= rect.right || _actorHitY < rect.top || _actorHitY >= rect.bottom)
- decode = false;
- } else {
- markRectAsDirty(rect);
-
- if (_vm->_game.heversion >= 71) {
- ActorHE *a = (ActorHE *)_vm->derefActor(_actorID, "paintCelByleRLE");
- a->setActorUpdateArea(rect.left, rect.top, rect.right, rect.bottom + 1);
- }
- }
- };
-
byte drawFlag = paintCelByleRLECommon(
xMoveCur,
yMoveCur,
@@ -648,7 +623,6 @@ byte AkosRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
false,
false,
compData,
- markAsDirty,
decode);
if (!decode)
@@ -670,6 +644,31 @@ void AkosRenderer::markRectAsDirty(Common::Rect rect) {
_vm->markRectAsDirty(kMainVirtScreen, rect, _actorID);
}
+void AkosRenderer::markAsDirty(const Common::Rect &rect, ByleRLEData &compData, bool &decode) {
+ if (_vm->_game.heversion >= 71) {
+ if (_clipOverride.right > _clipOverride.left && _clipOverride.bottom > _clipOverride.top) {
+ compData.boundsRect = _clipOverride;
+ compData.boundsRect.right += 1;
+ compData.boundsRect.bottom += 1;
+
+ compData.boundsRect.right = CLIP<int16>(compData.boundsRect.right, 0, _vm->_screenWidth);
+ compData.boundsRect.bottom = CLIP<int16>(compData.boundsRect.bottom, 0, _vm->_screenHeight);
+ }
+ }
+
+ if (_actorHitMode) {
+ if (_actorHitX < rect.left || _actorHitX >= rect.right || _actorHitY < rect.top || _actorHitY >= rect.bottom)
+ decode = false;
+ } else {
+ markRectAsDirty(rect);
+
+ if (_vm->_game.heversion >= 71) {
+ ActorHE *a = (ActorHE *)_vm->derefActor(_actorID, "paintCelByleRLE");
+ a->setActorUpdateArea(rect.left, rect.top, rect.right, rect.bottom + 1);
+ }
+ }
+}
+
byte AkosRenderer::paintCelCDATRLE(int xmoveCur, int ymoveCur) {
Common::Rect clip;
int32 maxw, maxh;
diff --git a/engines/scumm/akos.h b/engines/scumm/akos.h
index dcc37b4489e..2e54cd7799c 100644
--- a/engines/scumm/akos.h
+++ b/engines/scumm/akos.h
@@ -132,9 +132,11 @@ protected:
int32 specialRenderFlags);
#endif
+private:
void majMinCodecDecompress(byte *dest, int32 pitch, const byte *src, int32 t_width, int32 t_height, int32 dir, int32 numSkipBefore, int32 numSkipAfter, byte transparency, int maskLeft, int maskTop, int zBuf);
void markRectAsDirty(Common::Rect rect);
+ void markAsDirty(const Common::Rect &rect, ByleRLEData &compData, bool &decode) override;
};
enum AkosSequenceCodes {
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index e285c8bec31..28929ea1b86 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -65,7 +65,6 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
bool amiOrPcEngCost,
bool c64Cost,
ByleRLEData &compData,
- std::function<void(const Common::Rect &)> markAsDirty,
bool &decode) {
bool actorIsScaled;
@@ -193,7 +192,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
compData.skipWidth = _width;
compData.scaleXStep = _mirror ? 1 : -1;
- markAsDirty(rect);
+ markAsDirty(rect, compData, decode);
if (!decode)
return 0;
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index ccca811ccc0..e0a8f440adc 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -25,8 +25,6 @@
#include "common/scummsys.h"
#include "scumm/actor.h" // for CostumeData
-#include <functional>
-
namespace Scumm {
#include "common/pack-start.h" // START STRUCT PACKING
@@ -171,12 +169,15 @@ protected:
bool amiOrPcEngCost,
bool c64Cost,
ByleRLEData &compData,
- std::function<void(const Common::Rect &)> markAsDirty,
bool &decode);
void byleRLEDecode(ByleRLEData &compData, int16 actorHitX = 0, int16 actorHitY = 0, bool *actorHitResult = nullptr, const uint8 *xmap = nullptr);
void skipCelLines(ByleRLEData &compData, int num);
+
+private:
+ // helper function to be called from paintCelByleRLECommon
+ virtual void markAsDirty(const Common::Rect &rect, ByleRLEData &compData, bool &decode) {}
};
} // End of namespace Scumm
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index c5ef15aa8c9..65e66b0ade8 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -112,15 +112,6 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
bool decode = true;
- const auto markAsDirty = [this](const Common::Rect &rect) {
- if (_vm->_game.version == 1) {
- // V1 games uses 8 x 8 pixels for actors
- _vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 8, rect.top, rect.bottom, _actorID);
- } else {
- _vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 1, rect.top, rect.bottom, _actorID);
- }
- };
-
byte drawFlag = paintCelByleRLECommon(
xMoveCur,
yMoveCur,
@@ -129,7 +120,6 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
newAmiCost || pcEngCost,
c64Cost,
compData,
- markAsDirty,
decode);
if (!decode)
@@ -159,6 +149,15 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
return drawFlag;
}
+void ClassicCostumeRenderer::markAsDirty(const Common::Rect &rect, ByleRLEData &compData, bool &decode) {
+ if (_vm->_game.version == 1) {
+ // V1 games uses 8 x 8 pixels for actors
+ _vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 8, rect.top, rect.bottom, _actorID);
+ } else {
+ _vm->markRectAsDirty(kMainVirtScreen, rect.left, rect.right + 1, rect.top, rect.bottom, _actorID);
+ }
+}
+
// Skin colors
static const int v1MMActorPalatte1[25] = {
8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h
index d1ddb6a2b37..7e14948fbf9 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -98,6 +98,9 @@ protected:
void byleRLEDecode_C64(ByleRLEData &compData, int actor);
void byleRLEDecode_ami(ByleRLEData &compData);
void byleRLEDecode_PCEngine(ByleRLEData &compData);
+
+private:
+ void markAsDirty(const Common::Rect &rect, ByleRLEData &compData, bool &decode) override;
};
class NESCostumeRenderer : public BaseCostumeRenderer {
Commit: a1d5a77f157da041fbb1771a9807e2b8b3bf6bc7
https://github.com/scummvm/scummvm/commit/a1d5a77f157da041fbb1771a9807e2b8b3bf6bc7
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Keep original AkosRenderer behavior
Those three occasions are the only divergence in both renderers'
behavior.
Changed paths:
engines/scumm/akos.h
engines/scumm/base-costume.cpp
engines/scumm/base-costume.h
diff --git a/engines/scumm/akos.h b/engines/scumm/akos.h
index 2e54cd7799c..f7c317324ea 100644
--- a/engines/scumm/akos.h
+++ b/engines/scumm/akos.h
@@ -95,7 +95,7 @@ protected:
public:
- AkosRenderer(ScummEngine *scumm) : BaseCostumeRenderer(scumm) {
+ AkosRenderer(ScummEngine *scumm) : BaseCostumeRenderer(scumm, true) {
_useBompPalette = false;
_akhd = nullptr;
_akpl = nullptr;
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index 28929ea1b86..e83e6e52301 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -226,8 +226,12 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
}
}
} else {
- if (!actorIsScaled)
- linesToSkip = rect.right - compData.boundsRect.right; // AkosRenderer had +1 here, weird
+ if (!actorIsScaled) {
+ if (_akosRendering)
+ linesToSkip = rect.right - compData.boundsRect.right + 1;
+ else
+ linesToSkip = rect.right - compData.boundsRect.right;
+ }
if (linesToSkip > 0) {
if (!amiOrPcEngCost && !c64Cost) {
compData.skipWidth -= linesToSkip;
@@ -247,7 +251,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
}
}
- if (compData.skipWidth <= 0 || _height <= 0) { // AkosRenderer added the second check (|| _height <= 0)
+ if (compData.skipWidth <= 0 || (_akosRendering && _height <= 0)) {
decode = false;
return 0;
}
@@ -269,7 +273,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
if (_drawBottom < rect.bottom)
_drawBottom = rect.bottom;
- if (_height + rect.top >= 256) { // AkosRenderer didn't do this check
+ if (!_akosRendering && (_height + rect.top >= 256)) {
decode = false;
return 2;
}
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index e0a8f440adc..f7d95672404 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -86,6 +86,9 @@ public:
protected:
ScummEngine *_vm;
+ // flag to enable AkosRenderer's behaviour in paintCelByleRLECommon()
+ bool _akosRendering;
+
// Destination
Graphics::Surface _out;
int32 _numStrips;
@@ -129,7 +132,7 @@ public:
int scaleIndexMask;
};
- BaseCostumeRenderer(ScummEngine *scumm) {
+ BaseCostumeRenderer(ScummEngine *scumm, bool akosRendering = false) {
_actorID = 0;
_shadowMode = 0;
_shadowTable = nullptr;
@@ -139,6 +142,8 @@ public:
_drawTop = _drawBottom = 0;
_vm = scumm;
+ _akosRendering = akosRendering;
+
_numStrips = -1;
_srcPtr = nullptr;
_xMove = _yMove = 0;
Commit: 9709d724f779118849003ab480627b33f12a4069
https://github.com/scummvm/scummvm/commit/9709d724f779118849003ab480627b33f12a4069
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Fix USE_ARM_COSTUME_ASM code
Also, make usage of classic costumes code (!_akosRendering) more
explicit. No need for the made-up 0xFF _shadowMode anymore.
Changed paths:
engines/scumm/base-costume.cpp
engines/scumm/base-costume.h
engines/scumm/costume.cpp
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index e83e6e52301..8e4912bfc95 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -293,7 +293,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
extern "C" int ClassicProc3RendererShadowARM(
int _scaleY,
- ClassicCostumeRenderer::ByleRLEData *compData,
+ BaseCostumeRenderer::ByleRLEData *compData,
int pitch,
const byte *src,
int height,
@@ -315,7 +315,8 @@ void BaseCostumeRenderer::byleRLEDecode(ByleRLEData &compData, int16 actorHitX,
bool masked;
#ifdef USE_ARM_COSTUME_ASM
- if ((_shadowMode == 0xff) &&
+ if ((!_akosRendering && (_shadowMode & 0x20) == 0) &&
+ (actorHitResult == NULL) &&
(compData.maskPtr != NULL) &&
(_shadowTable != NULL))
{
@@ -371,46 +372,52 @@ void BaseCostumeRenderer::byleRLEDecode(ByleRLEData &compData, int16 actorHitX,
bool skipColumn = false;
if (color && !masked) {
- pcolor = _palette[color];
- if (_shadowMode == 0xff) {
- // classic costume, skipColumn = false
- if (pcolor == 13 && _shadowTable)
- pcolor = _shadowTable[*dst];
- } else if (_shadowMode & 0x20) {
- // classic costume, skipColumn = false
- pcolor = _shadowTable[*dst];
- } else if (_shadowMode == 1) {
- if (pcolor == 13) {
- // In shadow mode 1 skipColumn works more or less the same way as in shadow
- // mode 3. It is only ever checked and applied if pcolor is 13.
- skipColumn = (lastColumnX == compData.x);
+ uint16 pcolor;
+
+ if (!_akosRendering) {
+ if (_shadowMode & 0x20) {
pcolor = _shadowTable[*dst];
+ } else {
+ pcolor = _palette[color];
+ if (pcolor == 13 && _shadowTable)
+ pcolor = _shadowTable[*dst];
}
- } else if (_shadowMode == 2) {
- error("AkosRenderer::byleRLEDecode(): shadowMode 2 not implemented."); // TODO
- } else if (_shadowMode == 3) {
- if (_vm->_game.features & GF_16BIT_COLOR) {
- // I add the column skip here, too, although I don't know whether it always
- // applies. But this is the only way to prevent recursive shading of pixels.
- // This might need more fine tuning...
- skipColumn = (lastColumnX == compData.x);
- uint16 srcColor = (pcolor >> 1) & 0x7DEF;
- uint16 dstColor = (READ_UINT16(dst) >> 1) & 0x7DEF;
- pcolor = srcColor + dstColor;
- } else if (_vm->_game.heversion >= 90) {
- // I add the column skip here, too, although I don't know whether it always
- // applies. But this is the only way to prevent recursive shading of pixels.
- // This might need more fine tuning...
- skipColumn = (lastColumnX == compData.x);
- pcolor = (pcolor << 8) + *dst;
- pcolor = xmap[pcolor];
- } else if (pcolor < 8) {
- // This mode is used in COMI. The column skip only takes place when the shading
- // is actually applied (for pcolor < 8). The skip avoids shading of pixels that
- // already have been shaded.
- skipColumn = (lastColumnX == compData.x);
- pcolor = (pcolor << 8) + *dst;
- pcolor = _shadowTable[pcolor];
+ } else {
+ pcolor = _palette[color];
+
+ if (_shadowMode == 1) {
+ if (pcolor == 13) {
+ // In shadow mode 1 skipColumn works more or less the same way as in shadow
+ // mode 3. It is only ever checked and applied if pcolor is 13.
+ skipColumn = (lastColumnX == compData.x);
+ pcolor = _shadowTable[*dst];
+ }
+ } else if (_shadowMode == 2) {
+ error("AkosRenderer::byleRLEDecode(): shadowMode 2 not implemented."); // TODO
+ } else if (_shadowMode == 3) {
+ if (_vm->_game.features & GF_16BIT_COLOR) {
+ // I add the column skip here, too, although I don't know whether it always
+ // applies. But this is the only way to prevent recursive shading of pixels.
+ // This might need more fine tuning...
+ skipColumn = (lastColumnX == compData.x);
+ uint16 srcColor = (pcolor >> 1) & 0x7DEF;
+ uint16 dstColor = (READ_UINT16(dst) >> 1) & 0x7DEF;
+ pcolor = srcColor + dstColor;
+ } else if (_vm->_game.heversion >= 90) {
+ // I add the column skip here, too, although I don't know whether it always
+ // applies. But this is the only way to prevent recursive shading of pixels.
+ // This might need more fine tuning...
+ skipColumn = (lastColumnX == compData.x);
+ pcolor = (pcolor << 8) + *dst;
+ pcolor = xmap[pcolor];
+ } else if (pcolor < 8) {
+ // This mode is used in COMI. The column skip only takes place when the shading
+ // is actually applied (for pcolor < 8). The skip avoids shading of pixels that
+ // already have been shaded.
+ skipColumn = (lastColumnX == compData.x);
+ pcolor = (pcolor << 8) + *dst;
+ pcolor = _shadowTable[pcolor];
+ }
}
}
if (!skipColumn) {
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index f7d95672404..50125b0ccd2 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -86,7 +86,7 @@ public:
protected:
ScummEngine *_vm;
- // flag to enable AkosRenderer's behaviour in paintCelByleRLECommon()
+ // flag to enable AkosRenderer's behaviour in paintCelByleRLECommon() and byleRLEDecode()
bool _akosRendering;
// Destination
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 65e66b0ade8..4d8e901fbd5 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -127,12 +127,6 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
compData.maskPtr = _vm->getMaskBuffer(0, compData.y, _zbuf);
- // temporarily replace _shadowMode to distinguish from AkosRenderer's _shadowMode
- byte oldShadowMode = _shadowMode;
- if (!(_shadowMode & 0x20)) {
- _shadowMode = 0xff;
- }
-
if (c64Cost) {
// The v1 costume renderer needs the actor number, which is
// the same thing as the costume renderer's _actorID.
@@ -144,8 +138,6 @@ byte ClassicCostumeRenderer::paintCelByleRLE(int xMoveCur, int yMoveCur) {
else
byleRLEDecode(compData);
- _shadowMode = oldShadowMode;
-
return drawFlag;
}
Commit: af99cab986268bfaac9b864e6e45a629a9b1d5ed
https://github.com/scummvm/scummvm/commit/af99cab986268bfaac9b864e6e45a629a9b1d5ed
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-03-09T17:24:46+01:00
Commit Message:
SCUMM: Align with HE source code
The height is not checked also in costume.cpp.
Changed paths:
engines/scumm/akos.cpp
engines/scumm/base-costume.cpp
engines/scumm/base-costume.h
engines/scumm/costume.cpp
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index 6dff81023e8..5d5ff261650 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -301,9 +301,9 @@ void AkosRenderer::setCostume(int costume, int shadow) {
}
void AkosRenderer::setFacing(const Actor *a) {
- _mirror = (newDirToOldDir(a->getFacing()) != 0 || READ_LE_UINT16(&_akhd->costumeFlags) & 1);
+ _drawActorToRight = (newDirToOldDir(a->getFacing()) != 0 || READ_LE_UINT16(&_akhd->costumeFlags) & 1);
if (a->_flip)
- _mirror = !_mirror;
+ _drawActorToRight = !_drawActorToRight;
}
byte AkosRenderer::drawLimb(const Actor *a, int limb) {
@@ -678,7 +678,7 @@ byte AkosRenderer::paintCelCDATRLE(int xmoveCur, int ymoveCur) {
return 0;
}
- if (!_mirror) {
+ if (!_drawActorToRight) {
clip.left = (_actorX - xmoveCur - _width) + 1;
} else {
clip.left = _actorX + xmoveCur - 1;
@@ -705,7 +705,7 @@ byte AkosRenderer::paintCelCDATRLE(int xmoveCur, int ymoveCur) {
BompDrawData bdd;
bdd.dst = _out;
- if (!_mirror) {
+ if (!_drawActorToRight) {
bdd.x = (_actorX - xmoveCur - _width) + 1;
} else {
bdd.x = _actorX + xmoveCur;
@@ -727,7 +727,7 @@ byte AkosRenderer::paintCelCDATRLE(int xmoveCur, int ymoveCur) {
bdd.actorPalette = _useBompPalette ? _palette : nullptr;
- bdd.mirror = !_mirror;
+ bdd.mirror = !_drawActorToRight;
drawBomp(bdd);
@@ -789,7 +789,7 @@ byte AkosRenderer::paintCelMajMin(int xMoveCur, int yMoveCur) {
return 0;
}
- if (!_mirror) {
+ if (!_drawActorToRight) {
clip.left = (_actorX - xMoveCur - _width) + 1;
} else {
clip.left = _actorX + xMoveCur;
@@ -857,7 +857,7 @@ byte AkosRenderer::paintCelMajMin(int xMoveCur, int yMoveCur) {
heightUnk = clip.top;
int32 dir;
- if (!_mirror) {
+ if (!_drawActorToRight) {
dir = -1;
int tmpSkipX = skipX;
@@ -908,7 +908,7 @@ byte AkosRenderer::hePaintCel(int actor, int drawToBack, int celX, int celY, int
Actor *a = _vm->derefActor(actor, "hePaintCel");
if (allowFlip) {
- xFlipFlag = _mirror;
+ xFlipFlag = _drawActorToRight;
} else {
xFlipFlag = false;
}
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index 8e4912bfc95..456cba532dc 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -102,7 +102,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
compData.scaleXStep = 1;
}
- if (_mirror) {
+ if (_drawActorToRight) {
/* Adjust X position */
startScaleIndexX = j = (scaletableSize - xMoveCur) & compData.scaleIndexMask;
for (i = 0; i < xMoveCur; i++) {
@@ -166,13 +166,13 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
rect.bottom++;
}
} else {
- if (!_mirror)
+ if (!_drawActorToRight)
xMoveCur = -xMoveCur;
compData.x += xMoveCur;
compData.y += yMoveCur;
- if (_mirror) {
+ if (_drawActorToRight) {
rect.left = compData.x;
rect.right = compData.x + _width;
} else {
@@ -190,7 +190,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
compData.scaleXIndex = startScaleIndexX;
compData.scaleYIndex = startScaleIndexY;
compData.skipWidth = _width;
- compData.scaleXStep = _mirror ? 1 : -1;
+ compData.scaleXStep = _drawActorToRight ? 1 : -1;
markAsDirty(rect, compData, decode);
if (!decode)
@@ -208,7 +208,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
compData.repLen = 0;
- if (_mirror) {
+ if (_drawActorToRight) {
if (!actorIsScaled)
linesToSkip = compData.boundsRect.left - compData.x;
if (linesToSkip > 0) {
@@ -251,7 +251,7 @@ byte BaseCostumeRenderer::paintCelByleRLECommon(
}
}
- if (compData.skipWidth <= 0 || (_akosRendering && _height <= 0)) {
+ if (compData.skipWidth <= 0) {
decode = false;
return 0;
}
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index 50125b0ccd2..6836dc38604 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -100,7 +100,7 @@ protected:
int _xMove, _yMove;
// whether to draw the actor mirrored
- bool _mirror;
+ bool _drawActorToRight;
int _numBlocks;
@@ -147,7 +147,7 @@ public:
_numStrips = -1;
_srcPtr = nullptr;
_xMove = _yMove = 0;
- _mirror = false;
+ _drawActorToRight = false;
_width = _height = 0;
_skipLimbs = false;
_paletteNum = 0;
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 4d8e901fbd5..aab00a030b9 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -220,7 +220,7 @@ void ClassicCostumeRenderer::byleRLEDecode_C64(ByleRLEData &compData, int actor)
color = *src++;
if (0 <= y && y < _out.h && 0 <= compData.x && compData.x < _out.w) {
- if (!_mirror) {
+ if (!_drawActorToRight) {
LINE(0, 0); LINE(2, 2); LINE(4, 4); LINE(6, 6);
} else {
LINE(6, 0); LINE(4, 2); LINE(2, 4); LINE(0, 6);
@@ -350,7 +350,7 @@ void ClassicCostumeRenderer::byleRLEDecode_PCEngine(ByleRLEData &compData) {
if (_numBlocks == 0)
return;
- xStep = _mirror ? +1 : -1;
+ xStep = _drawActorToRight ? +1 : -1;
for (uint x = 0; x < width; ++x) {
yPos = 0;
@@ -655,11 +655,11 @@ byte ClassicCostumeRenderer::drawLimb(const Actor *a, int limb) {
// We adjust the positioning a bit, and make sure the
// lid is always mirrored the same way.
- bool mirror = _mirror;
+ bool mirror = _drawActorToRight;
if (_vm->_game.id == GID_TENTACLE && _vm->_currentRoom == 61 && a->_number == 1 && _loaded._id == 324 && _vm->enhancementEnabled(kEnhMinorBugFixes)) {
if (limb == 0) {
- _mirror = true;
+ _drawActorToRight = true;
xmoveCur--;
} else {
if (a->getFacing() == 270) {
@@ -672,7 +672,7 @@ byte ClassicCostumeRenderer::drawLimb(const Actor *a, int limb) {
byte result = paintCelByleRLE(xmoveCur, ymoveCur);
- _mirror = mirror;
+ _drawActorToRight = mirror;
return result;
}
}
@@ -829,7 +829,7 @@ void ClassicCostumeRenderer::setPalette(uint16 *palette) {
}
void ClassicCostumeRenderer::setFacing(const Actor *a) {
- _mirror = newDirToOldDir(a->getFacing()) != 0 || _loaded._mirror;
+ _drawActorToRight = newDirToOldDir(a->getFacing()) != 0 || _loaded._mirror;
}
void ClassicCostumeRenderer::setCostume(int costume, int shadow) {
More information about the Scummvm-git-logs
mailing list