aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBendegúz Nagy2016-07-22 21:33:45 +0200
committerBendegúz Nagy2016-08-26 23:02:22 +0200
commitee3973aa153f5fba6485515cf1f51c1659fd31c4 (patch)
tree8959a81bbbeb842cfabf31e8526f68009f9db87f
parentaa92c3ba2067a011743ddfbb4db8d2376e92aceb (diff)
downloadscummvm-rg350-ee3973aa153f5fba6485515cf1f51c1659fd31c4.tar.gz
scummvm-rg350-ee3973aa153f5fba6485515cf1f51c1659fd31c4.tar.bz2
scummvm-rg350-ee3973aa153f5fba6485515cf1f51c1659fd31c4.zip
DM: Add code for loading the save files
-rw-r--r--engines/dm/champion.cpp66
-rw-r--r--engines/dm/champion.h1
-rw-r--r--engines/dm/dm.cpp13
-rw-r--r--engines/dm/dm.h12
-rw-r--r--engines/dm/group.cpp18
-rw-r--r--engines/dm/group.h1
-rw-r--r--engines/dm/loadsave.cpp140
-rw-r--r--engines/dm/timeline.cpp18
-rw-r--r--engines/dm/timeline.h2
9 files changed, 244 insertions, 27 deletions
diff --git a/engines/dm/champion.cpp b/engines/dm/champion.cpp
index f22d4dd605..aac5584777 100644
--- a/engines/dm/champion.cpp
+++ b/engines/dm/champion.cpp
@@ -1724,7 +1724,7 @@ void ChampionMan::save2_PartyPart(Common::OutSaveFile* file) {
file->writeUint16BE(champ->_cell);
file->writeUint16BE(champ->_actionIndex);
file->writeUint16BE(champ->_symbolStep);
- for(uint16 j = 0; j < 5; ++j)
+ for (uint16 j = 0; j < 5; ++j)
file->writeByte(champ->_symbols[j]);
file->writeUint16BE(champ->_directionMaximumDamageReceived);
file->writeUint16BE(champ->_maximumDamageReceived);
@@ -1757,13 +1757,75 @@ void ChampionMan::save2_PartyPart(Common::OutSaveFile* file) {
file->writeByte(party._freezeLifeTicks);
file->writeByte(party._firstScentIndex);
file->writeByte(party._lastScentIndex);
- for(uint16 i = 0; i < 24; ++i)
+ 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);
}
+void ChampionMan::load2_PartyPart(Common::InSaveFile* file) {
+ for (uint16 i = 0; i < 4; ++i) {
+ Champion *champ = &_gK71_champions[i];
+ champ->_attributes = file->readUint16BE();
+ champ->_wounds = file->readUint16BE();
+ for (uint16 y = 0; y < 7; ++y)
+ for (uint16 x = 0; x < 3; ++x)
+ champ->_statistics[y][x] = file->readByte();
+ for (uint16 j = 0; j < 30; ++j)
+ champ->_slots[j] = Thing(file->readUint16BE());
+ for (uint16 j = 0; j < 20; ++j) {
+ champ->_skills[j]._temporaryExperience = file->readSint16BE();
+ champ->_skills[j]._experience = file->readSint32BE();
+ }
+ for (uint16 j = 0; j < 8; ++j)
+ champ->_name[j] = file->readByte();
+ for (uint16 j = 0; j < 20; ++j)
+ champ->_title[j] = file->readByte();
+ champ->_dir = (direction)file->readUint16BE();
+ champ->_cell = (ViewCell)file->readUint16BE();
+ champ->_actionIndex = (ChampionAction)file->readUint16BE();
+ champ->_symbolStep = file->readUint16BE();
+ for (uint16 j = 0; j < 5; ++j)
+ champ->_symbols[j] = file->readByte();
+ champ->_directionMaximumDamageReceived = file->readUint16BE();
+ champ->_maximumDamageReceived = file->readUint16BE();
+ champ->_poisonEventCount = file->readUint16BE();
+ champ->_enableActionEventIndex = file->readSint16BE();
+ champ->_hideDamageReceivedIndex = file->readSint16BE();
+ champ->_currHealth = file->readSint16BE();
+ champ->_maxHealth = file->readSint16BE();
+ champ->_currStamina = file->readSint16BE();
+ champ->_maxStamina = file->readSint16BE();
+ champ->_currMana = file->readSint16BE();
+ champ->_maxMana = file->readSint16BE();
+ champ->_actionDefense = file->readSint16BE();
+ champ->_food = file->readSint16BE();
+ champ->_water = file->readSint16BE();
+ champ->_load = file->readUint16BE();
+ champ->_shieldDefense = file->readSint16BE();
+ for (uint16 j = 0; j < 928; ++j)
+ champ->_portrait[j] = file->readByte();
+ }
+
+ Party &party = _g407_party;
+ party._magicalLightAmount = file->readSint16BE();
+ party._event73Count_ThievesEye = file->readByte();
+ party._event79Count_Footprints = file->readByte();
+ party._shieldDefense = file->readSint16BE();
+ party._fireShieldDefense = file->readSint16BE();
+ party._spellShieldDefense = file->readSint16BE();
+ party._scentCount = file->readByte();
+ party._freezeLifeTicks = file->readByte();
+ party._firstScentIndex = file->readByte();
+ party._lastScentIndex = file->readByte();
+ for (uint16 i = 0; i < 24; ++i)
+ party._scents[i] = Scent(file->readUint16BE());
+ for (uint16 i = 0; i < 24; ++i)
+ party._scentStrengths[i] = file->readByte();
+ party._event71Count_Invisibility = file->readByte();
+}
+
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 15a07bebe7..17d8831179 100644
--- a/engines/dm/champion.h
+++ b/engines/dm/champion.h
@@ -586,6 +586,7 @@ public:
void f323_unpoison(int16 champIndex); // @ F0323_CHAMPION_Unpoison
void f331_applyTimeEffects(); // @ F0331_CHAMPION_ApplyTimeEffects_CPSF
void save2_PartyPart(Common::OutSaveFile *file);
+ void load2_PartyPart(Common::InSaveFile* file);
};
diff --git a/engines/dm/dm.cpp b/engines/dm/dm.cpp
index 2861cf1243..0aade77684 100644
--- a/engines/dm/dm.cpp
+++ b/engines/dm/dm.cpp
@@ -177,9 +177,6 @@ DMEngine::DMEngine(OSystem *syst) : Engine(syst), _console(nullptr) {
_g564_interfaceCredits = nullptr;
debug("DMEngine::DMEngine");
-
- warning(false, "DUMMY CODE: setting _g298_newGame to true, should be in processEntrance");
- _g298_newGame = true;
}
DMEngine::~DMEngine() {
@@ -222,7 +219,7 @@ uint16 DMEngine::f30_getScaledProduct(uint16 val, uint16 scale, uint16 vale2) {
void DMEngine::f463_initializeGame() {
_displayMan->f479_loadGraphics();
_displayMan->f460_initializeGraphicData();
- // DUMMY CODE: next line
+ warning(false, "Dummy code in f463_initializeGame, setting palette");
_displayMan->loadPalette(g21_PalDungeonView[0]);
_displayMan->f94_loadFloorSet(k0_FloorSetStone);
_displayMan->f95_loadWallSet(k0_WallSetStone);
@@ -231,12 +228,11 @@ void DMEngine::f463_initializeGame() {
_objectMan->loadObjectNames();
_eventMan->initMouse();
f441_processEntrance();
- while (f435_loadgame() != k1_LoadgameSuccess) {
+ while (f435_loadgame(1) != k1_LoadgameSuccess) {
f441_processEntrance();
}
//F0396_MENUS_LoadSpellAreaLinesBitmap() is not needed, every bitmap has been loaded
-
// There was some memory wizardy for the Amiga platform, I skipped that part
_displayMan->f461_allocateFlippedWallBitmaps();
@@ -321,7 +317,7 @@ Common::Error DMEngine::run() {
_projexpl = new ProjExpl(this);
_displayMan->setUpScreens(320, 200);
- f463_initializeGame(); // @ F0463_START_InitializeGame_CPSADEF
+ f463_initializeGame();
while (true) {
f2_gameloop();
warning(false, "TODO: F0444_STARTEND_Endgame(G0303_B_PartyDead);");
@@ -490,7 +486,6 @@ void DMEngine::f441_processEntrance() {
_g562_entranceDoorAnimSteps[i] = nullptr;
}
-
void DMEngine::f439_drawEntrance() {
static Box K0079_s_Box_Entrance_DoorsUpperHalf = {0, 231, 0, 80};
static Box K0152_s_Box_Entrance_DoorsLowerHalf = {0, 231, 81, 160};
@@ -508,7 +503,7 @@ void DMEngine::f439_drawEntrance() {
_dungeonMan->_g271_currMapData = L1398_apuc_MicroDungeonCurrentMapData;
Map map; // uninitialized, won't be used
- _dungeonMan->_g269_currMap = &map;
+ _dungeonMan->_g269_currMap = &map;
for (uint16 i = 0; i < 25; ++i)
L1399_auc_MicroDungeonSquares[i] = Square(k0_ElementTypeWall, 0);
for (L1397_ui_ColumnIndex = 0; L1397_ui_ColumnIndex < 5; L1397_ui_ColumnIndex++) {
diff --git a/engines/dm/dm.h b/engines/dm/dm.h
index cbc0bd35e0..279144bc4d 100644
--- a/engines/dm/dm.h
+++ b/engines/dm/dm.h
@@ -33,6 +33,8 @@
#include "gui/debugger.h"
#include "common/savefile.h"
#include "common/str.h"
+#include "engines/savestate.h"
+
namespace DM {
@@ -184,6 +186,13 @@ enum LoadgameResponse {
k1_LoadgameSuccess = 1// @ C01_LOAD_GAME_SUCCESS
};
+
+struct SaveGameHeader {
+ byte _version;
+ SaveStateDescriptor _descr;
+};
+
+
class DMEngine : public Engine {
void f462_startGame(); // @ F0462_START_StartGame_CPSF
void f3_processNewPartyMap(uint16 mapIndex); // @ F0003_MAIN_ProcessNewPartyMap_CPSE
@@ -193,6 +202,7 @@ class DMEngine : public Engine {
void initArrays();
Common::String getSavefileName(uint16 slot);
void writeSaveGameHeader(Common::OutSaveFile *out, const Common::String &saveName);
+ bool readSaveGameHeader(Common::InSaveFile *file, SaveGameHeader *header);
void f439_drawEntrance(); // @ F0439_STARTEND_DrawEntrance
public:
explicit DMEngine(OSystem *syst);
@@ -207,7 +217,7 @@ public:
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
+ LoadgameResponse f435_loadgame(int16 slot); // @ F0435_STARTEND_LoadGame_CPSF
void f441_processEntrance(); // @ F0441_STARTEND_ProcessEntrance
private:
diff --git a/engines/dm/group.cpp b/engines/dm/group.cpp
index e59a6e7846..6f6991e4b5 100644
--- a/engines/dm/group.cpp
+++ b/engines/dm/group.cpp
@@ -2077,4 +2077,22 @@ void GroupMan::save1_ActiveGroupPart(Common::OutSaveFile* file) {
}
}
+void GroupMan::load1_ActiveGroupPart(Common::InSaveFile* file) {
+ for (uint16 i = 0; i < _g376_maxActiveGroupCount; ++i) {
+ ActiveGroup *group = &_g375_activeGroups[i];
+ group->_groupThingIndex = file->readUint16BE();
+ group->_directions = (direction)file->readUint16BE();
+ group->_cells = file->readByte();
+ group->_lastMoveTime = file->readByte();
+ group->_delayFleeingFromTarget = file->readByte();
+ group->_targetMapX = file->readByte();
+ group->_targetMapY = file->readByte();
+ group->_priorMapX = file->readByte();
+ group->_priorMapY = file->readByte();
+ group->_homeMapX = file->readByte();
+ group->_homeMapY = file->readByte();
+ for (uint16 j = 0; j < 4; ++j)
+ group->_aspect[j] = file->readByte();
+ }
+}
}
diff --git a/engines/dm/group.h b/engines/dm/group.h
index 2ad2d8dd1d..699f195aa9 100644
--- a/engines/dm/group.h
+++ b/engines/dm/group.h
@@ -245,6 +245,7 @@ public:
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);
+ void load1_ActiveGroupPart(Common::InSaveFile* file);
};
diff --git a/engines/dm/loadsave.cpp b/engines/dm/loadsave.cpp
index 28b57f2651..9b50351376 100644
--- a/engines/dm/loadsave.cpp
+++ b/engines/dm/loadsave.cpp
@@ -42,32 +42,96 @@ namespace DM {
#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;
+LoadgameResponse DMEngine::f435_loadgame(int16 slot) {
+ Common::String fileName;
+ Common::SaveFileManager *saveFileManager = nullptr;
+ Common::InSaveFile *file = nullptr;
+
+ if (!_g298_newGame) {
+ fileName = getSavefileName(slot);
+ saveFileManager = _system->getSavefileManager();
+ file = saveFileManager->openForLoading(fileName);
+ }
+
_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) {
+ if (_g298_newGame) {
+ //L1366_B_FadePalette = !F0428_DIALOG_RequireGameDiskInDrive_NoDialogDrawn(C0_DO_NOT_FORCE_DIALOG_DM_CSB, true);
+T0435002:
_g524_restartGameAllowed = false;
- cm._g305_partyChampionCount = 0;
- cm._g414_leaderHandObject = Thing::_none;
- _g525_gameId = _rnd->getRandomNumber(65536) * _rnd->getRandomNumber(65536);
+ _championMan->_g305_partyChampionCount = 0;
+ _championMan->_g414_leaderHandObject = Thing::_none;
+ _g525_gameId = ((int32)getRandomNumber(65536)) * getRandomNumber(65536);
} else {
- assert(false);
- // MISSING CODE: load game
- }
- _dungeonMan->f434_loadDungeonFile();
+ warning(false, "MISSING CODE: missing check for matching _g525_gameId in f435_loadgame");
+ /*if (_vm->_g523_restartGameRequest && (L1372_s_SaveHeader.GameID != _vm->_g525_gameId)) {
+ L1367_pc_Message = G0546_pc_THATSNOTTHESAMEGAME;
+ goto T0435004;
+ }*/
+
+ SaveGameHeader header;
+ readSaveGameHeader(file, &header);
+
+ warning(false, "MISSING CODE: missing check for matching format and platform in save in f435_loadgame");
+
+ _g313_gameTime = file->readUint32BE();
+ // G0349_ul_LastRandomNumber = L1371_s_GlobalData.LastRandomNumber;
+ _championMan->_g305_partyChampionCount = file->readUint16BE();
+ _dungeonMan->_g306_partyMapX = file->readSint16BE();
+ _dungeonMan->_g307_partyMapY = file->readSint16BE();
+ _dungeonMan->_g308_partyDir = (direction)file->readUint16BE();
+ _dungeonMan->_g309_partyMapIndex = file->readByte();
+ _championMan->_g411_leaderIndex = (ChampionIndex)file->readSint16BE();
+ _championMan->_g514_magicCasterChampionIndex = (ChampionIndex)file->readSint16BE();
+ _timeline->_g372_eventCount = file->readUint16BE();
+ _timeline->_g373_firstUnusedEventIndex = file->readUint16BE();
+ _timeline->_g369_eventMaxCount = file->readUint16BE();
+ _groupMan->_g377_currActiveGroupCount = file->readUint16BE();
+ _projexpl->_g361_lastCreatureAttackTime = file->readSint32BE();
+ _projexpl->_g362_lastPartyMovementTime = file->readSint32BE();
+ _g310_disabledMovementTicks = file->readSint16BE();
+ _g311_projectileDisableMovementTicks = file->readSint16BE();
+ _g312_lastProjectileDisabledMovementDirection = file->readSint16BE();
+ _championMan->_g414_leaderHandObject = Thing(file->readUint16BE());
+ _groupMan->_g376_maxActiveGroupCount = file->readUint16BE();
+ if (!_g523_restartGameRequest) {
+ _timeline->f233_initTimeline();
+ _groupMan->f196_initActiveGroups();
+ }
- if (newGame) {
+ _groupMan->load1_ActiveGroupPart(file);
+ _championMan->load2_PartyPart(file);
+ _timeline->load3_eventsPart(file);
+ _timeline->load4_timelinePart(file);
+
+ _g525_gameId = file->readSint32BE();
+ }
+
+ _dungeonMan->f434_loadDungeonFile();
+ if (_g298_newGame) {
_timeline->f233_initTimeline();
_groupMan->f196_initActiveGroups();
+ warning(false, "MISSING CODE: missing fadePlette stuff in f435_loadgame on newGame");
+ /*
+ if (L1366_B_FadePalette) {
+ F0436_STARTEND_FadeToPalette(G0345_aui_BlankBuffer);
+ D26_WaitForVerticalBlank();
+ D18_FillScreenBlack();
+ F0436_STARTEND_FadeToPalette(_vm->_displayMan->_g347_paletteTopAndBottomScreen);
+ }*/
} else {
- assert(false);
- // MISSING CODE: load game
+ _g528_saveFormat = file->readSint16BE();
+ _g527_platform = file->readSint16BE();
+ _g526_dungeonId = file->readUint16BE();
+
+ _g524_restartGameAllowed = true;
+ warning(false, "MISSING CDOE: F0427_DIALOG_Draw in f435_loadgame");
}
- cm._g303_partyDead = false;
+ _championMan->_g303_partyDead = false;
+
+ delete file;
return k1_LoadgameSuccess;
}
@@ -176,4 +240,50 @@ void DMEngine::writeSaveGameHeader(Common::OutSaveFile* out, const Common::Strin
out->writeUint32BE(playTime);
}
+
+bool DMEngine::readSaveGameHeader(Common::InSaveFile* in, SaveGameHeader* header) {
+ uint32 id = in->readUint32BE();
+
+ // Check if it's a valid ScummVM savegame
+ if (id != SAVEGAME_ID)
+ return false;
+
+ // Read in the version
+ header->_version = in->readByte();
+
+ // Check that the save version isn't newer than this binary
+ if (header->_version > SAVEGAME_VERSION)
+ return false;
+
+ // Read in the save name
+ Common::String saveName;
+ char ch;
+ while ((ch = (char)in->readByte()) != '\0')
+ saveName += ch;
+ header->_descr.setDescription(saveName);
+
+ // Get the thumbnail
+ header->_descr.setThumbnail(Graphics::loadThumbnail(*in));
+
+ uint32 saveDate = in->readUint32BE();
+ uint16 saveTime = in->readUint16BE();
+ uint32 playTime = in->readUint32BE();
+
+ int day = (saveDate >> 24) & 0xFF;
+ int month = (saveDate >> 16) & 0xFF;
+ int year = saveDate & 0xFFFF;
+ header->_descr.setSaveDate(year, month, day);
+
+ int hour = (saveTime >> 8) & 0xFF;
+ int minutes = saveTime & 0xFF;
+ header->_descr.setSaveTime(hour, minutes);
+
+ header->_descr.setPlayTime(playTime * 1000);
+ if (g_engine)
+ g_engine->setTotalPlayTime(playTime * 1000);
+
+ return true;
}
+
+}
+
diff --git a/engines/dm/timeline.cpp b/engines/dm/timeline.cpp
index afeb577eeb..37eb880690 100644
--- a/engines/dm/timeline.cpp
+++ b/engines/dm/timeline.cpp
@@ -1106,4 +1106,22 @@ void Timeline::save4_timelinePart(Common::OutSaveFile* file) {
file->writeUint16BE(_g371_timeline[i]);
}
+void Timeline::load3_eventsPart(Common::InSaveFile* file) {
+ for (uint16 i = 0; i < _g369_eventMaxCount; ++i) {
+ TimelineEvent *event = &_g370_events[i];
+ event->_mapTime = file->readSint32BE();
+ event->_type = file->readByte();
+ event->_priority = file->readByte();
+ event->_B._location._mapX = file->readByte();
+ event->_B._location._mapY = file->readByte();
+ event->_C.A._cell = file->readUint16BE();
+ event->_C.A._effect = file->readUint16BE();
+ }
+}
+
+void Timeline::load4_timelinePart(Common::InSaveFile* file) {
+ for (uint16 i = 0; i < _g369_eventMaxCount; ++i)
+ _g371_timeline[i] = file->readUint16BE();
+}
+
}
diff --git a/engines/dm/timeline.h b/engines/dm/timeline.h
index 8f68c35fe2..2d722d5569 100644
--- a/engines/dm/timeline.h
+++ b/engines/dm/timeline.h
@@ -189,6 +189,8 @@ public:
void f255_timelineProcessEvent13_ViAltarRebirth(TimelineEvent *event); // @ F0255_TIMELINE_ProcessEvent13_ViAltarRebirth
void save3_eventsPart(Common::OutSaveFile *file);
void save4_timelinePart(Common::OutSaveFile *file);
+ void load3_eventsPart(Common::InSaveFile* file);
+ void load4_timelinePart(Common::InSaveFile* file);
};