aboutsummaryrefslogtreecommitdiff
path: root/engines/dm
diff options
context:
space:
mode:
authorBendegúz Nagy2016-07-19 18:04:14 +0200
committerBendegúz Nagy2016-08-26 23:02:22 +0200
commit11704d0c509c1fc5af73c22bd64be60572ff4b8c (patch)
treeadc925a33b19b7feb6509eb8c882a7a33ffb3aa7 /engines/dm
parentbd9fa3eb87a08dd7ba6387ac7c2d911a040cd9c4 (diff)
downloadscummvm-rg350-11704d0c509c1fc5af73c22bd64be60572ff4b8c.tar.gz
scummvm-rg350-11704d0c509c1fc5af73c22bd64be60572ff4b8c.tar.bz2
scummvm-rg350-11704d0c509c1fc5af73c22bd64be60572ff4b8c.zip
DM: Add savegame functions
Diffstat (limited to 'engines/dm')
-rw-r--r--engines/dm/champion.cpp66
-rw-r--r--engines/dm/champion.h1
-rw-r--r--engines/dm/dm.cpp9
-rw-r--r--engines/dm/dm.h17
-rw-r--r--engines/dm/dungeonman.h2
-rw-r--r--engines/dm/group.cpp22
-rw-r--r--engines/dm/group.h3
-rw-r--r--engines/dm/loadsave.cpp148
-rw-r--r--engines/dm/loadsave.h6
-rw-r--r--engines/dm/timeline.cpp19
-rw-r--r--engines/dm/timeline.h2
11 files changed, 261 insertions, 34 deletions
diff --git a/engines/dm/champion.cpp b/engines/dm/champion.cpp
index 7b2dc00ce6..f22d4dd605 100644
--- a/engines/dm/champion.cpp
+++ b/engines/dm/champion.cpp
@@ -1295,10 +1295,10 @@ void ChampionMan::f302_processCommands28to65_clickOnSlotBox(uint16 slotBoxIndex)
}
if (slotThing != Thing::_none) {
f300_getObjectRemovedFromSlot(champIndex, slotIndex);
- f297_putObjectInLeaderHand(slotThing, false);
+ f297_putObjectInLeaderHand(slotThing, false);
}
if (leaderHandObject != Thing::_none) {
- f301_addObjectInSlot((ChampionIndex)champIndex, leaderHandObject, (ChampionSlot) slotIndex);
+ f301_addObjectInSlot((ChampionIndex)champIndex, leaderHandObject, (ChampionSlot)slotIndex);
}
f292_drawChampionState((ChampionIndex)champIndex);
_vm->_eventMan->f77_hideMouse();
@@ -1702,6 +1702,68 @@ void ChampionMan::f331_applyTimeEffects() {
f293_drawAllChampionStates();
}
+void ChampionMan::save2_PartyPart(Common::OutSaveFile* file) {
+ for (uint16 i = 0; i < 4; ++i) {
+ Champion *champ = &_gK71_champions[i];
+ file->writeUint16BE(champ->_attributes);
+ file->writeUint16BE(champ->_wounds);
+ for (uint16 y = 0; y < 7; ++y)
+ for (uint16 x = 0; x < 3; ++x)
+ file->writeByte(champ->_statistics[y][x]);
+ for (uint16 j = 0; j < 30; ++j)
+ file->writeUint16BE(champ->_slots[j].toUint16());
+ for (uint16 j = 0; j < 20; ++j) {
+ file->writeSint16BE(champ->_skills[j]._temporaryExperience);
+ file->writeSint32BE(champ->_skills[j]._experience);
+ }
+ for (uint16 j = 0; j < 8; ++j)
+ file->writeByte(champ->_name[j]);
+ for (uint16 j = 0; j < 20; ++j)
+ file->writeByte(champ->_title[j]);
+ file->writeUint16BE(champ->_dir);
+ file->writeUint16BE(champ->_cell);
+ file->writeUint16BE(champ->_actionIndex);
+ file->writeUint16BE(champ->_symbolStep);
+ for(uint16 j = 0; j < 5; ++j)
+ file->writeByte(champ->_symbols[j]);
+ file->writeUint16BE(champ->_directionMaximumDamageReceived);
+ file->writeUint16BE(champ->_maximumDamageReceived);
+ file->writeUint16BE(champ->_poisonEventCount);
+ file->writeSint16BE(champ->_enableActionEventIndex);
+ file->writeSint16BE(champ->_hideDamageReceivedIndex);
+ file->writeSint16BE(champ->_currHealth);
+ file->writeSint16BE(champ->_maxHealth);
+ file->writeSint16BE(champ->_currStamina);
+ file->writeSint16BE(champ->_maxStamina);
+ file->writeSint16BE(champ->_currMana);
+ file->writeSint16BE(champ->_maxMana);
+ file->writeSint16BE(champ->_actionDefense);
+ file->writeSint16BE(champ->_food);
+ file->writeSint16BE(champ->_water);
+ file->writeUint16BE(champ->_load);
+ file->writeSint16BE(champ->_shieldDefense);
+ for (uint16 j = 0; j < 928; ++j)
+ file->writeByte(champ->_portrait[j]);
+ }
+
+ Party &party = _g407_party;
+ file->writeSint16BE(party._magicalLightAmount);
+ file->writeByte(party._event73Count_ThievesEye);
+ file->writeByte(party._event79Count_Footprints);
+ file->writeSint16BE(party._shieldDefense);
+ file->writeSint16BE(party._fireShieldDefense);
+ file->writeSint16BE(party._spellShieldDefense);
+ file->writeByte(party._scentCount);
+ file->writeByte(party._freezeLifeTicks);
+ file->writeByte(party._firstScentIndex);
+ file->writeByte(party._lastScentIndex);
+ for(uint16 i = 0; i < 24; ++i)
+ file->writeUint16BE(party._scents[i].toUint16());
+ for (uint16 i = 0; i < 24; ++i)
+ file->writeByte(party._scentStrengths[i]);
+ file->writeByte(party._event71Count_Invisibility);
+}
+
ChampionIndex ChampionMan::f285_getIndexInCell(int16 cell) {
for (uint16 i = 0; i < _g305_partyChampionCount; ++i) {
if ((_gK71_champions[i]._cell == cell) && _gK71_champions[i]._currHealth)
diff --git a/engines/dm/champion.h b/engines/dm/champion.h
index d4491d50c8..85afd6f6f9 100644
--- a/engines/dm/champion.h
+++ b/engines/dm/champion.h
@@ -580,6 +580,7 @@ public:
void f318_dropAllObjects(uint16 champIndex); // @ F0318_CHAMPION_DropAllObjects
void f323_unpoison(int16 champIndex); // @ F0323_CHAMPION_Unpoison
void f331_applyTimeEffects(); // @ F0331_CHAMPION_ApplyTimeEffects_CPSF
+ void save2_PartyPart(Common::OutSaveFile *file);
};
diff --git a/engines/dm/dm.cpp b/engines/dm/dm.cpp
index 526b60e5f1..d401c7bbe6 100644
--- a/engines/dm/dm.cpp
+++ b/engines/dm/dm.cpp
@@ -140,7 +140,6 @@ DMEngine::DMEngine(OSystem *syst) : Engine(syst), _console(nullptr) {
_eventMan = nullptr;
_menuMan = nullptr;
_championMan = nullptr;
- _loadsaveMan = nullptr;
_objectMan = nullptr;
_inventoryMan = nullptr;
_textMan = nullptr;
@@ -149,6 +148,10 @@ DMEngine::DMEngine(OSystem *syst) : Engine(syst), _console(nullptr) {
_timeline = nullptr;
_projexpl = nullptr;
+ _g528_saveFormat = 0;
+ _g527_platform = 0;
+ _g526_dungeonId = 0;
+
_g298_newGame = false;
_g523_restartGameRequest = false;
_g321_stopWaitingForPlayerInput = true;
@@ -187,7 +190,6 @@ DMEngine::~DMEngine() {
delete _eventMan;
delete _menuMan;
delete _championMan;
- delete _loadsaveMan;
delete _objectMan;
delete _inventoryMan;
delete _textMan;
@@ -220,7 +222,7 @@ void DMEngine::f463_initializeGame() {
_objectMan->loadObjectNames();
_eventMan->initMouse();
//F0441_STARTEND_ProcessEntrance();
- while (_loadsaveMan->f435_loadgame() != k1_LoadgameSuccess) {
+ while (f435_loadgame() != k1_LoadgameSuccess) {
warning(false, "TODO: F0441_STARTEND_ProcessEntrance");
}
//F0396_MENUS_LoadSpellAreaLinesBitmap() is not needed, every bitmap has been loaded
@@ -301,7 +303,6 @@ Common::Error DMEngine::run() {
_eventMan = new EventManager(this);
_menuMan = new MenuMan(this);
_championMan = new ChampionMan(this);
- _loadsaveMan = new LoadsaveMan(this);
_objectMan = new ObjectMan(this);
_inventoryMan = new InventoryMan(this);
_textMan = new TextMan(this);
diff --git a/engines/dm/dm.h b/engines/dm/dm.h
index dce88f17f8..dfc7b4c01c 100644
--- a/engines/dm/dm.h
+++ b/engines/dm/dm.h
@@ -31,6 +31,8 @@
#include "common/random.h"
#include "engines/engine.h"
#include "gui/debugger.h"
+#include "common/savefile.h"
+#include "common/str.h"
namespace DM {
@@ -41,7 +43,6 @@ class DungeonMan;
class EventManager;
class MenuMan;
class ChampionMan;
-class LoadsaveMan;
class ObjectMan;
class InventoryMan;
class TextMan;
@@ -50,6 +51,7 @@ class GroupMan;
class Timeline;
class ProjExpl;
+
void warning(bool repeat, const char *s, ...);
enum direction {
@@ -177,6 +179,11 @@ inline T f26_getBoundedValue(T min, T val, T max) {
#define k99_modeWaitingOnEntrance 99 // @ C099_MODE_WAITING_ON_ENTRANCE
#define k202_modeEntranceDrawCredits 202 // @ C202_MODE_ENTRANCE_DRAW_CREDITS
+enum LoadgameResponse {
+ kM1_LoadgameFailure = -1, // @ CM1_LOAD_GAME_FAILURE
+ k1_LoadgameSuccess = 1// @ C01_LOAD_GAME_SUCCESS
+};
+
class DMEngine : public Engine {
void f462_startGame(); // @ F0462_START_StartGame_CPSF
void f3_processNewPartyMap(uint16 mapIndex); // @ F0003_MAIN_ProcessNewPartyMap_CPSE
@@ -184,6 +191,8 @@ class DMEngine : public Engine {
void f448_initMemoryManager(); // @ F0448_STARTUP1_InitializeMemoryManager_CPSADEF
void f2_gameloop(); // @ F0002_MAIN_GameLoop_CPSDF
void initArrays();
+ Common::String getSavefileName(uint16 slot);
+ void writeSaveGameHeader(Common::OutSaveFile *out, const Common::String &saveName);
public:
explicit DMEngine(OSystem *syst);
~DMEngine();
@@ -195,8 +204,13 @@ public:
int16 M0_indexToOrdinal(int16 val); // @ M00_INDEX_TO_ORDINAL
void f19_displayErrorAndStop(int16 errorIndex); // @ F0019_MAIN_DisplayErrorAndStop
virtual Common::Error run(); // @ main
+ void f433_processCommand140_saveGame(uint16 slot, const Common::String desc); // @ F0433_STARTEND_ProcessCommand140_SaveGame_CPSCDF
+ LoadgameResponse f435_loadgame(); // @ F0435_STARTEND_LoadGame_CPSF
private:
+ int16 _g528_saveFormat; // @ G0528_i_Format
+ int16 _g527_platform; // @ G0527_i_Platform
+ uint16 _g526_dungeonId; // @ G0526_ui_DungeonID
Console *_console;
public:
Common::RandomSource *_rnd;
@@ -205,7 +219,6 @@ public:
EventManager *_eventMan;
MenuMan *_menuMan;
ChampionMan *_championMan;
- LoadsaveMan *_loadsaveMan;
ObjectMan *_objectMan;
InventoryMan *_inventoryMan;
TextMan *_textMan;
diff --git a/engines/dm/dungeonman.h b/engines/dm/dungeonman.h
index 1a91d5d61e..b3e4194249 100644
--- a/engines/dm/dungeonman.h
+++ b/engines/dm/dungeonman.h
@@ -604,7 +604,7 @@ public:
}; // wrapper for bytes which are used as squares
struct DungeonFileHeader {
- uint16 _dungeonId; // @ G0526_ui_DungeonID
+ uint16 _dungeonId;
// equal to dungeonId
uint16 _ornamentRandomSeed;
uint32 _rawMapDataSize;
diff --git a/engines/dm/group.cpp b/engines/dm/group.cpp
index edb6056aff..5961f7cb92 100644
--- a/engines/dm/group.cpp
+++ b/engines/dm/group.cpp
@@ -1691,7 +1691,7 @@ void GroupMan::f183_addActiveGroup(Thing thing, int16 mapX, int16 mapY) {
L0344_i_ActiveGroupIndex = 0;
while (L0341_ps_ActiveGroup->_groupThingIndex >= 0) {
if (++L0344_i_ActiveGroupIndex >= _vm->_groupMan->_g376_maxActiveGroupCount) {
- return;
+ return;
}
L0341_ps_ActiveGroup++;
}
@@ -2056,4 +2056,24 @@ void GroupMan::f225_fuseAction(uint16 mapX, uint16 mapY) {
warning(false, "F0446_STARTEND_FuseSequence()");
}
}
+
+void GroupMan::save1_ActiveGroupPart(Common::OutSaveFile* file) {
+ for (uint16 i = 0; i < _g376_maxActiveGroupCount; ++i) {
+ ActiveGroup *group = &_g375_activeGroups[i];
+ file->writeUint16BE(group->_groupThingIndex);
+ file->writeUint16BE(group->_directions);
+ file->writeByte(group->_cells);
+ file->writeByte(group->_lastMoveTime);
+ file->writeByte(group->_delayFleeingFromTarget);
+ file->writeByte(group->_targetMapX);
+ file->writeByte(group->_targetMapY);
+ file->writeByte(group->_priorMapX);
+ file->writeByte(group->_priorMapY);
+ file->writeByte(group->_homeMapX);
+ file->writeByte(group->_homeMapY);
+ for (uint16 j = 0; j < 4; ++j)
+ file->writeByte(group->_aspect[j]);
+ }
+}
+
}
diff --git a/engines/dm/group.h b/engines/dm/group.h
index 6578a20851..2ad2d8dd1d 100644
--- a/engines/dm/group.h
+++ b/engines/dm/group.h
@@ -92,7 +92,7 @@ enum CreatureType {
class ActiveGroup {
public:
- int _groupThingIndex;
+ int16 _groupThingIndex;
direction _directions;
byte _cells;
byte _lastMoveTime;
@@ -244,6 +244,7 @@ public:
uint16 f222_isLordChaosOnSquare(int16 mapX, int16 mapY); // @ F0222_GROUP_IsLordChaosOnSquare
bool f221_isFluxcageOnSquare(int16 mapX, int16 mapY); // @ F0221_GROUP_IsFluxcageOnSquare
void f225_fuseAction(uint16 mapX, uint16 mapY); // @ F0225_GROUP_FuseAction
+ void save1_ActiveGroupPart(Common::OutSaveFile *file);
};
diff --git a/engines/dm/loadsave.cpp b/engines/dm/loadsave.cpp
index 81a914c040..9d705ef8e5 100644
--- a/engines/dm/loadsave.cpp
+++ b/engines/dm/loadsave.cpp
@@ -24,39 +24,45 @@
* Based on the Reverse Engineering work of Christophe Fontanel,
* maintainer of the Dungeon Master Encyclopaedia (http://dmweb.free.fr/)
*/
+#include "common/system.h"
+#include "common/savefile.h"
+#include "graphics/thumbnail.h"
-#include "loadsave.h"
+#include "dm.h"
#include "dungeonman.h"
-#include "champion.h"
-#include "group.h"
#include "timeline.h"
-
+#include "group.h"
+#include "champion.h"
+#include "menus.h"
+#include "eventman.h"
+#include "projexpl.h"
namespace DM {
-
-LoadsaveMan::LoadsaveMan(DMEngine *vm) : _vm(vm) {}
-
-
-LoadgameResponse LoadsaveMan::f435_loadgame() {
- bool newGame = _vm->_g298_newGame;
- ChampionMan &cm = *_vm->_championMan;
-
+#define C2_FORMAT_DM_AMIGA_2X_PC98_X68000_FM_TOWNS_CSB_ATARI_ST 2
+#define C3_PLATFORM_AMIGA 3
+#define C10_DUNGEON_DM 10
+LoadgameResponse DMEngine::f435_loadgame() {
+ bool newGame = _g298_newGame;
+ ChampionMan &cm = *_championMan;
+ _g528_saveFormat = C2_FORMAT_DM_AMIGA_2X_PC98_X68000_FM_TOWNS_CSB_ATARI_ST;
+ _g527_platform = C3_PLATFORM_AMIGA;
+ _g526_dungeonId = C10_DUNGEON_DM;
if (newGame) {
- _vm->_g524_restartGameAllowed = false;
+ _g524_restartGameAllowed = false;
cm._g305_partyChampionCount = 0;
cm._g414_leaderHandObject = Thing::_none;
- _vm->_g525_gameId = _vm->_rnd->getRandomNumber(65536) * _vm->_rnd->getRandomNumber(65536);
+ _g525_gameId = _rnd->getRandomNumber(65536) * _rnd->getRandomNumber(65536);
} else {
assert(false);
// MISSING CODE: load game
}
- _vm->_dungeonMan->f434_loadDungeonFile();
+ _dungeonMan->f434_loadDungeonFile();
if (newGame) {
- _vm->_timeline->f233_initTimeline();
- _vm->_groupMan->f196_initActiveGroups();
+ _timeline->f233_initTimeline();
+ _groupMan->f196_initActiveGroups();
} else {
assert(false);
// MISSING CODE: load game
@@ -65,4 +71,110 @@ LoadgameResponse LoadsaveMan::f435_loadgame() {
return k1_LoadgameSuccess;
}
-} \ No newline at end of file
+
+void DMEngine::f433_processCommand140_saveGame(uint16 slot, const Common::String desc) {
+ char *message = nullptr;
+
+ _menuMan->f456_drawDisabledMenu();
+ _eventMan->f78_showMouse();
+
+ // do {
+ // ask the play what he wants
+ // while
+
+ // F0427_DIALOG_Draw(0, G0551_pc_SAVINGGAME, 0, 0, 0, 0, false, false, false);
+
+ uint16 champHandObjWeight;
+ if (!_championMan->_g415_leaderEmptyHanded) {
+ champHandObjWeight = _dungeonMan->f140_getObjectWeight(_championMan->_g414_leaderHandObject);
+ _championMan->_gK71_champions[_championMan->_g411_leaderIndex]._load -= champHandObjWeight;
+ }
+
+
+ Common::String savefileName = getSavefileName(slot);
+ Common::SaveFileManager *saveFileManager = _system->getSavefileManager();
+ Common::OutSaveFile *file = saveFileManager->openForSaving(savefileName);
+
+ if (!file)
+ return; // TODO: silent fail
+
+ writeSaveGameHeader(file, desc);
+
+ // write C0_SAVE_PART_GLOBAL_DATA part
+ file->writeUint32BE(_g313_gameTime);
+ //L1348_s_GlobalData.LastRandomNumber = G0349_ul_LastRandomNumber;
+ file->writeUint16BE(_championMan->_g305_partyChampionCount);
+ file->writeSint16BE(_dungeonMan->_g306_partyMapX);
+ file->writeSint16BE(_dungeonMan->_g307_partyMapY);
+ file->writeUint16BE(_dungeonMan->_g308_partyDir);
+ file->writeByte(_dungeonMan->_g309_partyMapIndex);
+ file->writeSint16BE(_championMan->_g411_leaderIndex);
+ file->writeSint16BE(_championMan->_g514_magicCasterChampionIndex);
+ file->writeUint16BE(_timeline->_g372_eventCount);
+ file->writeUint16BE(_timeline->_g373_firstUnusedEventIndex);
+ file->writeUint16BE(_timeline->_g369_eventMaxCount);
+ file->writeUint16BE(_groupMan->_g377_currActiveGroupCount);
+ file->writeSint32BE(_projexpl->_g361_lastCreatureAttackTime);
+ file->writeSint32BE(_projexpl->_g362_lastPartyMovementTime);
+ file->writeSint16BE(_g310_disabledMovementTicks);
+ file->writeSint16BE(_g311_projectileDisableMovementTicks);
+ file->writeSint16BE(_g312_lastProjectileDisabledMovementDirection);
+ file->writeUint16BE(_championMan->_g414_leaderHandObject.toUint16());
+ file->writeUint16BE(_groupMan->_g376_maxActiveGroupCount);
+
+ // write C1_SAVE_PART_ACTIVE_GROUP part
+ _groupMan->save1_ActiveGroupPart(file);
+ // write C2_SAVE_PART_PARTY part
+ _championMan->save2_PartyPart(file);
+ // write C3_SAVE_PART_EVENTS part
+ _timeline->save3_eventsPart(file);
+ // write C4_SAVE_PART_TIMELINE part
+ _timeline->save4_timelinePart(file);
+
+ file->writeSint32BE(_g525_gameId);
+ file->writeSint16BE(_g528_saveFormat);
+ file->writeSint16BE(_g527_platform);
+ file->writeUint16BE(_g526_dungeonId);
+
+ warning(false, "MISSING CODE in save game");
+
+ file->flush();
+ file->finalize();
+ delete file;
+}
+
+Common::String DMEngine::getSavefileName(uint16 slot) {
+ return Common::String::format("%s.%03u", _targetName.c_str(), slot);
+}
+
+#define SAVEGAME_ID MKTAG('D', 'M', 'D', 'M')
+#define SAVEGAME_VERSION 1
+
+void DMEngine::writeSaveGameHeader(Common::OutSaveFile* out, const Common::String& saveName) {
+ out->writeUint32BE(SAVEGAME_ID);
+
+ // Write version
+ out->writeByte(SAVEGAME_VERSION);
+
+ // Write savegame name
+ out->writeString(saveName);
+ out->writeByte(0);
+
+ // Save the game thumbnail
+ Graphics::saveThumbnail(*out);
+
+ // Creation date/time
+ TimeDate curTime;
+ _system->getTimeAndDate(curTime);
+
+ uint32 saveDate = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF);
+ uint16 saveTime = ((curTime.tm_hour & 0xFF) << 8) | ((curTime.tm_min) & 0xFF);
+ uint32 playTime = getTotalPlayTime() / 1000;
+
+ out->writeUint32BE(saveDate);
+ out->writeUint16BE(saveTime);
+ out->writeUint32BE(playTime);
+}
+
+
+}
diff --git a/engines/dm/loadsave.h b/engines/dm/loadsave.h
index c45b111ac9..85ed8a01da 100644
--- a/engines/dm/loadsave.h
+++ b/engines/dm/loadsave.h
@@ -32,17 +32,13 @@
namespace DM {
-enum LoadgameResponse {
- kM1_LoadgameFailure = -1, // @ CM1_LOAD_GAME_FAILURE
- k1_LoadgameSuccess = 1// @ C01_LOAD_GAME_SUCCESS
-};
+;
class LoadsaveMan {
DMEngine *_vm;
public:
explicit LoadsaveMan(DMEngine *vm);
- LoadgameResponse f435_loadgame(); // @ F0435_STARTEND_LoadGame_CPSF
};
}
diff --git a/engines/dm/timeline.cpp b/engines/dm/timeline.cpp
index 3858ad512e..afeb577eeb 100644
--- a/engines/dm/timeline.cpp
+++ b/engines/dm/timeline.cpp
@@ -1087,4 +1087,23 @@ T0255002:
_vm->_championMan->f283_viAltarRebirth(event->_priority);
}
}
+
+void Timeline::save3_eventsPart(Common::OutSaveFile* file) {
+ for (uint16 i = 0; i < _g369_eventMaxCount; ++i) {
+ TimelineEvent *event = &_g370_events[i];
+ file->writeSint32BE(event->_mapTime);
+ file->writeByte(event->_type);
+ file->writeByte(event->_priority);
+ file->writeByte(event->_B._location._mapX); // writing bytes of the union I think should preserve the union's identity
+ file->writeByte(event->_B._location._mapY);
+ file->writeUint16BE(event->_C.A._cell); // writing bytes of the union I think should preserve the union's identity
+ file->writeUint16BE(event->_C.A._effect);
+ }
+}
+
+void Timeline::save4_timelinePart(Common::OutSaveFile* file) {
+ for (uint16 i = 0; i < _g369_eventMaxCount; ++i)
+ file->writeUint16BE(_g371_timeline[i]);
+}
+
}
diff --git a/engines/dm/timeline.h b/engines/dm/timeline.h
index 08c6ce1c5f..8f68c35fe2 100644
--- a/engines/dm/timeline.h
+++ b/engines/dm/timeline.h
@@ -187,6 +187,8 @@ public:
void f257_timelineProcessEvent70_light(TimelineEvent *event); // @ F0257_TIMELINE_ProcessEvent70_Light
void f260_timelineRefreshAllChampionStatusBoxes(); // @ F0260_TIMELINE_RefreshAllChampionStatusBoxes
void f255_timelineProcessEvent13_ViAltarRebirth(TimelineEvent *event); // @ F0255_TIMELINE_ProcessEvent13_ViAltarRebirth
+ void save3_eventsPart(Common::OutSaveFile *file);
+ void save4_timelinePart(Common::OutSaveFile *file);
};