[Scummvm-git-logs] scummvm master -> 406dba241029029329b626f569a4cc9403bb5246
sev-
noreply at scummvm.org
Tue Apr 28 22:22:56 UTC 2026
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
2f7f01f11c CHAMBER: Implement save/load game state serialization
23d7606abb CHAMBER: Connect in-game save/load stubs to ScummVM API
f1d988c6b8 CHAMBER: Address save/load review feedback and fix post-load rendering
3759c403f5 CHAMBER: Move save/load methods to savegame and remove commented code
406dba2410 CHAMBER: Rename savegame to saveload
Commit: 2f7f01f11c311fb4e008aa58a26f57e912ccf5d9
https://github.com/scummvm/scummvm/commit/2f7f01f11c311fb4e008aa58a26f57e912ccf5d9
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-29T00:22:50+02:00
Commit Message:
CHAMBER: Implement save/load game state serialization
Implement syncGameStream() to serialize all game state using
Common::Serializer. Pointers are stored as uint16 byte offsets from
their base arrays (0xFFFF = null) via syncPtrOffset(). After loading,
reset cur_spot_flags to prevent a spurious door-open animation, redraw
the room, blit sprites, and flush the backbuffer to screen.
Changed paths:
engines/chamber/chamber.cpp
diff --git a/engines/chamber/chamber.cpp b/engines/chamber/chamber.cpp
index 611df714263..31334e559dc 100644
--- a/engines/chamber/chamber.cpp
+++ b/engines/chamber/chamber.cpp
@@ -34,6 +34,11 @@
#include "chamber/chamber.h"
#include "chamber/renderer.h"
+#include "chamber/script.h"
+#include "chamber/resdata.h"
+#include "chamber/room.h"
+#include "chamber/dialog.h"
+#include "chamber/cga.h"
namespace Chamber {
@@ -89,9 +94,24 @@ bool ChamberEngine::hasFeature(EngineFeature f) const {
(f == kSupportsSavingDuringRuntime);
}
+// Serializes a pointer as a byte offset from base; 0xFFFF represents null
+template<typename T>
+static void syncPtrOffset(Common::Serializer &s, T *&ptr, void *base) {
+ uint16 ofs = s.isSaving() ? (ptr ? (uint16)((byte *)ptr - (byte *)base) : 0xFFFF) : 0;
+ s.syncAsUint16LE(ofs);
+ if (s.isLoading())
+ ptr = (ofs == 0xFFFF) ? nullptr : (T *)((byte *)base + ofs);
+}
+
Common::Error ChamberEngine::loadGameStream(Common::SeekableReadStream *stream) {
Common::Serializer s(stream, nullptr);
syncGameStream(s);
+ // Prevent door transition animation from firing on load (mirrors restartGame behavior)
+ script_byte_vars.cur_spot_flags = 0xFF;
+ memset(backbuffer, 0, sizeof(backbuffer));
+ drawRoomStatics();
+ blitSpritesToBackBuffer();
+ _renderer->backBufferToRealFull();
return Common::kNoError;
}
@@ -102,9 +122,82 @@ Common::Error ChamberEngine::saveGameStream(Common::WriteStream *stream, bool is
}
void ChamberEngine::syncGameStream(Common::Serializer &s) {
- // Use methods of Serializer to save/load fields
- int16 dummy = 0;
- s.syncAsUint16LE(dummy);
+ s.syncBytes((byte *)&script_byte_vars, sizeof(script_byte_vars));
+ s.syncBytes((byte *)&script_word_vars, sizeof(script_word_vars));
+ s.syncBytes(zones_data, RES_ZONES_MAX);
+ s.syncBytes((byte *)inventory_items, sizeof(item_t) * MAX_INV_ITEMS);
+ s.syncBytes((byte *)pers_list, sizeof(pers_t) * PERS_MAX);
+ s.syncBytes((byte *)dirty_rects, sizeof(dirty_rect_t) * MAX_DIRTY_RECT);
+ s.syncBytes((byte *)menu_commands_12, sizeof(uint16) * SPECIAL_COMMANDS_MAX);
+ s.syncBytes((byte *)menu_commands_22, sizeof(uint16) * SPECIAL_COMMANDS_MAX);
+ s.syncBytes((byte *)menu_commands_24, sizeof(uint16) * SPECIAL_COMMANDS_MAX);
+ s.syncBytes((byte *)menu_commands_23, sizeof(uint16) * SPECIAL_COMMANDS_MAX);
+ s.syncBytes((byte *)&room_bounds_rect, sizeof(rect_t));
+
+ s.syncAsUint16LE(next_vorts_cmd);
+ s.syncAsUint16LE(next_vorts_ticks);
+ s.syncAsUint16LE(next_turkey_cmd);
+ s.syncAsUint16LE(next_turkey_ticks);
+ s.syncAsUint16LE(next_protozorqs_ticks);
+ s.syncAsUint16LE(fight_pers_ofs);
+ s.syncAsUint16LE(drops_cleanup_time);
+
+ s.syncAsByte(wait_delta);
+ s.syncAsByte(in_de_profundis);
+ s.syncAsByte(zone_name);
+ s.syncAsByte(room_hint_bar_width);
+ s.syncAsByte(room_hint_bar_coords_x);
+ s.syncAsByte(room_hint_bar_coords_y);
+ s.syncAsByte(last_object_hint);
+ s.syncAsByte(object_hint);
+ s.syncAsByte(command_hint);
+ s.syncAsByte(last_command_hint);
+ s.syncAsByte(zone_spr_index);
+ s.syncAsByte(zone_obj_count);
+
+ for (int i = 0; i < 2; i++) {
+ s.syncAsByte(the_wall_doors[i].height);
+ s.syncAsByte(the_wall_doors[i].width);
+ s.syncAsUint16LE(the_wall_doors[i].pitch);
+ s.syncAsUint16LE(the_wall_doors[i].offs);
+ syncPtrOffset(s, the_wall_doors[i].pixels, sprit_load_buffer);
+ }
+
+ syncPtrOffset(s, script_vars[kScrPool0_WordVars0], &script_word_vars);
+ syncPtrOffset(s, script_vars[kScrPool1_WordVars1], &script_word_vars);
+ syncPtrOffset(s, script_vars[kScrPool2_ByteVars], &script_byte_vars);
+ syncPtrOffset(s, script_vars[kScrPool3_CurrentItem], inventory_items);
+ syncPtrOffset(s, script_vars[kScrPool4_ZoneSpots], zones_data);
+ syncPtrOffset(s, script_vars[kScrPool5_Persons], pers_list);
+ syncPtrOffset(s, script_vars[kScrPool6_Inventory], inventory_items);
+ syncPtrOffset(s, script_vars[kScrPool7_Zapstiks], inventory_items);
+ syncPtrOffset(s, script_vars[kScrPool8_CurrentPers], pers_list);
+
+ for (int i = 0; i < MAX_SPRITES; i++)
+ syncPtrOffset(s, sprites_list[i], scratch_mem1);
+ for (int i = 0; i < MAX_DOORS; i++)
+ syncPtrOffset(s, doors_list[i], arpla_data);
+
+ syncPtrOffset(s, zone_spots, zones_data);
+ syncPtrOffset(s, zone_spots_end, zones_data);
+ syncPtrOffset(s, zone_spots_cur, zones_data);
+
+ syncPtrOffset(s, script_stack_ptr, script_stack);
+ for (int i = 0; i < 5 * 2; i++)
+ syncPtrOffset(s, script_stack[i], templ_data);
+
+ syncPtrOffset(s, vort_ptr, pers_list);
+ syncPtrOffset(s, vortanims_ptr, vortsanim_list);
+ syncPtrOffset(s, turkeyanims_ptr, turkeyanim_list);
+ syncPtrOffset(s, aspirant_ptr, pers_list);
+ syncPtrOffset(s, aspirant_spot, zones_data);
+ syncPtrOffset(s, found_spot, zones_data);
+ syncPtrOffset(s, spot_sprite, sprites_list);
+
+ uint16 timedSeqOfs = s.isSaving() ? (timed_seq_ptr ? (uint16)(timed_seq_ptr - patrol_route) : 0xFFFF) : 0;
+ s.syncAsUint16LE(timedSeqOfs);
+ if (s.isLoading())
+ timed_seq_ptr = (timedSeqOfs == 0xFFFF) ? nullptr : patrol_route + timedSeqOfs;
}
int ChamberEngine::getX(int original_x) {
Commit: 23d7606abbaf4fbb121bdee42de89aee71cd3570
https://github.com/scummvm/scummvm/commit/23d7606abbaf4fbb121bdee42de89aee71cd3570
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-29T00:22:50+02:00
Commit Message:
CHAMBER: Connect in-game save/load stubs to ScummVM API
Replace the warning stubs in loadScena() and saveScena() with calls to
g_vm->loadGameState() and g_vm->saveGameState(), wiring the original
game's save/load triggers into the ScummVM save system.
Changed paths:
engines/chamber/savegame.cpp
diff --git a/engines/chamber/savegame.cpp b/engines/chamber/savegame.cpp
index 699c5d37751..de505a8543a 100644
--- a/engines/chamber/savegame.cpp
+++ b/engines/chamber/savegame.cpp
@@ -588,8 +588,8 @@ error:;
#endif
int16 loadScena(void) {
- warning("STUB: loadScena()");
- return 1;
+ Common::Error err = g_vm->loadGameState(0);
+ return err.getCode() == Common::kNoError ? 0 : 1;
#if 0
int16 f;
int16 res;
@@ -622,8 +622,8 @@ int16 loadScena(void) {
}
int16 saveScena(void) {
- warning("STUB: saveScena()");
- return 1;
+ Common::Error err = g_vm->saveGameState(0, Common::U32String("Save"));
+ return err.getCode() == Common::kNoError ? 0 : 1;
#if 0
int16 f;
int16 res;
Commit: f1d988c6b817ba31f53bf78907d160847114ad33
https://github.com/scummvm/scummvm/commit/f1d988c6b817ba31f53bf78907d160847114ad33
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-29T00:22:50+02:00
Commit Message:
CHAMBER: Address save/load review feedback and fix post-load rendering
Open the ScummVM save/load chooser instead of hardcoding slot 0, version
the savegame with syncVersion(), check stream errors, and serialize
small structs (item_t, pers_t, dirty_rect_t, rect_t) field-by-field so
the format is host-portable. After loading, replace the stale-buffer
blit with backupSpotsImages() + drawPersons() and refresh the cursor via
selectCursor(), so the loaded scene renders correctly and the mouse
pointer stays visible.
Changed paths:
engines/chamber/chamber.cpp
engines/chamber/savegame.cpp
diff --git a/engines/chamber/chamber.cpp b/engines/chamber/chamber.cpp
index 31334e559dc..22ce2f5c968 100644
--- a/engines/chamber/chamber.cpp
+++ b/engines/chamber/chamber.cpp
@@ -39,6 +39,7 @@
#include "chamber/room.h"
#include "chamber/dialog.h"
#include "chamber/cga.h"
+#include "chamber/cursor.h"
namespace Chamber {
@@ -94,6 +95,8 @@ bool ChamberEngine::hasFeature(EngineFeature f) const {
(f == kSupportsSavingDuringRuntime);
}
+static const byte kSaveVersion = 1;
+
// Serializes a pointer as a byte offset from base; 0xFFFF represents null
template<typename T>
static void syncPtrOffset(Common::Serializer &s, T *&ptr, void *base) {
@@ -103,21 +106,62 @@ static void syncPtrOffset(Common::Serializer &s, T *&ptr, void *base) {
ptr = (ofs == 0xFFFF) ? nullptr : (T *)((byte *)base + ofs);
}
+static void syncItem(Common::Serializer &s, item_t &it) {
+ s.syncAsByte(it.flags);
+ s.syncAsByte(it.area);
+ s.syncAsByte(it.sprite);
+ s.syncAsByte(it.name);
+ s.syncAsUint16LE(it.command);
+}
+
+static void syncPers(Common::Serializer &s, pers_t &p) {
+ s.syncAsByte(p.area);
+ s.syncAsByte(p.flags);
+ s.syncAsByte(p.name);
+ s.syncAsByte(p.index);
+ s.syncAsByte(p.item);
+}
+
+static void syncDirtyRect(Common::Serializer &s, dirty_rect_t &dr) {
+ s.syncAsByte(dr.kind);
+ s.syncAsUint16LE(dr.offs);
+ s.syncAsByte(dr.height);
+ s.syncAsByte(dr.width);
+ s.syncAsByte(dr.y);
+ s.syncAsByte(dr.x);
+}
+
+static void syncRect(Common::Serializer &s, rect_t &r) {
+ s.syncAsByte(r.sx);
+ s.syncAsByte(r.ex);
+ s.syncAsByte(r.sy);
+ s.syncAsByte(r.ey);
+}
+
Common::Error ChamberEngine::loadGameStream(Common::SeekableReadStream *stream) {
Common::Serializer s(stream, nullptr);
+ if (!s.syncVersion(kSaveVersion))
+ return Common::Error(Common::kReadingFailed, "Save from a newer engine version");
syncGameStream(s);
+ 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();
- blitSpritesToBackBuffer();
+ backupSpotsImages();
+ drawPersons();
_renderer->backBufferToRealFull();
+ _renderer->selectCursor(CURSOR_FINGER);
return Common::kNoError;
}
Common::Error ChamberEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
Common::Serializer s(nullptr, stream);
+ s.syncVersion(kSaveVersion);
syncGameStream(s);
+ if (s.err())
+ return Common::kWritingFailed;
return Common::kNoError;
}
@@ -125,14 +169,21 @@ void ChamberEngine::syncGameStream(Common::Serializer &s) {
s.syncBytes((byte *)&script_byte_vars, sizeof(script_byte_vars));
s.syncBytes((byte *)&script_word_vars, sizeof(script_word_vars));
s.syncBytes(zones_data, RES_ZONES_MAX);
- s.syncBytes((byte *)inventory_items, sizeof(item_t) * MAX_INV_ITEMS);
- s.syncBytes((byte *)pers_list, sizeof(pers_t) * PERS_MAX);
- s.syncBytes((byte *)dirty_rects, sizeof(dirty_rect_t) * MAX_DIRTY_RECT);
- s.syncBytes((byte *)menu_commands_12, sizeof(uint16) * SPECIAL_COMMANDS_MAX);
- s.syncBytes((byte *)menu_commands_22, sizeof(uint16) * SPECIAL_COMMANDS_MAX);
- s.syncBytes((byte *)menu_commands_24, sizeof(uint16) * SPECIAL_COMMANDS_MAX);
- s.syncBytes((byte *)menu_commands_23, sizeof(uint16) * SPECIAL_COMMANDS_MAX);
- s.syncBytes((byte *)&room_bounds_rect, sizeof(rect_t));
+
+ for (int i = 0; i < MAX_INV_ITEMS; i++)
+ syncItem(s, inventory_items[i]);
+ for (int i = 0; i < PERS_MAX; i++)
+ syncPers(s, pers_list[i]);
+ for (int i = 0; i < MAX_DIRTY_RECT; i++)
+ syncDirtyRect(s, dirty_rects[i]);
+
+ for (int i = 0; i < SPECIAL_COMMANDS_MAX; i++) {
+ s.syncAsUint16LE(menu_commands_12[i]);
+ s.syncAsUint16LE(menu_commands_22[i]);
+ s.syncAsUint16LE(menu_commands_24[i]);
+ s.syncAsUint16LE(menu_commands_23[i]);
+ }
+ syncRect(s, room_bounds_rect);
s.syncAsUint16LE(next_vorts_cmd);
s.syncAsUint16LE(next_vorts_ticks);
diff --git a/engines/chamber/savegame.cpp b/engines/chamber/savegame.cpp
index de505a8543a..ada736e41ac 100644
--- a/engines/chamber/savegame.cpp
+++ b/engines/chamber/savegame.cpp
@@ -588,8 +588,7 @@ error:;
#endif
int16 loadScena(void) {
- Common::Error err = g_vm->loadGameState(0);
- return err.getCode() == Common::kNoError ? 0 : 1;
+ return g_vm->loadGameDialog() ? 0 : 1;
#if 0
int16 f;
int16 res;
@@ -622,8 +621,7 @@ int16 loadScena(void) {
}
int16 saveScena(void) {
- Common::Error err = g_vm->saveGameState(0, Common::U32String("Save"));
- return err.getCode() == Common::kNoError ? 0 : 1;
+ return g_vm->saveGameDialog() ? 0 : 1;
#if 0
int16 f;
int16 res;
Commit: 3759c403f51f594586effa57c6c169f277c09cfc
https://github.com/scummvm/scummvm/commit/3759c403f51f594586effa57c6c169f277c09cfc
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-29T00:22:50+02:00
Commit Message:
CHAMBER: Move save/load methods to savegame and remove commented code
Move loadGameStream, saveGameStream, syncGameStream and helper functions
from chamber.cpp into savegame.cpp. Remove commented-out original
save/load implementation.
Changed paths:
engines/chamber/chamber.cpp
engines/chamber/savegame.cpp
diff --git a/engines/chamber/chamber.cpp b/engines/chamber/chamber.cpp
index 22ce2f5c968..012299811c4 100644
--- a/engines/chamber/chamber.cpp
+++ b/engines/chamber/chamber.cpp
@@ -95,162 +95,6 @@ bool ChamberEngine::hasFeature(EngineFeature f) const {
(f == kSupportsSavingDuringRuntime);
}
-static const byte kSaveVersion = 1;
-
-// Serializes a pointer as a byte offset from base; 0xFFFF represents null
-template<typename T>
-static void syncPtrOffset(Common::Serializer &s, T *&ptr, void *base) {
- uint16 ofs = s.isSaving() ? (ptr ? (uint16)((byte *)ptr - (byte *)base) : 0xFFFF) : 0;
- s.syncAsUint16LE(ofs);
- if (s.isLoading())
- ptr = (ofs == 0xFFFF) ? nullptr : (T *)((byte *)base + ofs);
-}
-
-static void syncItem(Common::Serializer &s, item_t &it) {
- s.syncAsByte(it.flags);
- s.syncAsByte(it.area);
- s.syncAsByte(it.sprite);
- s.syncAsByte(it.name);
- s.syncAsUint16LE(it.command);
-}
-
-static void syncPers(Common::Serializer &s, pers_t &p) {
- s.syncAsByte(p.area);
- s.syncAsByte(p.flags);
- s.syncAsByte(p.name);
- s.syncAsByte(p.index);
- s.syncAsByte(p.item);
-}
-
-static void syncDirtyRect(Common::Serializer &s, dirty_rect_t &dr) {
- s.syncAsByte(dr.kind);
- s.syncAsUint16LE(dr.offs);
- s.syncAsByte(dr.height);
- s.syncAsByte(dr.width);
- s.syncAsByte(dr.y);
- s.syncAsByte(dr.x);
-}
-
-static void syncRect(Common::Serializer &s, rect_t &r) {
- s.syncAsByte(r.sx);
- s.syncAsByte(r.ex);
- s.syncAsByte(r.sy);
- s.syncAsByte(r.ey);
-}
-
-Common::Error ChamberEngine::loadGameStream(Common::SeekableReadStream *stream) {
- Common::Serializer s(stream, nullptr);
- if (!s.syncVersion(kSaveVersion))
- return Common::Error(Common::kReadingFailed, "Save from a newer engine version");
- syncGameStream(s);
- 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();
- backupSpotsImages();
- drawPersons();
- _renderer->backBufferToRealFull();
- _renderer->selectCursor(CURSOR_FINGER);
- return Common::kNoError;
-}
-
-Common::Error ChamberEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
- Common::Serializer s(nullptr, stream);
- s.syncVersion(kSaveVersion);
- syncGameStream(s);
- if (s.err())
- return Common::kWritingFailed;
- return Common::kNoError;
-}
-
-void ChamberEngine::syncGameStream(Common::Serializer &s) {
- s.syncBytes((byte *)&script_byte_vars, sizeof(script_byte_vars));
- s.syncBytes((byte *)&script_word_vars, sizeof(script_word_vars));
- s.syncBytes(zones_data, RES_ZONES_MAX);
-
- for (int i = 0; i < MAX_INV_ITEMS; i++)
- syncItem(s, inventory_items[i]);
- for (int i = 0; i < PERS_MAX; i++)
- syncPers(s, pers_list[i]);
- for (int i = 0; i < MAX_DIRTY_RECT; i++)
- syncDirtyRect(s, dirty_rects[i]);
-
- for (int i = 0; i < SPECIAL_COMMANDS_MAX; i++) {
- s.syncAsUint16LE(menu_commands_12[i]);
- s.syncAsUint16LE(menu_commands_22[i]);
- s.syncAsUint16LE(menu_commands_24[i]);
- s.syncAsUint16LE(menu_commands_23[i]);
- }
- syncRect(s, room_bounds_rect);
-
- s.syncAsUint16LE(next_vorts_cmd);
- s.syncAsUint16LE(next_vorts_ticks);
- s.syncAsUint16LE(next_turkey_cmd);
- s.syncAsUint16LE(next_turkey_ticks);
- s.syncAsUint16LE(next_protozorqs_ticks);
- s.syncAsUint16LE(fight_pers_ofs);
- s.syncAsUint16LE(drops_cleanup_time);
-
- s.syncAsByte(wait_delta);
- s.syncAsByte(in_de_profundis);
- s.syncAsByte(zone_name);
- s.syncAsByte(room_hint_bar_width);
- s.syncAsByte(room_hint_bar_coords_x);
- s.syncAsByte(room_hint_bar_coords_y);
- s.syncAsByte(last_object_hint);
- s.syncAsByte(object_hint);
- s.syncAsByte(command_hint);
- s.syncAsByte(last_command_hint);
- s.syncAsByte(zone_spr_index);
- s.syncAsByte(zone_obj_count);
-
- for (int i = 0; i < 2; i++) {
- s.syncAsByte(the_wall_doors[i].height);
- s.syncAsByte(the_wall_doors[i].width);
- s.syncAsUint16LE(the_wall_doors[i].pitch);
- s.syncAsUint16LE(the_wall_doors[i].offs);
- syncPtrOffset(s, the_wall_doors[i].pixels, sprit_load_buffer);
- }
-
- syncPtrOffset(s, script_vars[kScrPool0_WordVars0], &script_word_vars);
- syncPtrOffset(s, script_vars[kScrPool1_WordVars1], &script_word_vars);
- syncPtrOffset(s, script_vars[kScrPool2_ByteVars], &script_byte_vars);
- syncPtrOffset(s, script_vars[kScrPool3_CurrentItem], inventory_items);
- syncPtrOffset(s, script_vars[kScrPool4_ZoneSpots], zones_data);
- syncPtrOffset(s, script_vars[kScrPool5_Persons], pers_list);
- syncPtrOffset(s, script_vars[kScrPool6_Inventory], inventory_items);
- syncPtrOffset(s, script_vars[kScrPool7_Zapstiks], inventory_items);
- syncPtrOffset(s, script_vars[kScrPool8_CurrentPers], pers_list);
-
- for (int i = 0; i < MAX_SPRITES; i++)
- syncPtrOffset(s, sprites_list[i], scratch_mem1);
- for (int i = 0; i < MAX_DOORS; i++)
- syncPtrOffset(s, doors_list[i], arpla_data);
-
- syncPtrOffset(s, zone_spots, zones_data);
- syncPtrOffset(s, zone_spots_end, zones_data);
- syncPtrOffset(s, zone_spots_cur, zones_data);
-
- syncPtrOffset(s, script_stack_ptr, script_stack);
- for (int i = 0; i < 5 * 2; i++)
- syncPtrOffset(s, script_stack[i], templ_data);
-
- syncPtrOffset(s, vort_ptr, pers_list);
- syncPtrOffset(s, vortanims_ptr, vortsanim_list);
- syncPtrOffset(s, turkeyanims_ptr, turkeyanim_list);
- syncPtrOffset(s, aspirant_ptr, pers_list);
- syncPtrOffset(s, aspirant_spot, zones_data);
- syncPtrOffset(s, found_spot, zones_data);
- syncPtrOffset(s, spot_sprite, sprites_list);
-
- uint16 timedSeqOfs = s.isSaving() ? (timed_seq_ptr ? (uint16)(timed_seq_ptr - patrol_route) : 0xFFFF) : 0;
- s.syncAsUint16LE(timedSeqOfs);
- if (s.isLoading())
- timed_seq_ptr = (timedSeqOfs == 0xFFFF) ? nullptr : patrol_route + timedSeqOfs;
-}
-
int ChamberEngine::getX(int original_x) {
return original_x;
}
diff --git a/engines/chamber/savegame.cpp b/engines/chamber/savegame.cpp
index ada736e41ac..28493dba9f0 100644
--- a/engines/chamber/savegame.cpp
+++ b/engines/chamber/savegame.cpp
@@ -27,671 +27,181 @@
#include "chamber/cga.h"
#include "chamber/room.h"
#include "chamber/dialog.h"
-#include "chamber/room.h"
+#include "chamber/cursor.h"
namespace Chamber {
-#if 0
-static const char restart_name[] = "CLEARx.BIN";
-
-#ifdef VERSION_USA
-static const char savegame_name[] = "SCENACx.BIN";
-#else
-static const char savegame_name[] = "SCENAx.BIN";
-#endif
-#endif
-
-#ifdef VERSION_USA
-
-#define CGA_SAVE_BEG_OFS 0x769B
-#define CGA_SAVE_END_OFS 0x9EDA
-
-#define CGA_SAVE_WORD_VARS_OFS 0x79C1
-#define CGA_SAVE_BYTE_VARS_OFS 0x7B33
-#define CGA_SAVE_INVENTORY_OFS 0x7762
-#define CGA_SAVE_ZONES_OFS 0x7BA4
-#define CGA_SAVE_PERS_OFS 0x78E2
-#define CGA_SAVE_STACK_OFS 0x76DF
-#define CGA_SAVE_SPRITES_OFS 0x5264
-#define CGA_SAVE_SPRLIST_OFS 0x76AD
-#define CGA_SAVE_SPRBUFF_OFS 0x4C68
-#define CGA_SAVE_ARPLA_OFS 0x26F6
-#define CGA_SAVE_SCRSTACK_OFS 0x76DF
-#define CGA_SAVE_TEMPL_OFS 0x1AC7
-#define CGA_SAVE_VORTANIMS_OFS 0xA7B7
-#define CGA_SAVE_TURKEYANIMS_OFS 0xA8FC
-#define CGA_SAVE_TIMEDSEQ_OFS 0xA96E
-
-#else
-
-#define CGA_SAVE_BEG_OFS 0x751E
-#define CGA_SAVE_END_OFS 0x9D5D
-
-#define CGA_SAVE_WORD_VARS_OFS 0x7844
-#define CGA_SAVE_BYTE_VARS_OFS 0x79B6
-#define CGA_SAVE_INVENTORY_OFS 0x75E5
-#define CGA_SAVE_ZONES_OFS 0x7A27
-#define CGA_SAVE_PERS_OFS 0x7765
-#define CGA_SAVE_STACK_OFS 0x7562
-#define CGA_SAVE_SPRITES_OFS 0x5264
-#define CGA_SAVE_SPRLIST_OFS 0x7530
-#define CGA_SAVE_SPRBUFF_OFS 0x4C68
-#define CGA_SAVE_ARPLA_OFS 0x26F6
-#define CGA_SAVE_SCRSTACK_OFS 0x7562
-#define CGA_SAVE_TEMPL_OFS 0x182C
-#define CGA_SAVE_VORTANIMS_OFS 0xA609
-#define CGA_SAVE_TURKEYANIMS_OFS 0xA74E
-#define CGA_SAVE_TIMEDSEQ_OFS 0xA7C0
-
-#endif
-
-#define SAVEADDR(value, base, nativesize, origsize, origbase) \
- ((value) ? LE16(((((byte*)(value)) - (byte*)(base)) / nativesize) * origsize + origbase) : 0)
-
-#define LOADADDR(value, base, nativesize, origsize, origbase) \
- ((value) ? ((((LE16(value)) - (origbase)) / origsize) * nativesize + (byte*)base) : 0)
-
-#define WRITE(buffer, size) \
- wlen = write(f, buffer, size); if(wlen != size) goto error;
-
-#define READ(buffer, size) \
- rlen = read(f, buffer, size); if(rlen != size) goto error;
-
-#if 0
-int16 readSaveData(int16 f, int16 clean) {
- int16 rlen;
- uint16 zero = 0;
- byte *p;
- int16 i;
-
-#define BYTES(buffer, size) READ(buffer, size)
-#define UBYTE(variable) { byte temp_v; READ(&temp_v, 1); variable = temp_v; }
-#define SBYTE(variable) { int8 temp_v; READ(&temp_v, 1); variable = temp_v; }
-#define USHORT(variable) { uint16 temp_v; READ(&temp_v, 2); variable = temp_v; }
-#define SSHORT(variable) { int16 temp_v; READ(&temp_v, 2); variable = temp_v; }
-#define POINTER(variable, base, nativesize, origsize, origbase) \
- { int16 temp_v; READ(&temp_v, 2); variable = LOADADDR(temp_v, base, nativesize, origsize, origbase); }
-
- /*script_vars pointers*/
- POINTER(script_vars[ScrPool0_WordVars0], &script_word_vars, 2, 2, CGA_SAVE_WORD_VARS_OFS);
- POINTER(script_vars[ScrPool1_WordVars1], &script_word_vars, 2, 2, CGA_SAVE_WORD_VARS_OFS);
- POINTER(script_vars[ScrPool2_ByteVars], &script_byte_vars, 1, 1, CGA_SAVE_BYTE_VARS_OFS);
- POINTER(script_vars[ScrPool3_CurrentItem], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
- POINTER(script_vars[ScrPool4_ZoneSpots], zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
- POINTER(script_vars[ScrPool5_Persons], pers_list, 1, 1, CGA_SAVE_PERS_OFS);
- POINTER(script_vars[ScrPool6_Inventory], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
- POINTER(script_vars[ScrPool7_Zapstiks], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
- POINTER(script_vars[ScrPool8_CurrentPers], pers_list, 1, 1, CGA_SAVE_PERS_OFS);
-
- /* sprites_list */
- for (i = 0; i < MAX_SPRITES; i++) {
- POINTER(sprites_list[i], scratch_mem1, 1, 1, CGA_SAVE_SPRITES_OFS);
- }
-
- /* doors list */
- for (i = 0; i < MAX_DOORS; i++) {
- POINTER(doors_list[i], arpla_data, 1, 1, CGA_SAVE_ARPLA_OFS);
- }
-
- /* zone_spots */
- POINTER((byte *)zone_spots, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
-
- /* zone_spots_end */
- POINTER((byte *)zone_spots_end, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
-
- /* zone_spots_cur */
- POINTER((byte *)zone_spots_cur, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
-
- /* script_stack_ptr */
- /*TODO: FIX ME: original stack works in reverse order (from higher address to lower)*/
- POINTER((byte *)script_stack_ptr, script_stack, 1, 1, CGA_SAVE_SCRSTACK_OFS);
-
- /* script_stack */
- /*TODO: FIX ME: original stack works in reverse order (from higher address to lower)*/
- for (i = 0; i < 5 * 2; i++) {
- POINTER(script_stack[i], templ_data, 1, 1, CGA_SAVE_TEMPL_OFS);
- }
-
- /* padding */
- USHORT(zero);
-
- /* vort_ptr */
- POINTER((byte *)vort_ptr, pers_list, 1, 1, CGA_SAVE_PERS_OFS);
-
- /* vortanims_ptr */
- POINTER((byte *)vortanims_ptr, vortsanim_list, 1, 1, CGA_SAVE_VORTANIMS_OFS);
-
- /* turkeyanims_ptr */
- POINTER((byte *)turkeyanims_ptr, turkeyanim_list, 1, 1, CGA_SAVE_TURKEYANIMS_OFS);
-
- /* aspirant_ptr */
- POINTER((byte *)aspirant_ptr, pers_list, 1, 1, CGA_SAVE_PERS_OFS);
-
- /* aspirant_spot */
- POINTER((byte *)aspirant_spot, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
-
- /* found_spot */
- POINTER((byte *)found_spot, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
-
- /* spot_sprite */
- POINTER((byte *)spot_sprite, sprites_list, sizeof(sprites_list[0]), 2, CGA_SAVE_SPRLIST_OFS);
-
- /* timed_seq_ptr */
- POINTER(timed_seq_ptr, patrol_route, 1, 1, CGA_SAVE_TIMEDSEQ_OFS);
-
- /* keep_sp */
- /* TODO: how to save it? but it's probably useless anyway */
- USHORT(zero);
-
- /* unused ptr to script code */
- p = templ_data;
- POINTER(p, templ_data, 1, 1, CGA_SAVE_TEMPL_OFS);
-
- /* padding */
- UBYTE(zero);
-
- /* the wall doors state */
- for (i = 0; i < 2; i++) {
- thewalldoor_t *door = &the_wall_doors[i];
- UBYTE(door->height);
- UBYTE(door->width);
- USHORT(door->pitch);
- USHORT(door->offs);
- POINTER(door->pixels, sprit_load_buffer, 1, 1, CGA_SAVE_SPRBUFF_OFS);
- }
-
- /* wait_delta */
- UBYTE(wait_delta);
-
- /* padding */
- UBYTE(zero);
-
- /* dirty_rects */
- for (i = 0; i < MAX_DIRTY_RECT; i++) {
- dirty_rect_t *dr = &dirty_rects[i];
- UBYTE(dr->kind);
- USHORT(dr->offs);
- UBYTE(dr->height);
- UBYTE(dr->width);
- UBYTE(dr->y);
- UBYTE(dr->x);
- }
-
- /* inventory_items */
- for (i = 0; i < MAX_INV_ITEMS; i++) {
- /*TODO: properly serialize this*/
- BYTES(&inventory_items[i], sizeof(item_t));
- }
-
- /* room_hint_bar_coords_y */
- UBYTE(room_hint_bar_coords_y);
-
- /* room_hint_bar_coords_x */
- UBYTE(room_hint_bar_coords_x);
-
- /* padding */
- USHORT(zero);
-
- /* fight_pers_ofs */
- /* NB! raw offset */
- USHORT(fight_pers_ofs);
-
- /* pers_list */
- for (i = 0; i < PERS_MAX; i++) {
- /*TODO: properly serialize this*/
- BYTES(&pers_list[i], sizeof(pers_t));
- }
-
- /* drops_cleanup_time */
- USHORT(drops_cleanup_time);
-
- /* room_bounds_rect */
- /*TODO: properly serialize this*/
- BYTES(&room_bounds_rect, sizeof(rect_t));
-
- /* last_object_hint */
- UBYTE(last_object_hint);
-
- /* object_hint */
- UBYTE(object_hint);
-
- /* command_hint */
- UBYTE(command_hint);
-
- /* zone_name */
- UBYTE(zone_name);
-
- /* room_hint_bar_width */
- UBYTE(room_hint_bar_width);
-
- /* last_command_hint */
- UBYTE(last_command_hint);
-
- /* zone_spr_index */
- UBYTE(zone_spr_index);
-
- /* zone_obj_count */
- UBYTE(zone_obj_count);
-
- /* padding */
- USHORT(zero);
-
- /* padding */
- UBYTE(zero);
-
- /* in_de_profundis */
- UBYTE(in_de_profundis);
-
- /* script_word_vars */
- BYTES(&script_word_vars, sizeof(script_word_vars));
-
- /* menu_commands_12 */
- BYTES(menu_commands_12, sizeof(menu_commands_12));
-
- /* menu_commands_22 */
- BYTES(menu_commands_22, sizeof(menu_commands_22));
+static const byte kSaveVersion = 1;
- /* menu_commands_24 */
- BYTES(menu_commands_24, sizeof(menu_commands_24));
-
- /* menu_commands_23 */
- BYTES(menu_commands_23, sizeof(menu_commands_23));
-
- /* next_vorts_cmd */
- USHORT(next_vorts_cmd);
-
- /* next_vorts_ticks */
- USHORT(next_vorts_ticks);
-
- /* next_turkey_cmd */
- USHORT(next_turkey_cmd);
-
- /* next_turkey_ticks */
- USHORT(next_turkey_ticks);
-
- /* next_protozorqs_ticks */
- USHORT(next_protozorqs_ticks);
-
- /* padding */
- for (i = 0; i < 7; i++) USHORT(zero);
-
- /* script_byte_vars */
- BYTES(&script_byte_vars, sizeof(script_byte_vars));
-
- /* zones_data */
- BYTES(zones_data, RES_ZONES_MAX);
-
- if (clean == 0) {
- /* screen data */
- BYTES(backbuffer, 0x3FFF);
-
- CGA_BackBufferToRealFull();
- SelectPalette();
-
- BYTES(backbuffer, 0x3FFF);
- }
-
-#undef BYTES
-#undef UBYTE
-#undef SBYTE
-#undef USHORT
-#undef SSHORT
-#undef POINTER
-
- return 0;
-
-error:;
- return 1;
+// Serializes a pointer as a byte offset from base; 0xFFFF represents null
+template<typename T>
+static void syncPtrOffset(Common::Serializer &s, T *&ptr, void *base) {
+ uint16 ofs = s.isSaving() ? (ptr ? (uint16)((byte *)ptr - (byte *)base) : 0xFFFF) : 0;
+ s.syncAsUint16LE(ofs);
+ if (s.isLoading())
+ ptr = (ofs == 0xFFFF) ? nullptr : (T *)((byte *)base + ofs);
}
-int16 writeSaveData(int16 f, int16 clean) {
- int16 wlen;
- uint16 zero = 0;
- byte *p;
- int16 i;
-
-#define BYTES(buffer, size) WRITE(buffer, size)
-#define UBYTE(variable) { byte temp_v = variable; WRITE(&temp_v, 1); }
-#define SBYTE(variable) { int8 temp_v = variable; WRITE(&temp_v, 1); }
-#define USHORT(variable) { uint16 temp_v = variable; WRITE(&temp_v, 2); }
-#define SSHORT(variable) { int16 temp_v = variable; WRITE(&temp_v, 2); }
-#define POINTER(variable, base, nativesize, origsize, origbase) \
- { int16 temp_v = SAVEADDR(variable, base, nativesize, origsize, origbase); WRITE(&temp_v, 2); }
-
- /*script_vars pointers*/
- POINTER(script_vars[ScrPool0_WordVars0], &script_word_vars, 2, 2, CGA_SAVE_WORD_VARS_OFS);
- POINTER(script_vars[ScrPool1_WordVars1], &script_word_vars, 2, 2, CGA_SAVE_WORD_VARS_OFS);
- POINTER(script_vars[ScrPool2_ByteVars], &script_byte_vars, 1, 1, CGA_SAVE_BYTE_VARS_OFS);
- POINTER(script_vars[ScrPool3_CurrentItem], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
- POINTER(script_vars[ScrPool4_ZoneSpots], zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
- POINTER(script_vars[ScrPool5_Persons], pers_list, 1, 1, CGA_SAVE_PERS_OFS);
- POINTER(script_vars[ScrPool6_Inventory], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
- POINTER(script_vars[ScrPool7_Zapstiks], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
- POINTER(script_vars[ScrPool8_CurrentPers], pers_list, 1, 1, CGA_SAVE_PERS_OFS);
-
- /* sprites_list */
- for (i = 0; i < MAX_SPRITES; i++) {
- POINTER(sprites_list[i], scratch_mem1, 1, 1, CGA_SAVE_SPRITES_OFS);
- }
-
- /* doors list */
- for (i = 0; i < MAX_DOORS; i++) {
- POINTER(doors_list[i], arpla_data, 1, 1, CGA_SAVE_ARPLA_OFS);
- }
-
- /* zone_spots */
- POINTER(zone_spots, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
-
- /* zone_spots_end */
- POINTER(zone_spots_end, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
-
- /* zone_spots_cur */
- POINTER(zone_spots_cur, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
-
- /* script_stack_ptr */
- /*TODO: FIX ME: original stack works in reverse order (from higher address to lower)*/
- POINTER(script_stack_ptr, script_stack, 1, 1, CGA_SAVE_SCRSTACK_OFS);
-
- /* script_stack */
- /*TODO: FIX ME: original stack works in reverse order (from higher address to lower)*/
- for (i = 0; i < 5 * 2; i++) {
- POINTER(script_stack[i], templ_data, 1, 1, CGA_SAVE_TEMPL_OFS);
- }
-
- /* padding */
- USHORT(zero);
-
- /* vort_ptr */
- POINTER(vort_ptr, pers_list, 1, 1, CGA_SAVE_PERS_OFS);
-
- /* vortanims_ptr */
- POINTER(vortanims_ptr, vortsanim_list, 1, 1, CGA_SAVE_VORTANIMS_OFS);
-
- /* turkeyanims_ptr */
- POINTER(turkeyanims_ptr, turkeyanim_list, 1, 1, CGA_SAVE_TURKEYANIMS_OFS);
-
- /* aspirant_ptr */
- POINTER(aspirant_ptr, pers_list, 1, 1, CGA_SAVE_PERS_OFS);
-
- /* aspirant_spot */
- POINTER(aspirant_spot, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
-
- /* found_spot */
- POINTER(found_spot, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
-
- /* spot_sprite */
- POINTER(spot_sprite, sprites_list, sizeof(sprites_list[0]), 2, CGA_SAVE_SPRLIST_OFS);
-
- /* timed_seq_ptr */
- POINTER(timed_seq_ptr, patrol_route, 1, 1, CGA_SAVE_TIMEDSEQ_OFS);
-
- /* keep_sp */
- /* TODO: how to save it? but it's probably useless anyway */
- USHORT(zero);
-
- /* unused ptr to script code */
- p = templ_data;
- POINTER(p, templ_data, 1, 1, CGA_SAVE_TEMPL_OFS);
-
- /* padding */
- UBYTE(zero);
-
- /* the wall doors state */
- for (i = 0; i < 2; i++) {
- thewalldoor_t *door = &the_wall_doors[i];
- UBYTE(door->height);
- UBYTE(door->width);
- USHORT(door->pitch);
- USHORT(door->offs);
- POINTER(door->pixels, sprit_load_buffer, 1, 1, CGA_SAVE_SPRBUFF_OFS);
- }
-
- /* wait_delta */
- UBYTE(wait_delta);
-
- /* padding */
- UBYTE(zero);
-
- /* dirty_rects */
- for (i = 0; i < MAX_DIRTY_RECT; i++) {
- dirty_rect_t *dr = &dirty_rects[i];
- UBYTE(dr->kind);
- USHORT(dr->offs);
- UBYTE(dr->height);
- UBYTE(dr->width);
- UBYTE(dr->y);
- UBYTE(dr->x);
- }
-
- /* inventory_items */
- for (i = 0; i < MAX_INV_ITEMS; i++) {
- /*TODO: properly serialize this*/
- BYTES(&inventory_items[i], sizeof(item_t));
- }
-
- /* room_hint_bar_coords_y */
- UBYTE(room_hint_bar_coords_y);
-
- /* room_hint_bar_coords_x */
- UBYTE(room_hint_bar_coords_x);
-
- /* padding */
- USHORT(zero);
-
- /* fight_pers_ofs */
- /* NB! raw offset */
- USHORT(fight_pers_ofs);
-
- /* pers_list */
- for (i = 0; i < PERS_MAX; i++) {
- /*TODO: properly serialize this*/
- BYTES(&pers_list[i], sizeof(pers_t));
- }
-
- /* drops_cleanup_time */
- USHORT(drops_cleanup_time);
-
- /* room_bounds_rect */
- /*TODO: properly serialize this*/
- BYTES(&room_bounds_rect, sizeof(rect_t));
-
- /* last_object_hint */
- UBYTE(last_object_hint);
-
- /* object_hint */
- UBYTE(object_hint);
-
- /* command_hint */
- UBYTE(command_hint);
-
- /* zone_name */
- UBYTE(zone_name);
-
- /* room_hint_bar_width */
- UBYTE(room_hint_bar_width);
-
- /* last_command_hint */
- UBYTE(last_command_hint);
-
- /* zone_spr_index */
- UBYTE(zone_spr_index);
-
- /* zone_obj_count */
- UBYTE(zone_obj_count);
-
- /* padding */
- USHORT(zero);
-
- /* padding */
- UBYTE(zero);
-
- /* in_de_profundis */
- UBYTE(in_de_profundis);
-
- /* script_word_vars */
- BYTES(&script_word_vars, sizeof(script_word_vars));
-
- /* menu_commands_12 */
- BYTES(menu_commands_12, sizeof(menu_commands_12));
-
- /* menu_commands_22 */
- BYTES(menu_commands_22, sizeof(menu_commands_22));
-
- /* menu_commands_24 */
- BYTES(menu_commands_24, sizeof(menu_commands_24));
-
- /* menu_commands_23 */
- BYTES(menu_commands_23, sizeof(menu_commands_23));
-
- /* next_vorts_cmd */
- USHORT(next_vorts_cmd);
-
- /* next_vorts_ticks */
- USHORT(next_vorts_ticks);
-
- /* next_turkey_cmd */
- USHORT(next_turkey_cmd);
-
- /* next_turkey_ticks */
- USHORT(next_turkey_ticks);
-
- /* next_protozorqs_ticks */
- USHORT(next_protozorqs_ticks);
-
- /* padding */
- for (i = 0; i < 7; i++) USHORT(zero);
+static void syncItem(Common::Serializer &s, item_t &it) {
+ s.syncAsByte(it.flags);
+ s.syncAsByte(it.area);
+ s.syncAsByte(it.sprite);
+ s.syncAsByte(it.name);
+ s.syncAsUint16LE(it.command);
+}
- /* script_byte_vars */
- BYTES(&script_byte_vars, sizeof(script_byte_vars));
+static void syncPers(Common::Serializer &s, pers_t &p) {
+ s.syncAsByte(p.area);
+ s.syncAsByte(p.flags);
+ s.syncAsByte(p.name);
+ s.syncAsByte(p.index);
+ s.syncAsByte(p.item);
+}
- /* zones_data */
- BYTES(zones_data, RES_ZONES_MAX);
+static void syncDirtyRect(Common::Serializer &s, dirty_rect_t &dr) {
+ s.syncAsByte(dr.kind);
+ s.syncAsUint16LE(dr.offs);
+ s.syncAsByte(dr.height);
+ s.syncAsByte(dr.width);
+ s.syncAsByte(dr.y);
+ s.syncAsByte(dr.x);
+}
- if (clean == 0) {
- /* screen data */
- BYTES(frontbuffer, 0x3FFF);
- BYTES(backbuffer, 0x3FFF);
- }
+static void syncRect(Common::Serializer &s, rect_t &r) {
+ s.syncAsByte(r.sx);
+ s.syncAsByte(r.ex);
+ s.syncAsByte(r.sy);
+ s.syncAsByte(r.ey);
+}
-#undef BYTES
-#undef UBYTE
-#undef SBYTE
-#undef USHORT
-#undef SSHORT
-#undef POINTER
+Common::Error ChamberEngine::loadGameStream(Common::SeekableReadStream *stream) {
+ Common::Serializer s(stream, nullptr);
+ if (!s.syncVersion(kSaveVersion))
+ return Common::Error(Common::kReadingFailed, "Save from a newer engine version");
+ syncGameStream(s);
+ 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();
+ backupSpotsImages();
+ drawPersons();
+ _renderer->backBufferToRealFull();
+ _renderer->selectCursor(CURSOR_FINGER);
+ return Common::kNoError;
+}
- return 0;
+Common::Error ChamberEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
+ Common::Serializer s(nullptr, stream);
+ s.syncVersion(kSaveVersion);
+ syncGameStream(s);
+ if (s.err())
+ return Common::kWritingFailed;
+ return Common::kNoError;
+}
-error:;
- return 1;
+void ChamberEngine::syncGameStream(Common::Serializer &s) {
+ s.syncBytes((byte *)&script_byte_vars, sizeof(script_byte_vars));
+ s.syncBytes((byte *)&script_word_vars, sizeof(script_word_vars));
+ s.syncBytes(zones_data, RES_ZONES_MAX);
+
+ for (int i = 0; i < MAX_INV_ITEMS; i++)
+ syncItem(s, inventory_items[i]);
+ for (int i = 0; i < PERS_MAX; i++)
+ syncPers(s, pers_list[i]);
+ for (int i = 0; i < MAX_DIRTY_RECT; i++)
+ syncDirtyRect(s, dirty_rects[i]);
+
+ for (int i = 0; i < SPECIAL_COMMANDS_MAX; i++) {
+ s.syncAsUint16LE(menu_commands_12[i]);
+ s.syncAsUint16LE(menu_commands_22[i]);
+ s.syncAsUint16LE(menu_commands_24[i]);
+ s.syncAsUint16LE(menu_commands_23[i]);
+ }
+ syncRect(s, room_bounds_rect);
+
+ s.syncAsUint16LE(next_vorts_cmd);
+ s.syncAsUint16LE(next_vorts_ticks);
+ s.syncAsUint16LE(next_turkey_cmd);
+ s.syncAsUint16LE(next_turkey_ticks);
+ s.syncAsUint16LE(next_protozorqs_ticks);
+ s.syncAsUint16LE(fight_pers_ofs);
+ s.syncAsUint16LE(drops_cleanup_time);
+
+ s.syncAsByte(wait_delta);
+ s.syncAsByte(in_de_profundis);
+ s.syncAsByte(zone_name);
+ s.syncAsByte(room_hint_bar_width);
+ s.syncAsByte(room_hint_bar_coords_x);
+ s.syncAsByte(room_hint_bar_coords_y);
+ s.syncAsByte(last_object_hint);
+ s.syncAsByte(object_hint);
+ s.syncAsByte(command_hint);
+ s.syncAsByte(last_command_hint);
+ s.syncAsByte(zone_spr_index);
+ s.syncAsByte(zone_obj_count);
+
+ for (int i = 0; i < 2; i++) {
+ s.syncAsByte(the_wall_doors[i].height);
+ s.syncAsByte(the_wall_doors[i].width);
+ s.syncAsUint16LE(the_wall_doors[i].pitch);
+ s.syncAsUint16LE(the_wall_doors[i].offs);
+ syncPtrOffset(s, the_wall_doors[i].pixels, sprit_load_buffer);
+ }
+
+ syncPtrOffset(s, script_vars[kScrPool0_WordVars0], &script_word_vars);
+ syncPtrOffset(s, script_vars[kScrPool1_WordVars1], &script_word_vars);
+ syncPtrOffset(s, script_vars[kScrPool2_ByteVars], &script_byte_vars);
+ syncPtrOffset(s, script_vars[kScrPool3_CurrentItem], inventory_items);
+ syncPtrOffset(s, script_vars[kScrPool4_ZoneSpots], zones_data);
+ syncPtrOffset(s, script_vars[kScrPool5_Persons], pers_list);
+ syncPtrOffset(s, script_vars[kScrPool6_Inventory], inventory_items);
+ syncPtrOffset(s, script_vars[kScrPool7_Zapstiks], inventory_items);
+ syncPtrOffset(s, script_vars[kScrPool8_CurrentPers], pers_list);
+
+ for (int i = 0; i < MAX_SPRITES; i++)
+ syncPtrOffset(s, sprites_list[i], scratch_mem1);
+ for (int i = 0; i < MAX_DOORS; i++)
+ syncPtrOffset(s, doors_list[i], arpla_data);
+
+ syncPtrOffset(s, zone_spots, zones_data);
+ syncPtrOffset(s, zone_spots_end, zones_data);
+ syncPtrOffset(s, zone_spots_cur, zones_data);
+
+ syncPtrOffset(s, script_stack_ptr, script_stack);
+ for (int i = 0; i < 5 * 2; i++)
+ syncPtrOffset(s, script_stack[i], templ_data);
+
+ syncPtrOffset(s, vort_ptr, pers_list);
+ syncPtrOffset(s, vortanims_ptr, vortsanim_list);
+ syncPtrOffset(s, turkeyanims_ptr, turkeyanim_list);
+ syncPtrOffset(s, aspirant_ptr, pers_list);
+ syncPtrOffset(s, aspirant_spot, zones_data);
+ syncPtrOffset(s, found_spot, zones_data);
+ syncPtrOffset(s, spot_sprite, sprites_list);
+
+ uint16 timedSeqOfs = s.isSaving() ? (timed_seq_ptr ? (uint16)(timed_seq_ptr - patrol_route) : 0xFFFF) : 0;
+ s.syncAsUint16LE(timedSeqOfs);
+ if (s.isLoading())
+ timed_seq_ptr = (timedSeqOfs == 0xFFFF) ? nullptr : patrol_route + timedSeqOfs;
}
-#endif
int16 loadScena(void) {
return g_vm->loadGameDialog() ? 0 : 1;
-#if 0
- int16 f;
- int16 res;
-
- script_byte_vars.game_paused = 1;
-
- f = open(savegame_name, O_RDONLY | O_BINARY);
- if (f == -1) {
- script_byte_vars.game_paused = 0;
- return 1; /*error*/
- }
- /*
- Save format:
- vars memory (751E-9D5D)
- frontbuffer (0x3FFF bytes)
- backbuffer (0x3FFF bytes)
- */
-
- res = ReadSaveData(f, 0);
-
- if (res == 0) {
- /*re-initialize sprites list*/
- BackupSpotsImages();
- }
-
- close(f);
- script_byte_vars.game_paused = 0;
- return res;
-#endif
}
int16 saveScena(void) {
return g_vm->saveGameDialog() ? 0 : 1;
-#if 0
- int16 f;
- int16 res;
-
- script_byte_vars.game_paused = 1;
- BlitSpritesToBackBuffer();
- command_hint = 100;
- DrawCommandHint();
- ShowCommandHint(frontbuffer);
-
- f = open(savegame_name, O_CREAT | O_WRONLY | O_BINARY);
- if (f == -1) {
- script_byte_vars.game_paused = 0;
- return 1; /*error*/
- }
-
- res = WriteSaveData(f, 0);
-
- close(f);
-
- if (res != 0)
- unlink(savegame_name);
-
- script_byte_vars.game_paused = 0;
- return res;
-#endif
}
void saveRestartGame(void) {
warning("STUB: saveRestartGame()");
-#if 0
- int16 f;
-
- f = open(restart_name, O_CREAT | O_WRONLY | O_BINARY);
- if (f == -1) {
- return; /*error*/
- }
-
- WriteSaveData(f, 1);
-
- close(f);
- return;
-#endif
}
-//extern jmp_buf restart_jmp;
-extern void askDisk2(void);
-
void restartGame(void) {
warning("STUB: restartGame()");
g_vm->_shouldRestart = true;
-
-#if 0
- int16 f;
- int16 res;
-
- for (;; askDisk2()) {
- f = open(restart_name, O_RDONLY | O_BINARY);
- if (f != -1) {
- res = readSaveData(f, 1);
- close(f);
- if (res == 0)
- break;
- }
- }
-
- script_byte_vars.cur_spot_flags = 0xFF;
- script_byte_vars.load_flag = 2;
-
-#endif
}
} // End of namespace Chamber
Commit: 406dba241029029329b626f569a4cc9403bb5246
https://github.com/scummvm/scummvm/commit/406dba241029029329b626f569a4cc9403bb5246
Author: Ion Andrei Cristian (lecturatul2017 at gmail.com)
Date: 2026-04-29T00:22:50+02:00
Commit Message:
CHAMBER: Rename savegame to saveload
Rename savegame.cpp/h to saveload.cpp/h using git mv to preserve file
history. Update include guards and all references accordingly.
Changed paths:
A engines/chamber/saveload.cpp
A engines/chamber/saveload.h
R engines/chamber/savegame.cpp
R engines/chamber/savegame.h
engines/chamber/kult.cpp
engines/chamber/module.mk
engines/chamber/script.cpp
diff --git a/engines/chamber/kult.cpp b/engines/chamber/kult.cpp
index d99687d68a3..75fd0e9d478 100644
--- a/engines/chamber/kult.cpp
+++ b/engines/chamber/kult.cpp
@@ -35,7 +35,7 @@
#include "chamber/timer.h"
#include "chamber/portrait.h"
#include "chamber/room.h"
-#include "chamber/savegame.h"
+#include "chamber/saveload.h"
#include "chamber/resdata.h"
#include "chamber/script.h"
#include "chamber/print.h"
diff --git a/engines/chamber/module.mk b/engines/chamber/module.mk
index bb54a94e06a..3f388b106a4 100644
--- a/engines/chamber/module.mk
+++ b/engines/chamber/module.mk
@@ -24,7 +24,7 @@ MODULE_OBJS := \
r_texts.o \
resdata.o \
room.o \
- savegame.o \
+ saveload.o \
script.o \
sound.o \
timer.o
diff --git a/engines/chamber/savegame.cpp b/engines/chamber/saveload.cpp
similarity index 99%
rename from engines/chamber/savegame.cpp
rename to engines/chamber/saveload.cpp
index 28493dba9f0..9234688061a 100644
--- a/engines/chamber/savegame.cpp
+++ b/engines/chamber/saveload.cpp
@@ -21,7 +21,7 @@
#include "chamber/chamber.h"
#include "chamber/common.h"
-#include "chamber/savegame.h"
+#include "chamber/saveload.h"
#include "chamber/resdata.h"
#include "chamber/script.h"
#include "chamber/cga.h"
diff --git a/engines/chamber/savegame.h b/engines/chamber/saveload.h
similarity index 95%
rename from engines/chamber/savegame.h
rename to engines/chamber/saveload.h
index 54eee5d5098..dd41f63903f 100644
--- a/engines/chamber/savegame.h
+++ b/engines/chamber/saveload.h
@@ -19,8 +19,8 @@
*
*/
-#ifndef CHAMBER_SAVEGAME_H
-#define CHAMBER_SAVEGAME_H
+#ifndef CHAMBER_SAVELOAD_H
+#define CHAMBER_SAVELOAD_H
namespace Chamber {
diff --git a/engines/chamber/script.cpp b/engines/chamber/script.cpp
index 6e0ddd59358..4ac42031c65 100644
--- a/engines/chamber/script.cpp
+++ b/engines/chamber/script.cpp
@@ -40,7 +40,7 @@
#include "chamber/anim.h"
#include "chamber/invent.h"
#include "chamber/sound.h"
-#include "chamber/savegame.h"
+#include "chamber/saveload.h"
#include "chamber/ifgm.h"
#if 0
More information about the Scummvm-git-logs
mailing list