[Scummvm-git-logs] scummvm master -> bfa2d8d28720561045551ed660946ada2c9795c3
Strangerke
noreply at scummvm.org
Sat Jan 3 08:18:53 UTC 2026
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:
bfa2d8d287 HUGO: Implement DOS displayFrame() (#7108)
Commit: bfa2d8d28720561045551ed660946ada2c9795c3
https://github.com/scummvm/scummvm/commit/bfa2d8d28720561045551ed660946ada2c9795c3
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2026-01-03T09:18:49+01:00
Commit Message:
HUGO: Implement DOS displayFrame() (#7108)
- Fixes HUGO2 priority glitches in `hall2` doorways, bug #5667
- Fixes HUGO2 priority glitches in front of bed
The Windows version of HUGO2 still has a priority glitch in
front of the bed, but that is a bug in the original game.
Changed paths:
engines/hugo/display.cpp
engines/hugo/display.h
diff --git a/engines/hugo/display.cpp b/engines/hugo/display.cpp
index e0a2943d7e2..6ff37bc76ed 100644
--- a/engines/hugo/display.cpp
+++ b/engines/hugo/display.cpp
@@ -238,42 +238,6 @@ void Screen::setBackgroundColor(const uint16 color) {
remapPal(0, color);
}
-/**
- * Merge an object frame into _frontBuffer at sx, sy and update rectangle list.
- * If fore TRUE, force object above any overlay
- */
-void Screen::displayFrame(const int sx, const int sy, Seq *seq, const bool foreFl) {
- debugC(3, kDebugDisplay, "displayFrame(%d, %d, seq, %d)", sx, sy, (foreFl) ? 1 : 0);
-
- ImagePtr image = seq->_imagePtr; // Ptr to object image data
- ImagePtr subFrontBuffer = &_frontBuffer[sy * kXPix + sx]; // Ptr to offset in _frontBuffer
- int16 frontBufferwrap = kXPix - seq->_x2 - 1; // Wraps dest_p after each line
- int16 imageWrap = seq->_bytesPerLine8 - seq->_x2 - 1;
- OverlayState overlayState = (foreFl) ? kOvlForeground : kOvlUndef; // Overlay state of object
- for (uint16 y = 0; y < seq->_lines; y++) { // Each line in object
- for (uint16 x = 0; x <= seq->_x2; x++) {
- if (*image) { // Non-transparent
- byte ovlBound = _vm->_object->getFirstOverlay((uint16)(subFrontBuffer - _frontBuffer) >> 3); // Ptr into overlay bits
- if (ovlBound & (0x80 >> ((uint16)(subFrontBuffer - _frontBuffer) & 7))) { // Overlay bit is set
- if (overlayState == kOvlUndef) // Overlay defined yet?
- overlayState = findOvl(seq, subFrontBuffer, y);// No, find it.
- if (overlayState == kOvlForeground) // Object foreground
- *subFrontBuffer = *image; // Copy pixel
- } else { // No overlay
- *subFrontBuffer = *image; // Copy pixel
- }
- }
- image++;
- subFrontBuffer++;
- }
- image += imageWrap;
- subFrontBuffer += frontBufferwrap;
- }
-
- // Add this rectangle to the display list
- displayList(kDisplayAdd, sx, sy, seq->_x2 + 1, seq->_lines);
-}
-
/**
* Merge rectangles A,B leaving result in B
*/
@@ -741,17 +705,71 @@ void Screen_v1d::loadFontArr(Common::ReadStream &in) {
}
}
+/**
+ * Merge an object frame into _frontBuffer at sx, sy and update rectangle list.
+ * If fore TRUE, force object above any overlay
+ *
+ * Note: The DOS version has subtlety different overlay logic than the Windows version.
+ * The overlay base comparison occurs in a different order, and this alters the outcome.
+ * This may have been unintentional when the original DOS code was rewritten from assembly
+ * in C for Windows, as the Windows version introduces a priority bug when standing in
+ * front of the bed in the second room of Hugo2.
+ */
+void Screen_v1d::displayFrame(const int sx, const int sy, Seq *seq, const bool foreFl) {
+ debugC(3, kDebugDisplay, "displayFrame(%d, %d, seq, %d)", sx, sy, (foreFl) ? 1 : 0);
+
+ ImagePtr image = seq->_imagePtr; // Ptr to object image data
+ ImagePtr subFrontBuffer = &_frontBuffer[sy * kXPix + sx]; // Ptr to offset in _frontBuffer
+ int16 frontBufferwrap = kXPix - seq->_x2 - 1; // Wraps dest_p after each line
+ int16 imageWrap = seq->_bytesPerLine8 - seq->_x2 - 1;
+ OverlayState overlayState = (foreFl) ? kOvlForeground : kOvlUndef; // Overlay state of object
+ for (uint16 y = 0; y < seq->_lines; y++) { // Each line in object
+ for (uint16 x = 0; x <= seq->_x2; x++) {
+ byte ovlBound = _vm->_object->getFirstOverlay((uint16)(subFrontBuffer - _frontBuffer) >> 3); // Ptr into overlay bits
+ if (ovlBound != 0) {
+ if (overlayState == kOvlUndef) // Overlay defined yet?
+ overlayState = findOvl(seq, subFrontBuffer, y);// No, find it.
+ }
+
+ if (*image) { // Non-transparent
+ if (ovlBound & (0x80 >> ((uint16)(subFrontBuffer - _frontBuffer) & 7))) { // Overlay bit is set
+ if (overlayState == kOvlForeground) // Object foreground
+ *subFrontBuffer = *image; // Copy pixel
+ } else { // No overlay
+ *subFrontBuffer = *image; // Copy pixel
+ }
+ }
+ image++;
+ subFrontBuffer++;
+ }
+ image += imageWrap;
+ subFrontBuffer += frontBufferwrap;
+ }
+
+ // Add this rectangle to the display list
+ displayList(kDisplayAdd, sx, sy, seq->_x2 + 1, seq->_lines);
+}
+
/**
* Return the overlay state (Foreground/Background) of the currently
* processed object by looking down the current column for an overlay
* base byte set (in which case the object is foreground).
+ *
+ * Note: This DOS function was originally in assembly. We have structured
+ * it to resemble the Windows C code, but the original DOS assembly takes
+ * "y" as the number of lines left to scan, not the number of lines that
+ * have been scanned, so we invert it here. For example, if an object is
+ * 45 lines and and processFrame() locates an overlay byte on the second
+ * line, it will pass 1 for y, so we must scan 44 rows for a base byte
+ * starting from dstPtr (the second row from the top).
*/
OverlayState Screen_v1d::findOvl(Seq *seqPtr, ImagePtr dstPtr, uint16 y) {
debugC(4, kDebugDisplay, "findOvl()");
uint16 index = (uint16)(dstPtr - _frontBuffer) >> 3;
- for (int i = 0; i < seqPtr->_lines-y; i++) { // Each line in object
+ int linesToScan = seqPtr->_lines - y;
+ for (int i = 0; i < linesToScan; i++) { // Each line in object
if (_vm->_object->getBaseBoundary(index)) // If any overlay base byte is non-zero then the object is foreground, else back.
return kOvlForeground;
index += kCompLineSize;
@@ -810,6 +828,42 @@ void Screen_v1w::loadFontArr(Common::ReadStream &in) {
}
}
+/**
+ * Merge an object frame into _frontBuffer at sx, sy and update rectangle list.
+ * If fore TRUE, force object above any overlay
+ */
+void Screen_v1w::displayFrame(const int sx, const int sy, Seq *seq, const bool foreFl) {
+ debugC(3, kDebugDisplay, "displayFrame(%d, %d, seq, %d)", sx, sy, (foreFl) ? 1 : 0);
+
+ ImagePtr image = seq->_imagePtr; // Ptr to object image data
+ ImagePtr subFrontBuffer = &_frontBuffer[sy * kXPix + sx]; // Ptr to offset in _frontBuffer
+ int16 frontBufferwrap = kXPix - seq->_x2 - 1; // Wraps dest_p after each line
+ int16 imageWrap = seq->_bytesPerLine8 - seq->_x2 - 1;
+ OverlayState overlayState = (foreFl) ? kOvlForeground : kOvlUndef; // Overlay state of object
+ for (uint16 y = 0; y < seq->_lines; y++) { // Each line in object
+ for (uint16 x = 0; x <= seq->_x2; x++) {
+ if (*image) { // Non-transparent
+ byte ovlBound = _vm->_object->getFirstOverlay((uint16)(subFrontBuffer - _frontBuffer) >> 3); // Ptr into overlay bits
+ if (ovlBound & (0x80 >> ((uint16)(subFrontBuffer - _frontBuffer) & 7))) { // Overlay bit is set
+ if (overlayState == kOvlUndef) // Overlay defined yet?
+ overlayState = findOvl(seq, subFrontBuffer, y);// No, find it.
+ if (overlayState == kOvlForeground) // Object foreground
+ *subFrontBuffer = *image; // Copy pixel
+ } else { // No overlay
+ *subFrontBuffer = *image; // Copy pixel
+ }
+ }
+ image++;
+ subFrontBuffer++;
+ }
+ image += imageWrap;
+ subFrontBuffer += frontBufferwrap;
+ }
+
+ // Add this rectangle to the display list
+ displayList(kDisplayAdd, sx, sy, seq->_x2 + 1, seq->_lines);
+}
+
/**
* Return the overlay state (Foreground/Background) of the currently
* processed object by looking down the current column for an overlay
diff --git a/engines/hugo/display.h b/engines/hugo/display.h
index 554c83af0d4..1982634e9c3 100644
--- a/engines/hugo/display.h
+++ b/engines/hugo/display.h
@@ -59,7 +59,7 @@ public:
int16 stringLength(const char *s) const;
void displayBackground();
- void displayFrame(const int sx, const int sy, Seq *seq, const bool foreFl);
+ virtual void displayFrame(const int sx, const int sy, Seq *seq, const bool foreFl) = 0;
void displayList(int update, ...);
void displayRect(const int16 x, const int16 y, const int16 dx, const int16 dy);
void drawBoundaries();
@@ -118,8 +118,6 @@ protected:
inline bool isInY(const int16 y, const Rect *rect) const;
inline bool isOverlapping(const Rect *rectA, const Rect *rectB) const;
- virtual OverlayState findOvl(Seq *seqPtr, ImagePtr dstPtr, uint16 y) = 0;
-
private:
byte *_curPalette;
byte _iconImage[kInvDx * kInvDy];
@@ -153,8 +151,10 @@ public:
void loadFont(int16 fontId) override;
void loadFontArr(Common::ReadStream &in) override;
+
+ void displayFrame(const int sx, const int sy, Seq *seq, const bool foreFl) override;
protected:
- OverlayState findOvl(Seq *seqPtr, ImagePtr dstPtr, uint16 y) override;
+ OverlayState findOvl(Seq *seqPtr, ImagePtr dstPtr, uint16 y);
};
class Screen_v1w : public Screen {
@@ -164,8 +164,10 @@ public:
void loadFont(int16 fontId) override;
void loadFontArr(Common::ReadStream &in) override;
+
+ void displayFrame(const int sx, const int sy, Seq *seq, const bool foreFl) override;
protected:
- OverlayState findOvl(Seq *seqPtr, ImagePtr dstPtr, uint16 y) override;
+ OverlayState findOvl(Seq *seqPtr, ImagePtr dstPtr, uint16 y);
};
} // End of namespace Hugo
More information about the Scummvm-git-logs
mailing list