[Scummvm-git-logs] scummvm master -> 451d0c195de21201604c63f2ca71c208edc2a296

neuromancer noreply at scummvm.org
Wed Jun 17 19:46:09 UTC 2026


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
45bacff1fa SCUMM: RA2: start level 2 and level 11 in cover state
451d0c195d SCUMM: RA2: make sure translucid destroyable shields are properly handled


Commit: 45bacff1faa381a812d8a68eb0659a30acf0c5fd
    https://github.com/scummvm/scummvm/commit/45bacff1faa381a812d8a68eb0659a30acf0c5fd
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-17T17:03:28+02:00

Commit Message:
SCUMM: RA2: start level 2 and level 11 in cover state

Changed paths:
    engines/scumm/insane/rebel2/runlevels.cpp


diff --git a/engines/scumm/insane/rebel2/runlevels.cpp b/engines/scumm/insane/rebel2/runlevels.cpp
index 5f1e95858b4..2cb6b634a09 100644
--- a/engines/scumm/insane/rebel2/runlevels.cpp
+++ b/engines/scumm/insane/rebel2/runlevels.cpp
@@ -312,6 +312,11 @@ void InsaneRebel2::resetLevelPhaseState(bool clearEnemies) {
 
 	if (clearEnemies)
 		_enemies.clear();
+
+	if (_selectedChapter == 1 || _selectedChapter == 10) {
+		_rebelAutopilot = 1;
+		_rebelDamageLevel = 5;
+	}
 }
 
 void InsaneRebel2::clearEmbeddedHudFrames() {


Commit: 451d0c195de21201604c63f2ca71c208edc2a296
    https://github.com/scummvm/scummvm/commit/451d0c195de21201604c63f2ca71c208edc2a296
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-06-17T21:41:25+02:00

Commit Message:
SCUMM: RA2: make sure translucid destroyable shields are properly handled

Changed paths:
    engines/scumm/insane/rebel2/iact.cpp
    engines/scumm/insane/rebel2/rebel.cpp
    engines/scumm/insane/rebel2/rebel.h
    engines/scumm/insane/rebel2/runlevels.cpp
    engines/scumm/smush/rebel/codec_ra2.cpp
    engines/scumm/smush/rebel/codec_ra2.h
    engines/scumm/smush/rebel/smush_player_ra2.cpp
    engines/scumm/smush/rebel/smush_player_ra2.h


diff --git a/engines/scumm/insane/rebel2/iact.cpp b/engines/scumm/insane/rebel2/iact.cpp
index 02493b26fbc..c4d52b41477 100644
--- a/engines/scumm/insane/rebel2/iact.cpp
+++ b/engines/scumm/insane/rebel2/iact.cpp
@@ -2699,6 +2699,18 @@ void InsaneRebel2::enemyUpdate(byte *renderBitmap, Common::SeekableReadStream &b
 	int16 w = b.readSint16LE();        // Offset +14 (0x0E) - Width
 	int16 h = b.readSint16LE();        // Offset +16 (0x10) - Height
 
+	// par3==2 (turret handler) marks a translucent surface / force field (FUN_40A2E0 local_8==2):
+	// never a direct hit target — it is destroyed by clearing the gauge group (par4) it depends
+	// on. Show it while that group still has elements, hide it once the group is cleared.
+	if (par3 == 2 && _rebelHandler == 0x26) {
+		const int surfaceIdx = (par4 >= 100 && par4 < 110) ? (par4 - 100) : -1;
+		if (surfaceIdx >= 0 && _rebelGaugeCleared[surfaceIdx])
+			setBit(enemyId);
+		else
+			clearBit(enemyId);
+		return; // surfaces are not added to the hittable enemy list
+	}
+
 	// If disabled, stop processing this object
 	if (disabled) {
 		// debugC(DEBUG_INSANE, "Skipping Opcode 4 for disabled enemy ID=%d", enemyId);
diff --git a/engines/scumm/insane/rebel2/rebel.cpp b/engines/scumm/insane/rebel2/rebel.cpp
index 6b574ec9675..02f9442f926 100644
--- a/engines/scumm/insane/rebel2/rebel.cpp
+++ b/engines/scumm/insane/rebel2/rebel.cpp
@@ -246,6 +246,8 @@ InsaneRebel2::InsaneRebel2(ScummEngine_v7 *scumm) {
 	_rebelReactorMode = false;
 	_rebelGaugeArmed = false;
 	_rebelLastArmedSlot = -1;
+	for (int i = 0; i < 10; ++i)
+		_rebelGaugeCleared[i] = false;
 
 	_difficulty = 1; // Default to Medium.
 	_targetLockTimer = 0;  // DAT_00443676 equivalent
@@ -1761,11 +1763,15 @@ int32 InsaneRebel2::processMouse() {
 					if (*counter > 0) {
 						(*counter)--;
 						_rebelLastCounter = *counter;
-						// Level 6 ends on any group emptying; Level 13's reactor is gated in
-						// procPostRendering instead, so early obstacle groups don't complete it.
-						if (*counter == 0 && !_rebelReactorMode) {
-							_rebelShieldDestroyed = true;
-							debugC(DEBUG_INSANE, "Shield destroyed (gauge slot %d depleted by target %d)", slot, it->id);
+						if (*counter == 0) {
+							if (slot < 10)
+								_rebelGaugeCleared[slot] = true; // group emptied → its par3==2 surface can drop
+							// Level 6 ends on any group emptying; Level 13's reactor is gated in
+							// procPostRendering instead, so early obstacle groups don't complete it.
+							if (!_rebelReactorMode) {
+								_rebelShieldDestroyed = true;
+								debugC(DEBUG_INSANE, "Shield destroyed (gauge slot %d depleted by target %d)", slot, it->id);
+							}
 						}
 					}
 					_rebelGaugeSlot[it->id] = -1; // consume: avoid double-counting
diff --git a/engines/scumm/insane/rebel2/rebel.h b/engines/scumm/insane/rebel2/rebel.h
index 5fb614c8009..008bb55b591 100644
--- a/engines/scumm/insane/rebel2/rebel.h
+++ b/engines/scumm/insane/rebel2/rebel.h
@@ -970,6 +970,7 @@ public:
 	bool _rebelReactorMode;        // Level 13: finale ends when the last armed group is cleared
 	bool _rebelGaugeArmed;         // at least one gauge group has been set up this attempt
 	int _rebelLastArmedSlot;       // counter slot of the most recently armed group (-1 = none)
+	bool _rebelGaugeCleared[10];   // value-counter slot fully destroyed (drives par3==2 surfaces)
 	void resetShieldGauge();
 
 
diff --git a/engines/scumm/insane/rebel2/runlevels.cpp b/engines/scumm/insane/rebel2/runlevels.cpp
index 2cb6b634a09..15ed6c0e9e3 100644
--- a/engines/scumm/insane/rebel2/runlevels.cpp
+++ b/engines/scumm/insane/rebel2/runlevels.cpp
@@ -349,6 +349,8 @@ void InsaneRebel2::resetShieldGauge() {
 	_rebelShieldDestroyed = false;
 	_rebelGaugeArmed = false;
 	_rebelLastArmedSlot = -1;
+	for (int i = 0; i < 10; ++i)
+		_rebelGaugeCleared[i] = false;
 }
 
 void InsaneRebel2::resetExplosions() {
diff --git a/engines/scumm/smush/rebel/codec_ra2.cpp b/engines/scumm/smush/rebel/codec_ra2.cpp
index e528d51f8a9..cb6100a7e6d 100644
--- a/engines/scumm/smush/rebel/codec_ra2.cpp
+++ b/engines/scumm/smush/rebel/codec_ra2.cpp
@@ -225,6 +225,44 @@ void smushDecodeSkipRLE(byte *dst, const byte *src, int left, int top, int width
 	}
 }
 
+// Codec 23: a skip/run RLE that tints the background in place (no pixel data). Per line,
+// lineDataSize(2) then [skip(1), run(1)] pairs; each run pixel becomes remap[background]
+// (translucency) or background+addColor.
+void smushDecodeRA2SkipRemap(byte *dst, const byte *src, int left, int top, int width, int height, int pitch, int dataSize, const byte *remap, byte addColor) {
+	dst += top * pitch + left;
+	const byte *srcEnd = src + dataSize;
+
+	for (int row = 0; row < height; row++) {
+		if (src + 2 > srcEnd)
+			break;
+		int lineDataSize = READ_LE_UINT16(src);
+		src += 2;
+		const byte *lineStart = src;
+		const byte *lineEnd = (lineStart + lineDataSize <= srcEnd) ? lineStart + lineDataSize : srcEnd;
+		byte *lineDst = dst;
+		int x = 0;
+
+		while (x < width && src < lineEnd) {
+			x += *src++;                 // skip (preserve background)
+			if (x >= width || src >= lineEnd)
+				break;
+			int run = *src++;
+			if (run > width - x)
+				run = width - x;
+			if (remap) {
+				for (int i = 0; i < run; i++, x++)
+					lineDst[x] = remap[lineDst[x]];
+			} else {
+				for (int i = 0; i < run; i++, x++)
+					lineDst[x] = (byte)(lineDst[x] + addColor);
+			}
+		}
+
+		src = lineStart + lineDataSize;
+		dst += pitch;
+	}
+}
+
 bool smushPrepareRA2BlurData(const byte *src, int dataSize, byte *palette, byte *lookup, const byte *&maskData, int &maskSize) {
 	maskData = nullptr;
 	maskSize = 0;
diff --git a/engines/scumm/smush/rebel/codec_ra2.h b/engines/scumm/smush/rebel/codec_ra2.h
index b89797c1a0a..42911065cb0 100644
--- a/engines/scumm/smush/rebel/codec_ra2.h
+++ b/engines/scumm/smush/rebel/codec_ra2.h
@@ -29,6 +29,7 @@ namespace Scumm {
 void smushDecodeRLEOpaque(byte *dst, const byte *src, int left, int top, int width, int height, int pitch, int dataSize);
 void smushDecodeLineUpdate(byte *dst, const byte *src, int left, int top, int width, int height, int pitch, int dataSize);
 void smushDecodeSkipRLE(byte *dst, const byte *src, int left, int top, int width, int height, int pitch, int dataSize);
+void smushDecodeRA2SkipRemap(byte *dst, const byte *src, int left, int top, int width, int height, int pitch, int dataSize, const byte *remap, byte addColor);
 void smushDecodeRA2Blur(byte *dst, const byte *src, int left, int top, int dstWidth, int dstHeight, int pitch, int dataSize, byte *palette, byte *lookup);
 const byte *smushSkipRLELines(const byte *src, int &dataSize, int lines);
 
diff --git a/engines/scumm/smush/rebel/smush_player_ra2.cpp b/engines/scumm/smush/rebel/smush_player_ra2.cpp
index 339b2101206..f0455eea3dc 100644
--- a/engines/scumm/smush/rebel/smush_player_ra2.cpp
+++ b/engines/scumm/smush/rebel/smush_player_ra2.cpp
@@ -189,6 +189,8 @@ void SmushPlayerRebel2::initGamePlayerFields() {
 	_ra2PendingAnimHeaderPalette = false;
 	memset(_ra2Codec45Palette, 0, sizeof(_ra2Codec45Palette));
 	memset(_ra2Codec45Lookup, 0, sizeof(_ra2Codec45Lookup));
+	memset(_ra2SkipRemapTable, 0, sizeof(_ra2SkipRemapTable));
+	_ra2SkipRemapValid = false;
 	_scrollX = 0;
 	_scrollY = 0;
 }
@@ -1440,11 +1442,53 @@ bool SmushPlayerRebel2::handleGameCodecDecode(int codec, const uint8 *src, int l
 	if (isRebel2FullFrameDeltaCodec(codec))
 		return ra2DecodePlacedDeltaCodec(codec, src, left, top, width, height, pitch, dataSize);
 
+	// Codec 23 translucent surfaces: parm2 0x100 prefixes a fresh 256-byte remap table, >=0x100
+	// reuses the last one. (Font glyphs call smushDecodeSkipRLE directly and are unaffected.)
+	if (codec == SMUSH_CODEC_SKIP_RLE && parm2 >= 0x100) {
+		if (parm2 == 0x100 && dataSize >= 256) {
+			memcpy(_ra2SkipRemapTable, src, 256);
+			_ra2SkipRemapValid = true;
+			src += 256;
+			dataSize -= 256;
+		}
+		const byte *remap = _ra2SkipRemapValid ? _ra2SkipRemapTable : nullptr;
+		smushDecodeRA2SkipRemap(_dst, src, left, top, width, height, pitch, dataSize, remap, (byte)parm2);
+		return true;
+	}
+
 	// Handle RA2-specific codecs (21, 23, 44, 45); return false for standard
 	// codecs (RLE) so the base class decodes them.
 	return ra2DecodeCodec(codec, src, left, top, width, height, pitch, dataSize);
 }
 
+// Mirrors SmushPlayer::handleFrameObject but forwards the FOBJ parm2 word (base discards it).
+void SmushPlayerRebel2::handleFrameObject(int32 subSize, Common::SeekableReadStream &b) {
+	assert(subSize >= 14);
+	if (_skipNext) {
+		_skipNext = false;
+		return;
+	}
+
+	int codec = b.readUint16LE();
+	int left = (int)b.readSint16LE();
+	int top = (int)b.readSint16LE();
+	int width = b.readUint16LE();
+	int height = b.readUint16LE();
+	b.readUint16LE();                     // objectId
+	uint16 parm2 = b.readUint16LE();
+
+	const int32 chunkSize = subSize - 14;
+	handleGameFrameObjectPre(codec, left, top, width, height, chunkSize);
+
+	byte *chunkBuffer = (byte *)malloc(chunkSize);
+	assert(chunkBuffer);
+	b.read(chunkBuffer, chunkSize);
+
+	handleGameFrameObjectPost(codec, chunkBuffer, chunkSize, left, top, width, height);
+	decodeFrameObject(codec, chunkBuffer, left, top, width, height, chunkSize, 0, parm2);
+	free(chunkBuffer);
+}
+
 bool SmushPlayerRebel2::handleGameStoreFrame() {
 	// RA2 handles STOR via ra2StoreFobjData in handleGameFrameObjectPost
 	return true;
diff --git a/engines/scumm/smush/rebel/smush_player_ra2.h b/engines/scumm/smush/rebel/smush_player_ra2.h
index c3c87e8ea75..b1628a1a302 100644
--- a/engines/scumm/smush/rebel/smush_player_ra2.h
+++ b/engines/scumm/smush/rebel/smush_player_ra2.h
@@ -38,6 +38,8 @@ protected:
 	void initGameVideoState() override;
 	void releaseGameVideoState() override;
 	bool shouldPreserveFrameBuffer() const override { return true; }
+	// Override to keep the FOBJ parm2 field (codec 23 marker) the base reader discards.
+	void handleFrameObject(int32 subSize, Common::SeekableReadStream &b) override;
 	bool handleGameFetch(int32 subSize, Common::SeekableReadStream &b) override;
 	bool handleGameTextResource(uint32 subType, int32 subSize, Common::SeekableReadStream &b) override;
 	bool handleGameTextRendering(const char *str, int fontId, int color, int pos_x, int pos_y, int left, int top, int width, int height, TextStyleFlags flg) override;
@@ -110,6 +112,8 @@ private:
 	bool _ra2PendingAnimHeaderPalette;
 	byte _ra2Codec45Palette[0x300];
 	byte _ra2Codec45Lookup[0x8000];
+	byte _ra2SkipRemapTable[256]; // codec 23 translucency remap table
+	bool _ra2SkipRemapValid;
 };
 
 } // End of namespace Scumm




More information about the Scummvm-git-logs mailing list