[Scummvm-git-logs] scummvm master -> ef9ad271b061272eee66693b5af1696252b9801a
sev-
noreply at scummvm.org
Fri Jul 17 18:39:57 UTC 2026
This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
560c0d2894 CHAMBER: Support the Amiga US (Chamber) release in the Amiga renderer
168ec363e1 CHAMBER: fix Zone Scan line
f1cfc8afa2 CHAMBER: Add Amiga EU/US detection entries
268289e0a3 CHAMBER: Add Amiga Zone Scan palette effect
2e6146d462 CHAMBER: Fix Coverity dead-code, leak and uninit findings
44c539adf7 CHAMBER: Fix PVS-Studio dead-store and always-false findings
c11f6d3bb8 CHAMBER: Save backbuffer so scripted room changes survive load
ef9ad271b0 CHAMBER: Address Amiga US PR review comments
Commit: 560c0d2894a03a9c82b2bad5cb4fe789461f1a92
https://github.com/scummvm/scummvm/commit/560c0d2894a03a9c82b2bad5cb4fe789461f1a92
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-07-17T20:39:49+02:00
Commit Message:
CHAMBER: Support the Amiga US (Chamber) release in the Amiga renderer
The US Draconian build lays out the KULT executable differently: it
needs its own static resource offset table, embeds the English text
banks in the executable instead of separate files, and shows an
intro.pia title screen before pres.bin.
Changed paths:
engines/chamber/amiga.cpp
engines/chamber/kult.cpp
engines/chamber/resdata.cpp
diff --git a/engines/chamber/amiga.cpp b/engines/chamber/amiga.cpp
index 6d11a990fc4..996aee69871 100644
--- a/engines/chamber/amiga.cpp
+++ b/engines/chamber/amiga.cpp
@@ -35,21 +35,34 @@ namespace Chamber {
const byte *amiga_palette_table = nullptr;
const byte *amiga_room_palette_table = nullptr;
-// Static resources are sliced straight out of the EU KULT executable
struct AmigaResEnt {
const char *name;
byte **buffer;
- uint32 offset;
+ uint32 offset; // EU "Kult (M3)"
uint32 size;
+ uint32 offsetUS; // US "Chamber" (Draconian)
+ uint32 sizeUS;
};
#define AMIGA_PAL_OFFSET 40896
+#define AMIGA_PAL_OFFSET_US 41010
// Each room takes a shared base and drops its own 5-word delta over slots 1..5
#define AMIGA_ROOM_PAL_OFFSET 40268
+#define AMIGA_ROOM_PAL_OFFSET_US 40362
#define AMIGA_ROOM_DELTA_OFFSET 40068
+#define AMIGA_ROOM_DELTA_OFFSET_US 40162
#define AMIGA_NUM_ROOM_PALETTES 20
+// The US build ships no VERBE/MOTSE/DESCE/DIALE text files; the English banks
+// are embedded in the exe (in this order, right after ANICO). EU keeps them as
+// separate files because it is multilingual.
+#define AMIGA_DIALE_OFFSET_US 82656
+#define AMIGA_DESCE_OFFSET_US 92296
+#define AMIGA_VERBE_OFFSET_US 102746
+#define AMIGA_MOTSE_OFFSET_US 104066
+#define AMIGA_MOTSE_END_US 105166
+
static const byte *amiga_room_delta_table = nullptr;
// Accent colours every room shares. Slots 1..5 get overwritten by the delta
@@ -73,21 +86,33 @@ static const uint16 amiga_room_base_pal[16] = {
};
static AmigaResEnt amiga_res[] = {
- { "SOUCO.BIN", &souco_data, 37724, 424 },
- { "ZONES.BIN", &zones_data, 43250, 9014 },
- { "TEMPL.BIN", &templ_data, 52318, 27336 },
- { "MURSM.BIN", &mursm_data, 79654, 76 },
- { "ANIMA.BIN", &anima_data, 79730, 2046 },
- { "ANICO.BIN", &anico_data, 81776, 667 },
- { "ARPLA.BIN", &arpla_data, 105612, 8024 },
- { "CARAC.BIN", &carpc_data, 113636, 384 },
- { "GAUSS.BIN", &gauss_data, 114148, 2880 },
- { "ALEAT.BIN", &aleat_data, 117028, 256 },
- { "ICONE.BIN", &icone_data, 117284, 2752 },
- { "LUTIN.BIN", &lutin_data, 120036, 2800 },
+ // name buffer EU off EU sz US off US sz
+ { "SOUCO.BIN", &souco_data, 37724, 424, 37818, 424 },
+ { "ZONES.BIN", &zones_data, 43250, 9014, 43428, 9014 },
+ { "TEMPL.BIN", &templ_data, 52318, 27336, 52496, 27370 },
+ { "MURSM.BIN", &mursm_data, 79654, 76, 79866, 76 },
+ { "ANIMA.BIN", &anima_data, 79730, 2046, 79942, 2046 },
+ { "ANICO.BIN", &anico_data, 81776, 667, 81988, 667 },
+ { "ARPLA.BIN", &arpla_data, 105612, 8024, 105166, 8024 },
+ { "CARAC.BIN", &carpc_data, 113636, 384, 113190, 384 },
+ { "GAUSS.BIN", &gauss_data, 114148, 2880, 113702, 2880 },
+ { "ALEAT.BIN", &aleat_data, 117028, 256, 116582, 256 },
+ { "ICONE.BIN", &icone_data, 117284, 2752, 116838, 2752 },
+ { "LUTIN.BIN", &lutin_data, 120036, 2800, 119594, 2800 },
};
static const int kAmigaNumRes = sizeof(amiga_res) / sizeof(amiga_res[0]);
+// Copy an exe-embedded text bank into its fixed engine buffer, clamped to the
+// buffer size and to the space up to the next bank so we never overrun either.
+static void copyAmigaText(byte *dst, uint32 bufMax, const byte *raw, uint32 sz, uint32 off, uint32 next) {
+ uint32 n = next - off;
+ if (n > bufMax)
+ n = bufMax;
+ if (off + n > sz)
+ return;
+ memcpy(dst, raw + off, n);
+}
+
int16 loadAmigaStaticData() {
// Safe to call more than once: it runs both before the title splash (to make
// the palette available) and again from loadStaticData(); the second call
@@ -113,17 +138,31 @@ int16 loadAmigaStaticData() {
delete[] g_vm->_pxiData;
g_vm->_pxiData = raw;
+ // The US "Chamber" build uses a different exe with its own offset column
+ const bool isUS = g_vm->getLanguage() == Common::EN_USA;
+
for (int i = 0; i < kAmigaNumRes; i++) {
- if (amiga_res[i].offset + amiga_res[i].size > sz) {
+ uint32 off = isUS ? amiga_res[i].offsetUS : amiga_res[i].offset;
+ uint32 rsz = isUS ? amiga_res[i].sizeUS : amiga_res[i].size;
+ if (off + rsz > sz) {
warning("loadAmigaStaticData(): %s past EOF", amiga_res[i].name);
return 0;
}
- *amiga_res[i].buffer = raw + amiga_res[i].offset;
+ *amiga_res[i].buffer = raw + off;
}
- amiga_palette_table = raw + AMIGA_PAL_OFFSET;
- amiga_room_palette_table = raw + AMIGA_ROOM_PAL_OFFSET;
- amiga_room_delta_table = raw + AMIGA_ROOM_DELTA_OFFSET;
+ amiga_palette_table = raw + (isUS ? AMIGA_PAL_OFFSET_US : AMIGA_PAL_OFFSET);
+ amiga_room_palette_table = raw + (isUS ? AMIGA_ROOM_PAL_OFFSET_US : AMIGA_ROOM_PAL_OFFSET);
+ amiga_room_delta_table = raw + (isUS ? AMIGA_ROOM_DELTA_OFFSET_US : AMIGA_ROOM_DELTA_OFFSET);
+
+ // The US build has no VERBE/MOTSE/DESCE/DIALE files; slice the embedded
+ // English banks out of the exe into the buffers loadFile() would have filled.
+ if (isUS) {
+ copyAmigaText(diali_data, RES_DIALI_MAX, raw, sz, AMIGA_DIALE_OFFSET_US, AMIGA_DESCE_OFFSET_US);
+ copyAmigaText(desci_data, RES_DESCI_MAX, raw, sz, AMIGA_DESCE_OFFSET_US, AMIGA_VERBE_OFFSET_US);
+ copyAmigaText(vepci_data, RES_VEPCI_MAX, raw, sz, AMIGA_VERBE_OFFSET_US, AMIGA_MOTSE_OFFSET_US);
+ copyAmigaText(motsi_data, RES_MOTSI_MAX, raw, sz, AMIGA_MOTSE_OFFSET_US, AMIGA_MOTSE_END_US);
+ }
// Amiga glyphs sit one bit too high, shift them back into the low nibble
for (uint32 i = 0; i < 384; i++)
diff --git a/engines/chamber/kult.cpp b/engines/chamber/kult.cpp
index 1fc3f9d0258..6777b678a34 100644
--- a/engines/chamber/kult.cpp
+++ b/engines/chamber/kult.cpp
@@ -20,6 +20,7 @@
*/
#include "common/error.h"
+#include "common/file.h"
#include "common/system.h"
#include "engines/advancedDetector.h"
#include "engines/util.h"
@@ -103,7 +104,31 @@ Graphics::Surface *loadSplash(const char *filename) {
return surface;
}
+// TEMP headless debug helper, remove: dump current screen+palette as PPM
+void debugDumpScreen(const char *tag) {
+ if (gDebugLevel < 9)
+ return;
+ static int n = 0;
+ Graphics::Surface *s = g_system->lockScreen();
+ byte pal[768];
+ g_system->getPaletteManager()->grabPalette(pal, 0, 256);
+ Common::DumpFile f;
+ if (f.open(Common::Path(Common::String::format("/tmp/chamber_dbg/%03d_%s.ppm", n++, tag)))) {
+ f.writeString(Common::String::format("P6\n%d %d\n255\n", s->w, s->h));
+ for (int y = 0; y < s->h; y++)
+ for (int x = 0; x < s->w; x++) {
+ byte c = *(const byte *)s->getBasePtr(x, y);
+ f.writeByte(pal[c * 3]);
+ f.writeByte(pal[c * 3 + 1]);
+ f.writeByte(pal[c * 3 + 2]);
+ }
+ }
+ g_system->unlockScreen();
+}
+
uint16 benchmarkCpu(void) {
+ if (gDebugLevel >= 9) // TEMP headless debug stub, remove
+ return 1000;
byte t;
uint16 cycles = 0;
for (t = script_byte_vars.timer_ticks; t == script_byte_vars.timer_ticks;) ;
@@ -304,6 +329,20 @@ Common::Error ChamberEngine::init() {
if (getPlatform() == Common::kPlatformAmiga) {
// Amiga title: static resources (incl. palette) live in KULT, load them first
loadAmigaStaticData();
+ if (getLanguage() == Common::EN_USA) {
+ splash = ega_loadFond("INTRO.PIA");
+ if (splash) {
+ g_vm->_renderer->colorSelect(AMIGA_NUM_PALETTES - 1);
+ g_vm->_renderer->backBufferToRealFull();
+ // Splash wraps ega_backbuffer: the surface does not own its pixels
+ delete splash;
+ splash = nullptr;
+ clearKeyboard();
+ readKeyboardChar();
+ if (_shouldQuit)
+ return Common::kNoError;
+ }
+ }
splash = ega_loadFond("PRES.BIN");
if (!splash) {
_shouldQuit = true;
diff --git a/engines/chamber/resdata.cpp b/engines/chamber/resdata.cpp
index 47ddef5e4d4..1f0e7df3c22 100644
--- a/engines/chamber/resdata.cpp
+++ b/engines/chamber/resdata.cpp
@@ -277,8 +277,12 @@ ResEntry_t res_texts_amiga[] = {
Load strings data (commands/names)
*/
int16 loadVepciData() {
- if (g_vm->getPlatform() == Common::kPlatformAmiga)
+ if (g_vm->getPlatform() == Common::kPlatformAmiga) {
+ // US embeds these banks in the exe (loaded by loadAmigaStaticData())
+ if (g_vm->getLanguage() == Common::EN_USA)
+ return 1;
return loadFilesList(res_texts_amiga);
+ }
return loadFilesList(res_texts);
}
@@ -328,8 +332,11 @@ ResEntry_t res_desci_amiga[] = {
Load strings data (obj. descriptions)
*/
int16 loadDesciData(void) {
- if (g_vm->getPlatform() == Common::kPlatformAmiga)
+ if (g_vm->getPlatform() == Common::kPlatformAmiga) {
+ if (g_vm->getLanguage() == Common::EN_USA)
+ return 1;
return loadFilesList(res_desci_amiga);
+ }
while (!loadFilesList(res_desci))
askDisk2();
return 1;
@@ -349,8 +356,11 @@ ResEntry_t res_diali_amiga[] = {
Load strings data (dialogs)
*/
int16 loadDialiData(void) {
- if (g_vm->getPlatform() == Common::kPlatformAmiga)
+ if (g_vm->getPlatform() == Common::kPlatformAmiga) {
+ if (g_vm->getLanguage() == Common::EN_USA)
+ return 1;
return loadFilesList(res_diali_amiga);
+ }
while (!loadFilesList(res_diali))
askDisk2();
return 1;
Commit: 168ec363e16ea967ec9a2dbdb22c7b9f2017f79f
https://github.com/scummvm/scummvm/commit/168ec363e16ea967ec9a2dbdb22c7b9f2017f79f
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-07-17T20:39:49+02:00
Commit Message:
CHAMBER: fix Zone Scan line
Changed paths:
engines/chamber/script.cpp
diff --git a/engines/chamber/script.cpp b/engines/chamber/script.cpp
index 3af5a91302e..cb99c45aa45 100644
--- a/engines/chamber/script.cpp
+++ b/engines/chamber/script.cpp
@@ -3710,9 +3710,7 @@ uint16 CMD_E_PsiZoneScan(void) {
w = room_bounds_rect.ex - room_bounds_rect.sx;
h = room_bounds_rect.ey - room_bounds_rect.sy;
- /*room coords are in 4-pixel blocks; EGA is 1 byte/pixel so the scan line
- spans w*4 bytes, while CGA packs 4 pixels/byte and spans w bytes*/
- if (g_vm->_videoMode == Common::kRenderEGA)
+ if (isEgaLikeRenderer())
w *= 4;
for (y = room_bounds_rect.sy; h; y++, h--) {
@@ -4497,6 +4495,9 @@ uint16 RunScript(byte *code) {
while (script_ptr != script_end_ptr) {
byte opcode = *script_ptr;
+ if (gDebugLevel >= 9) // TEMP headless debug trace, remove
+ debug("scr %04X: %02X", (uint16)((script_ptr - templ_data) & 0xFFFF), opcode);
+
#ifdef DEBUG_SCRIPT
{
FILE *f = fopen(DEBUG_SCRIPT_LOG, "at");
Commit: f1cfc8afa236d4652f2c0ac9d3facfa001ad66db
https://github.com/scummvm/scummvm/commit/f1cfc8afa236d4652f2c0ac9d3facfa001ad66db
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-07-17T20:39:49+02:00
Commit Message:
CHAMBER: Add Amiga EU/US detection entries
Changed paths:
engines/chamber/detection.cpp
diff --git a/engines/chamber/detection.cpp b/engines/chamber/detection.cpp
index b7317a5982b..5fe2df85bd2 100644
--- a/engines/chamber/detection.cpp
+++ b/engines/chamber/detection.cpp
@@ -64,6 +64,30 @@ static const ADGameDescription gameDescriptions[] = {
GUIO4(GUIO_RENDERHERCGREEN, GUIO_RENDERHERCAMBER, GUIO_RENDERCGA, GUIO_RENDEREGA)
},
+ // Amiga EU "Kult" build.
+ {
+ "chamber",
+ "Amiga",
+ AD_ENTRY2s("FOND.BIN", "a838b23a9fa5d25f88a02dee95307996", 32000,
+ "6.BIN", "t:926c11afce55dc08e1bb15b1253fd677", 10702),
+ Common::UNK_LANG, // EU EN/FR/DE
+ Common::kPlatformAmiga,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_RENDERAMIGA)
+ },
+
+ // Amiga US "Chamber" (Draconian) build.
+ {
+ "chamber",
+ "Amiga",
+ AD_ENTRY2s("FOND.BIN", "a838b23a9fa5d25f88a02dee95307996", 32000,
+ "6.BIN", "t:3eb1d3f844593949697540de3e74f74a", 16046),
+ Common::EN_USA,
+ Common::kPlatformAmiga,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_RENDERAMIGA)
+ },
+
AD_TABLE_END_MARKER
};
} // End of namespace Chamber
Commit: 268289e0a32e20ee9d0302c9059ee0d1df70391f
https://github.com/scummvm/scummvm/commit/268289e0a32e20ee9d0302c9059ee0d1df70391f
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-07-17T20:39:49+02:00
Commit Message:
CHAMBER: Add Amiga Zone Scan palette effect
Changed paths:
engines/chamber/script.cpp
diff --git a/engines/chamber/script.cpp b/engines/chamber/script.cpp
index cb99c45aa45..38702602c77 100644
--- a/engines/chamber/script.cpp
+++ b/engines/chamber/script.cpp
@@ -3706,6 +3706,11 @@ uint16 CMD_E_PsiZoneScan(void) {
IFGM_PlaySample(26);
+ // On Amiga the scan tints the whole room green for its duration: the exe
+ // ships a dedicated green stone-ramp delta (19) that no room ever uses
+ if (g_vm->_videoMode == Common::kRenderAmiga)
+ amigaApplyRoomPalette(19);
+
offs = g_vm->_renderer->calcXY_p(room_bounds_rect.sx, room_bounds_rect.sy);
w = room_bounds_rect.ex - room_bounds_rect.sx;
h = room_bounds_rect.ey - room_bounds_rect.sy;
@@ -3713,12 +3718,14 @@ uint16 CMD_E_PsiZoneScan(void) {
if (isEgaLikeRenderer())
w *= 4;
+ byte inv = isEgaLikeRenderer() ? 0x0F : 0xFF;
+
for (y = room_bounds_rect.sy; h; y++, h--) {
spot_t *spot;
- for (x = 0; x < w; x++) frontbuffer[offs + x] = ~frontbuffer[offs + x];
+ for (x = 0; x < w; x++) frontbuffer[offs + x] ^= inv;
g_vm->_renderer->blitToScreen(offs, w, 1);
waitVBlank();
- for (x = 0; x < w; x++) frontbuffer[offs + x] = ~frontbuffer[offs + x];
+ for (x = 0; x < w; x++) frontbuffer[offs + x] ^= inv;
g_vm->_renderer->blitToScreen(offs, w, 1);
for (spot = zone_spots; spot != zone_spots_end; spot++) {
@@ -3735,6 +3742,10 @@ uint16 CMD_E_PsiZoneScan(void) {
offs += g_vm->_screenBPL;
}
+ // Bring back the room's own palette once the scan is over
+ if (g_vm->_videoMode == Common::kRenderAmiga)
+ amigaApplyRoomPalette(script_byte_vars.palette_index);
+
restoreScreenOfSpecialRoom();
IFGM_StopSample();
Commit: 2e6146d46227d4ea511f7c78f2b0d44e56d09e0f
https://github.com/scummvm/scummvm/commit/2e6146d46227d4ea511f7c78f2b0d44e56d09e0f
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-07-17T20:39:49+02:00
Commit Message:
CHAMBER: Fix Coverity dead-code, leak and uninit findings
- script.cpp CMD_21_VortTalk: drop unreachable rand_value >= 170 branch;
disasm confirms num == 7 is dead code in the original too (CID 1505505)
- room.cpp drawRoomStatics: drop unreachable index == 91 door check;
index is already constrained to 50..60 here (CID 1505503)
- cga.cpp blitToScreen: drop always-false endY > 200 clamp (dy/h are
hardcoded to 0/200 just above) (CID 1657769)
- chamber.cpp: initialize _speaker in the constructor (CID 1618357)
- script.cpp/kult.cpp: free the Graphics::Surface returned by
loadFond/ega_loadFond/loadSplash instead of leaking it
(CID 1657721, 1657750)
Changed paths:
engines/chamber/cga.cpp
engines/chamber/chamber.cpp
engines/chamber/kult.cpp
engines/chamber/room.cpp
engines/chamber/script.cpp
diff --git a/engines/chamber/cga.cpp b/engines/chamber/cga.cpp
index 6df33ff38d2..3f7416942c0 100644
--- a/engines/chamber/cga.cpp
+++ b/engines/chamber/cga.cpp
@@ -226,9 +226,6 @@ void CGARenderer::blitToScreen(int16 dx, int16 dy, int16 w, int16 h) {
int16 startY = dy;
int16 endY = dy + h;
- if (endY > 200)
- endY = 200;
-
int16 startX_bytes = dx / 4;
int16 endX_bytes = (dx + w + 3) / 4;
diff --git a/engines/chamber/chamber.cpp b/engines/chamber/chamber.cpp
index 6e189bc3aa9..b3df8987e3a 100644
--- a/engines/chamber/chamber.cpp
+++ b/engines/chamber/chamber.cpp
@@ -65,6 +65,7 @@ ChamberEngine::ChamberEngine(OSystem *syst, const ADGameDescription *desc)
_prioritycommand_1 = false;
_prioritycommand_2 = false;
_pxiData = NULL;
+ _speaker = nullptr;
_renderMode = Common::parseRenderMode(ConfMan.get("render_mode"));
if (_renderMode == Common::kRenderEGA || _renderMode == Common::kRenderHercG || _renderMode == Common::kRenderHercA)
diff --git a/engines/chamber/kult.cpp b/engines/chamber/kult.cpp
index 6777b678a34..fea21354a59 100644
--- a/engines/chamber/kult.cpp
+++ b/engines/chamber/kult.cpp
@@ -427,10 +427,13 @@ Common::Error ChamberEngine::init() {
c = 'E';
} else {
/* Load language selection screen */
- if (!loadSplash("DRAP.BIN")) {
+ Graphics::Surface *drap = loadSplash("DRAP.BIN");
+ if (!drap) {
_shouldQuit = true;
return Common::kNoError;
}
+ drap->free();
+ delete drap;
/* Wait for a keypress and show the language selection screen */
clearKeyboard();
@@ -512,8 +515,12 @@ Common::Error ChamberEngine::init() {
// Early intro screens set no palette of their own; apply the room palette now
amigaApplyRoomPalette(0);
} else {
- while (!loadFond() || !loadSpritesData() || !loadPersData())
+ Graphics::Surface *fond;
+ while (!(fond = loadFond()) || !loadSpritesData() || !loadPersData()) {
+ delete fond;
askDisk2();
+ }
+ delete fond;
}
/*TODO: is this necessary?*/
diff --git a/engines/chamber/room.cpp b/engines/chamber/room.cpp
index 381960ea277..4772f2665cc 100644
--- a/engines/chamber/room.cpp
+++ b/engines/chamber/room.cpp
@@ -953,8 +953,6 @@ void drawRoomStatics(void) {
doors_list[doorcount++] = aptr - 3; /*TODO: check for list overflow?*/
if (doorcount == script_byte_vars.cur_spot_idx)
continue;
- if (script_byte_vars.zone_room == 32 && index == 91 && (script_byte_vars.bvar_27 & 8))
- continue; /*TODO: error? index may never be that high here*/
}
/*draw decor object*/
drawRoomStaticObject(aptr, &x, &y, &w, &h);
diff --git a/engines/chamber/script.cpp b/engines/chamber/script.cpp
index 38702602c77..24cb8999689 100644
--- a/engines/chamber/script.cpp
+++ b/engines/chamber/script.cpp
@@ -1505,8 +1505,10 @@ uint16 SCR_26_GameOver(void) {
script_byte_vars.zone_index = 135;
/*reload background*/
- while (!loadFond())
+ Graphics::Surface *fond;
+ while (!(fond = loadFond()))
askDisk2();
+ delete fond;
jaggedZoom(backbuffer, frontbuffer);
@@ -3031,18 +3033,25 @@ void theEnd(void) {
}
while(buttons == 0);
- while (!loadFond())
+ Graphics::Surface *fond;
+ while (!(fond = loadFond()))
askDisk2();
+ delete fond;
jaggedZoom(backbuffer, frontbuffer);
g_vm->_renderer->backBufferToRealFull();
} else if (g_vm->getPlatform() == Common::kPlatformAmiga) {
- while (!ega_loadFond("PRES.BIN"))
+ Graphics::Surface *fond;
+ while (!(fond = ega_loadFond("PRES.BIN")))
askDisk2();
+ delete fond;
g_vm->_renderer->colorSelect(AMIGA_NUM_PALETTES - 1);
g_vm->_renderer->backBufferToRealFull();
} else {
- while (!loadSplash("PRES.BIN"))
+ Graphics::Surface *splash;
+ while (!(splash = loadSplash("PRES.BIN")))
askDisk2();
+ splash->free();
+ delete splash;
g_vm->_renderer->backBufferToRealFull();
}
}
@@ -4266,8 +4275,6 @@ uint16 CMD_21_VortTalk(void) {
if (script_byte_vars.rand_value >= 85)
num = 6;
- else if (script_byte_vars.rand_value >= 170)
- num = 7;
else
num = 35;
Commit: 44c539adf76a2d7027ec569d1dc80b1e5a61159c
https://github.com/scummvm/scummvm/commit/44c539adf76a2d7027ec569d1dc80b1e5a61159c
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-07-17T20:39:49+02:00
Commit Message:
CHAMBER: Fix PVS-Studio dead-store and always-false findings
- cga.cpp blitToScreen: drop always-false endX_bytes > 80 clamp (dx/w are
hardcoded to 0/320 above, so endX_bytes == 80) (V547)
- cga.cpp cga_ZoomInplace: drop dead ofs++ (ofs is reassigned to oofs on
the next line) (V519)
- script.cpp SCR_23_HidePortrait: collapse the right_button branch; both
arms were identical (this handler has no special effect to skip) (V523)
- script.cpp SCR_46_DeProfundisLowerHook: don't store the discarded
getPuzzlSprite() return into sprofs (it is overwritten right after) (V519)
- script.cpp/menu.cpp: give the intentional empty busy-wait delay loops an
explicit {} body instead of a bare ; (V529)
Changed paths:
engines/chamber/cga.cpp
engines/chamber/menu.cpp
engines/chamber/script.cpp
diff --git a/engines/chamber/cga.cpp b/engines/chamber/cga.cpp
index 3f7416942c0..7f0059eabdc 100644
--- a/engines/chamber/cga.cpp
+++ b/engines/chamber/cga.cpp
@@ -229,9 +229,6 @@ void CGARenderer::blitToScreen(int16 dx, int16 dy, int16 w, int16 h) {
int16 startX_bytes = dx / 4;
int16 endX_bytes = (dx + w + 3) / 4;
- if (endX_bytes > 80)
- endX_bytes = 80;
-
for (int y = startY; y < endY; y++) {
uint16 bank = (y % 2) * 8192;
uint16 line = (y / 2) * 80;
@@ -1664,7 +1661,6 @@ void cga_ZoomInplace(zoom_t *params, byte tw, byte th, byte *source, byte *targe
/*right partial pixel*/
target[ofs] = (source[ofs] & ~(0xFF << (sc * 2))) | (pix << (sc * 2));
- ofs++;
params->fw++;
/*ofs -= params->fw;*/
diff --git a/engines/chamber/menu.cpp b/engines/chamber/menu.cpp
index 8f1cfde8e83..625cac856fb 100644
--- a/engines/chamber/menu.cpp
+++ b/engines/chamber/menu.cpp
@@ -168,11 +168,11 @@ void actionsMenu(byte **pinfo) {
/*draw dot explosion animation*/
drawSpriteN(24, act_dot_rects[choice].sx, act_dot_rects[choice].sy, SCREENBUFFER);
- for (i = 0; i < 0xFFF; i++) ; /*TODO: weak delay*/
+ for (i = 0; i < 0xFFF; i++) {} /*TODO: weak delay*/
drawSpriteN(2, act_dot_rects[choice].sx, act_dot_rects[choice].sy, SCREENBUFFER);
- for (i = 0; i < 0xFFF; i++) ; /*TODO: weak delay*/
+ for (i = 0; i < 0xFFF; i++) {} /*TODO: weak delay*/
drawSpriteN(25, act_dot_rects[choice].sx, act_dot_rects[choice].sy, SCREENBUFFER);
- for (i = 0; i < 0xFFF; i++) ; /*TODO: weak delay*/
+ for (i = 0; i < 0xFFF; i++) {} /*TODO: weak delay*/
}
g_vm->_renderer->restoreBackupImage(SCREENBUFFER);
diff --git a/engines/chamber/script.cpp b/engines/chamber/script.cpp
index 24cb8999689..0a4cce1a643 100644
--- a/engines/chamber/script.cpp
+++ b/engines/chamber/script.cpp
@@ -1921,11 +1921,6 @@ uint16 SCR_23_HidePortrait(void) {
index = *script_ptr++;
getDirtyRectAndFree(index, &kind, &x, &y, &width, &height, &offs);
- if (right_button) {
- g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
- return 0;
- }
-
g_vm->_renderer->copyScreenBlock(backbuffer, width, height, SCREENBUFFER, offs);
return 0;
@@ -2464,7 +2459,7 @@ uint16 SCR_46_DeProfundisLowerHook(void) {
script_ptr++;
/*draw Hook*/
- sprofs = getPuzzlSprite(96, 140 / 4, 18, &w, &h, &ofs);
+ getPuzzlSprite(96, 140 / 4, 18, &w, &h, &ofs);
h = 1;
y = 15;
@@ -3007,7 +3002,7 @@ static void AnimSaucer(void) {
height_prev = height_new;
waitVBlank();
- for (i = delay; i--;) ; /*TODO: weak delay*/
+ for (i = delay; i--;) {} /*TODO: weak delay*/
delay += 500;
}
}
Commit: c11f6d3bb8018e52bee7d57efeca1547e7abc12c
https://github.com/scummvm/scummvm/commit/c11f6d3bb8018e52bee7d57efeca1547e7abc12c
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-07-17T20:39:49+02:00
Commit Message:
CHAMBER: Save backbuffer so scripted room changes survive load
Scripts draw persistent room changes (alternate decor sets, extra
objects, animation finals) directly into the backbuffer; rebuilding
the room from the base decor on load discarded them, so e.g. the De
Profundis monster or Deilos would not reappear after loading. Bump
the save version to 2 and store zone_palette, the video mode and the
backbuffer contents; restore the backbuffer verbatim when the video
mode matches, falling back to the old redraw otherwise. Also reapply
the room palette on load and honor the launcher save_slot option.
Changed paths:
engines/chamber/kult.cpp
engines/chamber/saveload.cpp
diff --git a/engines/chamber/kult.cpp b/engines/chamber/kult.cpp
index fea21354a59..673d7899f98 100644
--- a/engines/chamber/kult.cpp
+++ b/engines/chamber/kult.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "common/config-manager.h"
#include "common/error.h"
#include "common/file.h"
#include "common/system.h"
@@ -580,6 +581,12 @@ Common::Error ChamberEngine::execute() {
/* Initialize cursor backup */
processInput();
+ if (ConfMan.hasKey("save_slot") && ConfMan.getInt("save_slot") >= 0) {
+ int slot = ConfMan.getInt("save_slot");
+ ConfMan.set("save_slot", "-1");
+ loadGameState(slot);
+ }
+
#ifdef DEBUG_ENDING
script_byte_vars.game_paused = 5;
theEnd();
diff --git a/engines/chamber/saveload.cpp b/engines/chamber/saveload.cpp
index 0d571d03bb4..a6194ba550a 100644
--- a/engines/chamber/saveload.cpp
+++ b/engines/chamber/saveload.cpp
@@ -33,7 +33,7 @@
namespace Chamber {
-static const byte kSaveVersion = 1;
+static const byte kSaveVersion = 2;
// Serializes a pointer as a byte offset from base; 0xFFFF represents null
template<typename T>
@@ -81,12 +81,23 @@ Common::Error ChamberEngine::loadGameStream(Common::SeekableReadStream *stream)
if (!s.syncVersion(kSaveVersion))
return Common::Error(Common::kReadingFailed, "Save from a newer engine version");
syncGameStream(s);
+ bool backbufferRestored = false;
+ if (s.getVersion() >= 2) {
+ s.syncAsByte(zone_palette);
+ byte mode = 0;
+ s.syncAsByte(mode);
+ s.syncBytes(backbuffer, sizeof(backbuffer));
+ backbufferRestored = (mode == (byte)_videoMode);
+ }
if (s.err())
return Common::kReadingFailed;
// Prevent door transition animation from firing on load (mirrors restartGame behavior)
script_byte_vars.cur_spot_flags = 0xFF;
- memset(backbuffer, 0, sizeof(backbuffer));
- drawRoomStatics();
+ if (!backbufferRestored) {
+ memset(backbuffer, 0, sizeof(backbuffer));
+ drawRoomStatics();
+ }
+ selectPalette();
backupSpotsImages();
drawPersons();
_renderer->backBufferToRealFull();
@@ -98,6 +109,10 @@ Common::Error ChamberEngine::saveGameStream(Common::WriteStream *stream, bool is
Common::Serializer s(nullptr, stream);
s.syncVersion(kSaveVersion);
syncGameStream(s);
+ s.syncAsByte(zone_palette);
+ byte mode = (byte)_videoMode;
+ s.syncAsByte(mode);
+ s.syncBytes(backbuffer, sizeof(backbuffer));
if (s.err())
return Common::kWritingFailed;
return Common::kNoError;
Commit: ef9ad271b061272eee66693b5af1696252b9801a
https://github.com/scummvm/scummvm/commit/ef9ad271b061272eee66693b5af1696252b9801a
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-07-17T20:39:49+02:00
Commit Message:
CHAMBER: Address Amiga US PR review comments
Changed paths:
engines/chamber/kult.cpp
engines/chamber/menu.cpp
engines/chamber/resdata.cpp
engines/chamber/script.cpp
diff --git a/engines/chamber/kult.cpp b/engines/chamber/kult.cpp
index 673d7899f98..4297ee973c1 100644
--- a/engines/chamber/kult.cpp
+++ b/engines/chamber/kult.cpp
@@ -105,31 +105,7 @@ Graphics::Surface *loadSplash(const char *filename) {
return surface;
}
-// TEMP headless debug helper, remove: dump current screen+palette as PPM
-void debugDumpScreen(const char *tag) {
- if (gDebugLevel < 9)
- return;
- static int n = 0;
- Graphics::Surface *s = g_system->lockScreen();
- byte pal[768];
- g_system->getPaletteManager()->grabPalette(pal, 0, 256);
- Common::DumpFile f;
- if (f.open(Common::Path(Common::String::format("/tmp/chamber_dbg/%03d_%s.ppm", n++, tag)))) {
- f.writeString(Common::String::format("P6\n%d %d\n255\n", s->w, s->h));
- for (int y = 0; y < s->h; y++)
- for (int x = 0; x < s->w; x++) {
- byte c = *(const byte *)s->getBasePtr(x, y);
- f.writeByte(pal[c * 3]);
- f.writeByte(pal[c * 3 + 1]);
- f.writeByte(pal[c * 3 + 2]);
- }
- }
- g_system->unlockScreen();
-}
-
uint16 benchmarkCpu(void) {
- if (gDebugLevel >= 9) // TEMP headless debug stub, remove
- return 1000;
byte t;
uint16 cycles = 0;
for (t = script_byte_vars.timer_ticks; t == script_byte_vars.timer_ticks;) ;
@@ -430,8 +406,9 @@ Common::Error ChamberEngine::init() {
/* Load language selection screen */
Graphics::Surface *drap = loadSplash("DRAP.BIN");
if (!drap) {
+ warning("File DRAP.BIN not found");
_shouldQuit = true;
- return Common::kNoError;
+ return Common::kReadingFailed;
}
drap->free();
delete drap;
diff --git a/engines/chamber/menu.cpp b/engines/chamber/menu.cpp
index 625cac856fb..2769342751c 100644
--- a/engines/chamber/menu.cpp
+++ b/engines/chamber/menu.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "common/system.h"
#include "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/menu.h"
@@ -168,11 +169,11 @@ void actionsMenu(byte **pinfo) {
/*draw dot explosion animation*/
drawSpriteN(24, act_dot_rects[choice].sx, act_dot_rects[choice].sy, SCREENBUFFER);
- for (i = 0; i < 0xFFF; i++) {} /*TODO: weak delay*/
+ g_system->delayMillis(50);
drawSpriteN(2, act_dot_rects[choice].sx, act_dot_rects[choice].sy, SCREENBUFFER);
- for (i = 0; i < 0xFFF; i++) {} /*TODO: weak delay*/
+ g_system->delayMillis(50);
drawSpriteN(25, act_dot_rects[choice].sx, act_dot_rects[choice].sy, SCREENBUFFER);
- for (i = 0; i < 0xFFF; i++) {} /*TODO: weak delay*/
+ g_system->delayMillis(50);
}
g_vm->_renderer->restoreBackupImage(SCREENBUFFER);
diff --git a/engines/chamber/resdata.cpp b/engines/chamber/resdata.cpp
index 1f0e7df3c22..8adf9a8eab4 100644
--- a/engines/chamber/resdata.cpp
+++ b/engines/chamber/resdata.cpp
@@ -333,6 +333,7 @@ Load strings data (obj. descriptions)
*/
int16 loadDesciData(void) {
if (g_vm->getPlatform() == Common::kPlatformAmiga) {
+ // US embeds these banks in the exe (loaded by loadAmigaStaticData())
if (g_vm->getLanguage() == Common::EN_USA)
return 1;
return loadFilesList(res_desci_amiga);
@@ -357,6 +358,7 @@ Load strings data (dialogs)
*/
int16 loadDialiData(void) {
if (g_vm->getPlatform() == Common::kPlatformAmiga) {
+ // US embeds these banks in the exe (loaded by loadAmigaStaticData())
if (g_vm->getLanguage() == Common::EN_USA)
return 1;
return loadFilesList(res_diali_amiga);
diff --git a/engines/chamber/script.cpp b/engines/chamber/script.cpp
index 0a4cce1a643..0d5cfead939 100644
--- a/engines/chamber/script.cpp
+++ b/engines/chamber/script.cpp
@@ -3002,7 +3002,7 @@ static void AnimSaucer(void) {
height_prev = height_new;
waitVBlank();
- for (i = delay; i--;) {} /*TODO: weak delay*/
+ g_system->delayMillis(delay / 250);
delay += 500;
}
}
@@ -4508,8 +4508,7 @@ uint16 RunScript(byte *code) {
while (script_ptr != script_end_ptr) {
byte opcode = *script_ptr;
- if (gDebugLevel >= 9) // TEMP headless debug trace, remove
- debug("scr %04X: %02X", (uint16)((script_ptr - templ_data) & 0xFFFF), opcode);
+ debug(9, "scr %04X: %02X", (uint16)((script_ptr - templ_data) & 0xFFFF), opcode);
#ifdef DEBUG_SCRIPT
{
More information about the Scummvm-git-logs
mailing list