[Scummvm-git-logs] scummvm master -> 99f45887d9327b566e09e405645904a9a98e807b
AndywinXp
noreply at scummvm.org
Sun Sep 28 09:34:59 UTC 2025
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
99f45887d9 SCUMM/HE: FREDDI5: Fix #13797
Commit: 99f45887d9327b566e09e405645904a9a98e807b
https://github.com/scummvm/scummvm/commit/99f45887d9327b566e09e405645904a9a98e807b
Author: AndywinXp (andywinxp at gmail.com)
Date: 2025-09-28T11:34:53+02:00
Commit Message:
SCUMM/HE: FREDDI5: Fix #13797
Yet another case of "surely we don't need this part from the source code". :)
This fixes #13797:
"SCUMM/HE: FREDDI5: Outline of Freddi appears in the leftmost tide pool"
Turns out their own qsort algo behaves quite differently when several sprites
have the same priority assigned to them.
Changed paths:
engines/scumm/he/sprite_he.cpp
engines/scumm/he/sprite_he.h
diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp
index 656ed2cccc7..4949ef3daaf 100644
--- a/engines/scumm/he/sprite_he.cpp
+++ b/engines/scumm/he/sprite_he.cpp
@@ -1633,6 +1633,118 @@ static int compareSpritePriority(const void *a, const void *b) {
return spr1->priority - spr2->priority;
}
+#define SWAP_SPRITE_PTRS(e1, e2, te) { \
+ te = *e1; \
+ *e1 = *e2; \
+ *e2 = te; \
+}
+
+#define SPRITE_QSORT_CUTOFF 8
+
+void Sprite::qsortSpriteArray(SpriteInfo **base, uint num) {
+ SpriteInfo **lostk[30], **histk[30];
+ SpriteInfo **loguy, **higuy;
+ SpriteInfo **lo, **hi;
+ SpriteInfo **mid;
+ SpriteInfo *t;
+
+ uint size;
+ int stkptr;
+
+ if (num < 2)
+ return;
+
+ stkptr = 0;
+
+ lo = base;
+ hi = base + (num - 1);
+
+recurse:
+ size = (hi - lo) + 1;
+
+ if (size <= SPRITE_QSORT_CUTOFF) {
+ shortsortSpriteArray(lo, hi);
+ } else {
+ mid = lo + (size / 2);
+ SWAP_SPRITE_PTRS(mid, lo, t);
+
+ loguy = lo;
+ higuy = hi + 1;
+
+ for (;;) {
+ do {
+ ++loguy;
+ } while (loguy <= hi && compareSpriteCombinedPriority((const SpriteInfo **)loguy, (const SpriteInfo **)lo) <= 0);
+
+ do {
+ --higuy;
+ } while (higuy > lo && compareSpriteCombinedPriority((const SpriteInfo **)higuy, (const SpriteInfo **)lo) >= 0);
+
+ if (higuy < loguy)
+ break;
+
+ SWAP_SPRITE_PTRS(loguy, higuy, t);
+ }
+
+ SWAP_SPRITE_PTRS(lo, higuy, t);
+
+ if (higuy - 1 - lo >= hi - loguy) {
+ if (lo + 1 < higuy) {
+ lostk[stkptr] = lo;
+ histk[stkptr] = higuy - 1;
+ ++stkptr;
+ }
+
+ if (loguy < hi) {
+ lo = loguy;
+ goto recurse;
+ }
+ } else {
+ if (loguy < hi) {
+ lostk[stkptr] = loguy;
+ histk[stkptr] = hi;
+ ++stkptr;
+ }
+
+ if (lo + 1 < higuy) {
+ hi = higuy - 1;
+ goto recurse;
+ }
+ }
+ }
+
+ --stkptr;
+
+ if (stkptr >= 0) {
+ lo = lostk[stkptr];
+ hi = histk[stkptr];
+ goto recurse;
+ } else {
+ return;
+ }
+}
+
+void Sprite::shortsortSpriteArray(SpriteInfo **lo, SpriteInfo **hi) {
+ SpriteInfo **p, **max, *t;
+
+ while (hi > lo) {
+ max = lo;
+
+ for (p = lo + 1; p <= hi; p++) {
+ if (compareSpriteCombinedPriority((const SpriteInfo **)p, (const SpriteInfo **)max) > 0) {
+ max = p;
+ }
+ }
+
+ SWAP_SPRITE_PTRS(max, hi, t);
+ hi--;
+ }
+}
+
+#undef SPRITE_QSORT_CUTOFF
+
+#undef SWAP_SPRITE_PTRS
+
void Sprite::buildActiveSpriteList() {
SpriteInfo **spritePtr;
@@ -1666,7 +1778,7 @@ void Sprite::buildActiveSpriteList() {
// Sort the list of active sprites...
if (_activeSpriteCount) {
if (_vm->_game.heversion > 95) {
- qsort(_activeSprites, _activeSpriteCount, sizeof(SpriteInfo *), compareSpriteCombinedPriority);
+ qsortSpriteArray(_activeSprites, _activeSpriteCount);
} else {
qsort(_activeSprites, _activeSpriteCount, sizeof(SpriteInfo *), compareSpritePriority);
}
diff --git a/engines/scumm/he/sprite_he.h b/engines/scumm/he/sprite_he.h
index d09d39b934a..c6ede16d40c 100644
--- a/engines/scumm/he/sprite_he.h
+++ b/engines/scumm/he/sprite_he.h
@@ -236,6 +236,8 @@ public:
void eraseSprites();
bool doesRectIntersectUpdateAreas(const Common::Rect *rectPtr);
void checkForForcedRedraws(bool checkOnlyPositivePriority);
+ void qsortSpriteArray(SpriteInfo **base, uint num);
+ void shortsortSpriteArray(SpriteInfo **lo, SpriteInfo **hi);
void buildActiveSpriteList();
void renderSprites(bool negativeOrPositiveRender);
void runSpriteEngines();
More information about the Scummvm-git-logs
mailing list