LAB: Rewrite the save/load system
The two different save/load dialogs from the original have been dropped and replaced with the ScummVM save/load dialogs. The whole save/load code has been rewritten to be endian safe and use our common code. The original save format has not been preserved. The current implementation crashes when loading, but it's a good start
This commit is contained in:
parent
6af7abeab2
commit
0a71969018
10 changed files with 324 additions and 4628 deletions
|
@ -29,11 +29,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "engines/advancedDetector.h"
|
#include "engines/advancedDetector.h"
|
||||||
|
|
||||||
#include "common/system.h"
|
#include "common/system.h"
|
||||||
|
#include "common/str-array.h"
|
||||||
|
#include "common/savefile.h"
|
||||||
|
|
||||||
#include "base/plugins.h"
|
#include "base/plugins.h"
|
||||||
|
|
||||||
|
#include "graphics/surface.h"
|
||||||
|
|
||||||
#include "lab/lab.h"
|
#include "lab/lab.h"
|
||||||
|
#include "lab/labfun.h"
|
||||||
|
|
||||||
static const PlainGameDescriptor lab_setting[] = {
|
static const PlainGameDescriptor lab_setting[] = {
|
||||||
{ "lab", "Labyrith of Time" },
|
{ "lab", "Labyrith of Time" },
|
||||||
|
@ -143,8 +149,112 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool hasFeature(MetaEngineFeature f) const;
|
||||||
|
SaveStateList listSaves(const char *target) const;
|
||||||
|
virtual int getMaximumSaveSlot() const;
|
||||||
|
void removeSaveState(const char *target, int slot) const;
|
||||||
|
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool LabMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||||
|
return
|
||||||
|
(f == kSupportsListSaves) ||
|
||||||
|
//(f == kSupportsLoadingDuringStartup) ||
|
||||||
|
(f == kSupportsDeleteSave) ||
|
||||||
|
(f == kSavesSupportMetaInfo) ||
|
||||||
|
(f == kSavesSupportThumbnail) ||
|
||||||
|
(f == kSavesSupportCreationDate) ||
|
||||||
|
(f == kSavesSupportPlayTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Lab::LabEngine::hasFeature(EngineFeature f) const {
|
||||||
|
return
|
||||||
|
(f == kSupportsRTL);
|
||||||
|
//(f == kSupportsLoadingDuringRuntime) ||
|
||||||
|
//(f == kSupportsSavingDuringRuntime);
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveStateList LabMetaEngine::listSaves(const char *target) const {
|
||||||
|
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||||
|
Lab::SaveGameHeader header;
|
||||||
|
Common::String pattern = target;
|
||||||
|
pattern += ".???";
|
||||||
|
|
||||||
|
Common::StringArray filenames;
|
||||||
|
filenames = saveFileMan->listSavefiles(pattern.c_str());
|
||||||
|
Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)*/
|
||||||
|
|
||||||
|
SaveStateList saveList;
|
||||||
|
|
||||||
|
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
|
||||||
|
// Obtain the last 3 digits of the filename, since they correspond to the save slot
|
||||||
|
int slotNum = atoi(file->c_str() + file->size() - 3);
|
||||||
|
|
||||||
|
if (slotNum >= 0 && slotNum <= 999) {
|
||||||
|
Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
|
||||||
|
if (in) {
|
||||||
|
if (Lab::readSaveGameHeader(in, header))
|
||||||
|
saveList.push_back(SaveStateDescriptor(slotNum, header.desc.getDescription()));
|
||||||
|
delete in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return saveList;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LabMetaEngine::getMaximumSaveSlot() const {
|
||||||
|
return 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||||
|
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||||
|
Common::String filename = Common::String::format("%s.%03u", target, slot);
|
||||||
|
|
||||||
|
saveFileMan->removeSavefile(filename.c_str());
|
||||||
|
|
||||||
|
Common::StringArray filenames;
|
||||||
|
Common::String pattern = target;
|
||||||
|
pattern += ".???";
|
||||||
|
filenames = saveFileMan->listSavefiles(pattern.c_str());
|
||||||
|
Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
|
||||||
|
|
||||||
|
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
|
||||||
|
// Obtain the last 3 digits of the filename, since they correspond to the save slot
|
||||||
|
int slotNum = atoi(file->c_str() + file->size() - 3);
|
||||||
|
|
||||||
|
// Rename every slot greater than the deleted slot,
|
||||||
|
if (slotNum > slot) {
|
||||||
|
saveFileMan->renameSavefile(file->c_str(), filename.c_str());
|
||||||
|
filename = Common::String::format("%s.%03u", target, ++slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveStateDescriptor LabMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||||
|
Common::String filename = Common::String::format("%s.%03u", target, slot);
|
||||||
|
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
|
||||||
|
|
||||||
|
if (in) {
|
||||||
|
Lab::SaveGameHeader header;
|
||||||
|
|
||||||
|
bool successfulRead = Lab::readSaveGameHeader(in, header);
|
||||||
|
delete in;
|
||||||
|
|
||||||
|
if (successfulRead) {
|
||||||
|
SaveStateDescriptor desc(slot, header.desc.getDescription());
|
||||||
|
// Do not allow save slot 0 (used for auto-saving) to be deleted or
|
||||||
|
// overwritten.
|
||||||
|
//desc.setDeletableFlag(slot != 0);
|
||||||
|
//desc.setWriteProtectedFlag(slot == 0);
|
||||||
|
|
||||||
|
return header.desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SaveStateDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
#if PLUGIN_ENABLED_DYNAMIC(LAB)
|
#if PLUGIN_ENABLED_DYNAMIC(LAB)
|
||||||
REGISTER_PLUGIN_DYNAMIC(LAB, PLUGIN_TYPE_ENGINE, LabMetaEngine);
|
REGISTER_PLUGIN_DYNAMIC(LAB, PLUGIN_TYPE_ENGINE, LabMetaEngine);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -1451,8 +1451,6 @@ void LabEngine::go() {
|
||||||
mem = mem && initRoomBuffer() &&
|
mem = mem && initRoomBuffer() &&
|
||||||
initLabText();
|
initLabText();
|
||||||
|
|
||||||
doDisks();
|
|
||||||
|
|
||||||
if (!dointro)
|
if (!dointro)
|
||||||
g_music->initMusic();
|
g_music->initMusic();
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,6 @@
|
||||||
|
|
||||||
namespace Lab {
|
namespace Lab {
|
||||||
|
|
||||||
bool LabEngine::hasFeature(EngineFeature f) const {
|
|
||||||
return (f == kSupportsRTL) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LabEngine *g_lab;
|
LabEngine *g_lab;
|
||||||
|
|
||||||
LabEngine::LabEngine(OSystem *syst, const ADGameDescription *gameDesc)
|
LabEngine::LabEngine(OSystem *syst, const ADGameDescription *gameDesc)
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
#include "lab/stddefines.h"
|
#include "lab/stddefines.h"
|
||||||
#include "lab/parsetypes.h"
|
#include "lab/parsetypes.h"
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
|
#include "common/savefile.h"
|
||||||
|
|
||||||
|
#include "engines/savestate.h"
|
||||||
|
|
||||||
namespace Lab {
|
namespace Lab {
|
||||||
|
|
||||||
|
@ -54,6 +57,13 @@ struct Image;
|
||||||
struct TextFont;
|
struct TextFont;
|
||||||
struct Gadget;
|
struct Gadget;
|
||||||
|
|
||||||
|
struct SaveGameHeader {
|
||||||
|
byte version;
|
||||||
|
SaveStateDescriptor desc;
|
||||||
|
uint16 roomNumber;
|
||||||
|
uint16 direction;
|
||||||
|
};
|
||||||
|
|
||||||
/*----------------------------*/
|
/*----------------------------*/
|
||||||
/*------ From Audioi.c -------*/
|
/*------ From Audioi.c -------*/
|
||||||
/*----------------------------*/
|
/*----------------------------*/
|
||||||
|
@ -345,8 +355,6 @@ void doWestPaper(void);
|
||||||
|
|
||||||
void doMonitor(char *background, char *textfile, bool isinteractive, uint16 x1, uint16 y1, uint16 x2, uint16 y2);
|
void doMonitor(char *background, char *textfile, bool isinteractive, uint16 x1, uint16 y1, uint16 x2, uint16 y2);
|
||||||
|
|
||||||
uint16 doDisks(void);
|
|
||||||
|
|
||||||
bool saveRestoreGame(void);
|
bool saveRestoreGame(void);
|
||||||
|
|
||||||
|
|
||||||
|
@ -355,11 +363,10 @@ bool saveRestoreGame(void);
|
||||||
/*----- From saveGame.c ----*/
|
/*----- From saveGame.c ----*/
|
||||||
/*--------------------------*/
|
/*--------------------------*/
|
||||||
|
|
||||||
bool saveFloppy(char *path, uint16 RoomNum, uint16 Direction, uint16 NumQuarters, uint16 filenum, uint16 type);
|
bool saveGame(uint16 RoomNum, uint16 Direction, uint16 Quarters, int slot, Common::String desc);
|
||||||
|
bool loadGame(uint16 *RoomNum, uint16 *Direction, uint16 *Quarters, int slot);
|
||||||
bool readFloppy(char *path, uint16 *RoomNum, uint16 *Direction, uint16 *NumQuarters, uint16 filenum, uint16 type);
|
|
||||||
|
|
||||||
|
|
||||||
|
bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header);
|
||||||
|
|
||||||
/*--------------------------*/
|
/*--------------------------*/
|
||||||
/*----- From Special.c -----*/
|
/*----- From Special.c -----*/
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
|
||||||
*
|
|
||||||
* ScummVM is the legal property of its developers, whose names
|
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
||||||
* file distributed with this source distribution.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This code is based on Labyrinth of Time code with assistance of
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993 Terra Nova Development
|
|
||||||
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lab/stddefines.h"
|
|
||||||
#include "lab/labfun.h"
|
|
||||||
#include "lab/modernsavegame.h"
|
|
||||||
|
|
||||||
namespace Lab {
|
|
||||||
|
|
||||||
byte g_SaveGameImage[SAVED_IMAGE_SIZE]; // 640 x 358
|
|
||||||
|
|
||||||
char g_SaveGamePath[512];
|
|
||||||
char g_PathSeperator[4];
|
|
||||||
|
|
||||||
#define SAVEVERSION "LBS3"
|
|
||||||
|
|
||||||
int getSaveGameList(SaveGameInfo *info, int maxNum) {
|
|
||||||
warning("STUB: getSaveGameList");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
char path[512];
|
|
||||||
struct stat statb;
|
|
||||||
int total = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < maxNum; i++) {
|
|
||||||
checkMusic();
|
|
||||||
|
|
||||||
sprintf(path, "%s%s%d", g_SaveGamePath, g_PathSeperator, i);
|
|
||||||
statb.st_size = 0;
|
|
||||||
stat(path, &statb);
|
|
||||||
|
|
||||||
if (statb.st_size > 0) {
|
|
||||||
struct tm *create_date;
|
|
||||||
FILE *fh;
|
|
||||||
|
|
||||||
create_date = localtime(&statb.st_ctime);
|
|
||||||
strcpy(info->SaveGameDate, asctime(create_date));
|
|
||||||
|
|
||||||
fh = fopen(path, "rb");
|
|
||||||
|
|
||||||
if (fh != NULL) {
|
|
||||||
char temp[5];
|
|
||||||
unsigned short t;
|
|
||||||
int toSeek;
|
|
||||||
|
|
||||||
info->Index = i;
|
|
||||||
|
|
||||||
fread(temp, 1, 4, fh);
|
|
||||||
temp[4] = 0;
|
|
||||||
|
|
||||||
fread(&t, 1, 2, fh);
|
|
||||||
info->RoomNumber = swapUShort(t);
|
|
||||||
fread(&t, 1, 2, fh);
|
|
||||||
info->Direction = swapUShort(t);
|
|
||||||
|
|
||||||
toSeek = 2 + Conditions->lastElement / 8 + g_lab->_roomsFound->_lastElement / 8 + 6 + 2 * 16;
|
|
||||||
fseek(fh, toSeek, SEEK_CUR);
|
|
||||||
|
|
||||||
info->SaveGameImage = NULL;
|
|
||||||
|
|
||||||
if (strcmp(temp, SAVEVERSION) == 0) {
|
|
||||||
info->SaveGameImage = malloc(SAVED_IMAGE_SIZE);
|
|
||||||
|
|
||||||
if (info->SaveGameImage != NULL)
|
|
||||||
fread(info->SaveGameImage, 1, SAVED_IMAGE_SIZE, fh);
|
|
||||||
} else {
|
|
||||||
info->SaveGameImage = malloc(SAVED_IMAGE_SIZE);
|
|
||||||
|
|
||||||
if (info->SaveGameImage != NULL)
|
|
||||||
memset(info->SaveGameImage, 0, SAVED_IMAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fh);
|
|
||||||
|
|
||||||
info++;
|
|
||||||
total++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void freeSaveGameList(SaveGameInfo *info, int count) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
free(info->SaveGameImage);
|
|
||||||
++info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End of namespace Lab
|
|
|
@ -1,55 +0,0 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
|
||||||
*
|
|
||||||
* ScummVM is the legal property of its developers, whose names
|
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
||||||
* file distributed with this source distribution.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This code is based on Labyrinth of Time code with assistance of
|
|
||||||
*
|
|
||||||
* Copyright (c) 1993 Terra Nova Development
|
|
||||||
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LAB_MODERNGAMESAVE_H
|
|
||||||
#define LAB_MODERNGAMESAVE_H
|
|
||||||
|
|
||||||
namespace Lab {
|
|
||||||
|
|
||||||
#define MAX_SAVED_GAMES 15
|
|
||||||
#define SAVED_IMAGE_SIZE (128 * 72)
|
|
||||||
|
|
||||||
extern byte g_SaveGameImage[SAVED_IMAGE_SIZE]; // 640 x 358
|
|
||||||
|
|
||||||
struct SaveGameInfo {
|
|
||||||
unsigned short Index;
|
|
||||||
unsigned short RoomNumber;
|
|
||||||
unsigned short Direction;
|
|
||||||
byte *SaveGameImage;
|
|
||||||
char SaveGameDate[128];
|
|
||||||
};
|
|
||||||
|
|
||||||
int getSaveGameList(SaveGameInfo *info, int maxNum);
|
|
||||||
void freeSaveGameList(SaveGameInfo *info, int count);
|
|
||||||
|
|
||||||
} // End of namespace Lab
|
|
||||||
|
|
||||||
#endif /* LAB_MODERNGAMESAVE_H */
|
|
||||||
|
|
|
@ -15,13 +15,11 @@ MODULE_OBJS := \
|
||||||
labtext.o \
|
labtext.o \
|
||||||
machine.o \
|
machine.o \
|
||||||
map.o \
|
map.o \
|
||||||
modernsavegame.o \
|
|
||||||
mouse.o \
|
mouse.o \
|
||||||
processroom.o \
|
processroom.o \
|
||||||
readdiff.o \
|
readdiff.o \
|
||||||
readparse.o \
|
readparse.o \
|
||||||
savegame.o \
|
savegame.o \
|
||||||
savegamepalmap.o \
|
|
||||||
special.o \
|
special.o \
|
||||||
text.o \
|
text.o \
|
||||||
timing.o \
|
timing.o \
|
||||||
|
|
|
@ -28,167 +28,155 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "common/savefile.h"
|
||||||
|
|
||||||
|
#include "graphics/surface.h"
|
||||||
|
#include "graphics/thumbnail.h"
|
||||||
|
|
||||||
#include "lab/lab.h"
|
#include "lab/lab.h"
|
||||||
#include "lab/stddefines.h"
|
#include "lab/stddefines.h"
|
||||||
#include "lab/labfun.h"
|
#include "lab/labfun.h"
|
||||||
#include "lab/modernsavegame.h"
|
|
||||||
|
|
||||||
namespace Lab {
|
namespace Lab {
|
||||||
|
|
||||||
/* The version string */
|
// Labyrinth of Time ScummVM
|
||||||
#if defined(DOSCODE)
|
#define SAVEGAME_ID MKTAG('L', 'O', 'T', 'S')
|
||||||
#define SAVEVERSION "LBS2"
|
#define SAVEGAME_VERSION 1
|
||||||
#else
|
|
||||||
#define SAVEVERSION "LBS3"
|
|
||||||
#define SAVEVERSION_COMPAT "LBS2"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BOOKMARK 0
|
#define BOOKMARK 0
|
||||||
#define CARDMARK 1
|
#define CARDMARK 1
|
||||||
#define FLOPPY 2
|
#define FLOPPY 2
|
||||||
|
|
||||||
typedef void *LABFH;
|
|
||||||
#define INVALID_LABFH NULL
|
|
||||||
|
|
||||||
uint16 FileType, FileNum;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*----- The Amiga specific area of saveGame.c -----*/
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Opens a file to write to from disk. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static LABFH saveGameOpen(char *filename, bool iswrite) {
|
|
||||||
warning("STUB: saveGameOpen");
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (iswrite) {
|
|
||||||
unlink(filename);
|
|
||||||
return fopen(filename, "wb");
|
|
||||||
} else
|
|
||||||
return fopen(filename, "rb");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Closes a file. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static void saveGameClose(LABFH file, bool iswrite) {
|
|
||||||
warning("STUB: saveGameClose");
|
|
||||||
return;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (file != INVALID_LABFH)
|
|
||||||
fclose(file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Writes a block of memory to whatever it is that we're writing to. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static void saveGameWriteBlock(LABFH file, void *data, uint32 size) {
|
|
||||||
warning("STUB: saveGameWriteBlock");
|
|
||||||
return;
|
|
||||||
|
|
||||||
//fwrite(data, 1, size, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Writes a block of memory to whatever it is that we're writing to. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static void saveGameReadBlock(LABFH file, void *data, uint32 size) {
|
|
||||||
warning("STUB: saveGameReadBlock");
|
|
||||||
return;
|
|
||||||
|
|
||||||
//fread(data, 1, size, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*----- The machine independent section of saveGame.c -----*/
|
/*----- The machine independent section of saveGame.c -----*/
|
||||||
|
|
||||||
|
|
||||||
/* Lab: Labyrinth specific */
|
/* Lab: Labyrinth specific */
|
||||||
extern uint16 combination[6];
|
extern byte combination[6];
|
||||||
extern uint16 CurTile[4] [4];
|
extern uint16 CurTile[4] [4];
|
||||||
|
|
||||||
#if !defined(DOSCODE)
|
|
||||||
extern CrumbData BreadCrumbs[MAX_CRUMBS];
|
extern CrumbData BreadCrumbs[MAX_CRUMBS];
|
||||||
extern uint16 NumCrumbs;
|
extern uint16 NumCrumbs;
|
||||||
extern bool DroppingCrumbs;
|
extern bool DroppingCrumbs;
|
||||||
extern bool FollowingCrumbs;
|
extern bool FollowingCrumbs;
|
||||||
#endif
|
|
||||||
|
void 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;
|
||||||
|
g_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 = g_engine->getTotalPlayTime() / 1000;
|
||||||
|
|
||||||
|
out->writeUint32BE(saveDate);
|
||||||
|
out->writeUint16BE(saveTime);
|
||||||
|
out->writeUint32BE(playTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool 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.desc.setDescription(saveName);
|
||||||
|
|
||||||
|
// Get the thumbnail
|
||||||
|
header.desc.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.desc.setSaveDate(year, month, day);
|
||||||
|
|
||||||
|
int hour = (saveTime >> 8) & 0xFF;
|
||||||
|
int minutes = saveTime & 0xFF;
|
||||||
|
header.desc.setSaveTime(hour, minutes);
|
||||||
|
|
||||||
|
header.desc.setPlayTime(playTime * 1000);
|
||||||
|
g_engine->setTotalPlayTime(playTime * 1000);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char *getPictName(CloseDataPtr *LCPtr);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Writes the game out to disk. */
|
/* Writes the game out to disk. */
|
||||||
/* Assumes that the file has already been openned and is there. */
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
static bool saveGame(uint16 RoomNum, uint16 Direction, uint16 Quarters, LABFH file) {
|
bool saveGame(uint16 RoomNum, uint16 Direction, uint16 Quarters, int slot, Common::String desc) {
|
||||||
#if !defined(DOSCODE)
|
uint16 i, j;
|
||||||
uint16 temp;
|
Common::String fileName = g_lab->generateSaveFileName(slot);
|
||||||
CrumbData crumbs[sizeof(BreadCrumbs) / sizeof(CrumbData)];
|
Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
|
||||||
#endif
|
Common::OutSaveFile *file = saveFileManager->openForSaving(fileName);
|
||||||
uint16 last, counter, counter1;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
saveGameWriteBlock(file, (void *)SAVEVERSION, 4L);
|
if (!file)
|
||||||
#if defined(DOSCODE)
|
return false;
|
||||||
saveGameWriteBlock(file, &RoomNum, 2L);
|
|
||||||
saveGameWriteBlock(file, &Direction, 2L);
|
|
||||||
saveGameWriteBlock(file, &Quarters, 2L);
|
|
||||||
#else
|
|
||||||
temp = swapUShort(RoomNum);
|
|
||||||
saveGameWriteBlock(file, &temp, 2L);
|
|
||||||
temp = swapUShort(Direction);
|
|
||||||
saveGameWriteBlock(file, &temp, 2L);
|
|
||||||
temp = swapUShort(Quarters);
|
|
||||||
saveGameWriteBlock(file, &temp, 2L);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
last = g_lab->_conditions->_lastElement / 8;
|
// Load scene pic
|
||||||
saveGameWriteBlock(file, g_lab->_conditions->_array, (uint32) last);
|
CloseDataPtr CPtr = NULL;
|
||||||
|
readPict(getPictName(&CPtr), true);
|
||||||
|
|
||||||
last = g_lab->_roomsFound->_lastElement / 8;
|
writeSaveGameHeader(file, desc);
|
||||||
saveGameWriteBlock(file, g_lab->_roomsFound->_array, (uint32) last);
|
file->writeUint16LE(RoomNum);
|
||||||
|
file->writeUint16LE(Direction);
|
||||||
|
file->writeUint16LE(Quarters);
|
||||||
|
|
||||||
/* LAB: the combination lock and tile stuff */
|
// Conditions
|
||||||
for (counter = 0; counter < 6; counter++) {
|
for (i = 0; i < g_lab->_conditions->_lastElement / (8 * 2); i++)
|
||||||
c = (char)combination[counter];
|
file->writeUint16LE(g_lab->_conditions->_array[i]);
|
||||||
saveGameWriteBlock(file, &c, 1L);
|
|
||||||
|
// Rooms found
|
||||||
|
for (i = 0; i < g_lab->_roomsFound->_lastElement / (8 * 2); i++)
|
||||||
|
file->writeUint16LE(g_lab->_roomsFound->_array[i]);
|
||||||
|
|
||||||
|
// Combination lock and tile stuff
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
file->writeByte(combination[i]);
|
||||||
|
|
||||||
|
// Tiles
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
file->writeUint16LE(CurTile[i][j]);
|
||||||
|
|
||||||
|
// Breadcrumbs
|
||||||
|
for (i = 0; i < sizeof(BreadCrumbs); i++) {
|
||||||
|
file->writeUint16LE(BreadCrumbs[i].RoomNum);
|
||||||
|
file->writeUint16LE(BreadCrumbs[i].Direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (counter = 0; counter < 4; counter++)
|
file->flush();
|
||||||
for (counter1 = 0; counter1 < 4; counter1++)
|
file->finalize();
|
||||||
#if defined(DOSCODE)
|
delete file;
|
||||||
saveGameWriteBlock(file, &(CurTile[counter] [counter1]), 2L);
|
|
||||||
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
temp = swapUShort(CurTile[counter] [counter1]);
|
|
||||||
saveGameWriteBlock(file, &temp, 2L);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(DOSCODE)
|
|
||||||
saveGameWriteBlock(file, g_SaveGameImage, SAVED_IMAGE_SIZE);
|
|
||||||
memcpy(crumbs, BreadCrumbs, sizeof BreadCrumbs);
|
|
||||||
swapUShortPtr(&crumbs[0].RoomNum, sizeof(BreadCrumbs) / sizeof(uint16));
|
|
||||||
saveGameWriteBlock(file, crumbs, sizeof BreadCrumbs);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
saveGameClose(file, true);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -197,128 +185,58 @@ static bool saveGame(uint16 RoomNum, uint16 Direction, uint16 Quarters, LABFH fi
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Reads the game from disk. */
|
/* Reads the game from disk. */
|
||||||
/* Assumes that the file has already been openned and is there. */
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
static bool loadGame(uint16 *RoomNum, uint16 *Direction, uint16 *Quarters, LABFH file) {
|
bool loadGame(uint16 *RoomNum, uint16 *Direction, uint16 *Quarters, int slot) {
|
||||||
#if !defined(DOSCODE)
|
uint16 i, j;
|
||||||
uint16 t;
|
Common::String fileName = g_lab->generateSaveFileName(slot);
|
||||||
CrumbData crumbs[sizeof(BreadCrumbs) / sizeof(CrumbData)];
|
Common::SaveFileManager *saveFileManager = g_system->getSavefileManager();
|
||||||
#endif
|
Common::InSaveFile *file = saveFileManager->openForLoading(fileName);
|
||||||
char temp[5], c;
|
|
||||||
uint16 last, counter, counter1;
|
|
||||||
|
|
||||||
saveGameReadBlock(file, temp, 4L);
|
if (!file)
|
||||||
temp[4] = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (strcmp(temp, SAVEVERSION) != 0)
|
|
||||||
{
|
|
||||||
saveGameClose(file, false);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(DOSCODE)
|
SaveGameHeader header;
|
||||||
saveGameReadBlock(file, RoomNum, 2L);
|
readSaveGameHeader(file, header);
|
||||||
saveGameReadBlock(file, Direction, 2L);
|
*RoomNum = file->readUint16LE();
|
||||||
saveGameReadBlock(file, Quarters, 2L);
|
*Direction = file->readUint16LE();
|
||||||
#else
|
*Quarters = file->readUint16LE();
|
||||||
saveGameReadBlock(file, &t, 2L);
|
|
||||||
*RoomNum = swapUShort(t);
|
|
||||||
saveGameReadBlock(file, &t, 2L);
|
|
||||||
*Direction = swapUShort(t);
|
|
||||||
saveGameReadBlock(file, &t, 2L);
|
|
||||||
*Quarters = swapUShort(t);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
last = g_lab->_conditions->_lastElement / 8;
|
// Conditions
|
||||||
saveGameReadBlock(file, g_lab->_conditions->_array, (uint32) last);
|
for (i = 0; i < g_lab->_conditions->_lastElement / (8 * 2); i++)
|
||||||
|
g_lab->_conditions->_array[i] = file->readUint16LE();
|
||||||
|
|
||||||
last = g_lab->_roomsFound->_lastElement / 8;
|
// Rooms found
|
||||||
saveGameReadBlock(file, g_lab->_roomsFound->_array, (uint32) last);
|
for (i = 0; i < g_lab->_roomsFound->_lastElement / (8 * 2); i++)
|
||||||
|
g_lab->_roomsFound->_array[i] = file->readUint16LE();
|
||||||
|
|
||||||
/* LAB: the combination lock and tile stuff */
|
// Combination lock and tile stuff
|
||||||
for (counter = 0; counter < 6; counter++) {
|
for (i = 0; i < 6; i++)
|
||||||
saveGameReadBlock(file, &c, 1L);
|
combination[i] = file->readByte();
|
||||||
combination[counter] = c;
|
|
||||||
|
// Tiles
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
CurTile[i][j] = file->readUint16LE();
|
||||||
|
|
||||||
|
// Breadcrumbs
|
||||||
|
for (i = 0; i < sizeof(BreadCrumbs); i++) {
|
||||||
|
BreadCrumbs[i].RoomNum = file->readUint16LE();
|
||||||
|
BreadCrumbs[i].Direction = file->readUint16LE();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (counter = 0; counter < 4; counter++)
|
|
||||||
for (counter1 = 0; counter1 < 4; counter1++)
|
|
||||||
#if defined(DOSCODE)
|
|
||||||
saveGameReadBlock(file, &(CurTile[counter] [counter1]), 2L);
|
|
||||||
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
saveGameReadBlock(file, &t, 2L);
|
|
||||||
CurTile[counter] [counter1] = swapUShort(t);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (strcmp(temp, SAVEVERSION) == 0) {
|
|
||||||
saveGameReadBlock(file, g_SaveGameImage, SAVED_IMAGE_SIZE);
|
|
||||||
|
|
||||||
memset(crumbs, 0, sizeof BreadCrumbs);
|
|
||||||
saveGameReadBlock(file, crumbs, sizeof BreadCrumbs);
|
|
||||||
swapUShortPtr(&crumbs[0].RoomNum, sizeof(BreadCrumbs) / sizeof(uint16));
|
|
||||||
memcpy(BreadCrumbs, crumbs, sizeof BreadCrumbs);
|
|
||||||
DroppingCrumbs = (BreadCrumbs[0].RoomNum != 0);
|
DroppingCrumbs = (BreadCrumbs[0].RoomNum != 0);
|
||||||
FollowingCrumbs = false;
|
FollowingCrumbs = false;
|
||||||
|
|
||||||
for (counter = 0; counter < MAX_CRUMBS; counter++)
|
for (i = 0; i < sizeof(BreadCrumbs); i++) {
|
||||||
if (BreadCrumbs[counter].RoomNum == 0) break;
|
if (BreadCrumbs[i].RoomNum == 0)
|
||||||
|
break;
|
||||||
NumCrumbs = counter;
|
NumCrumbs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveGameClose(file, false);
|
delete file;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Saves the game to the floppy disk. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
bool saveFloppy(char *path, uint16 RoomNum, uint16 Direction, uint16 NumQuarters, uint16 filenum, uint16 type) {
|
|
||||||
LABFH FPtr;
|
|
||||||
|
|
||||||
g_music->checkMusic();
|
|
||||||
|
|
||||||
FileType = type;
|
|
||||||
FileNum = filenum;
|
|
||||||
|
|
||||||
if ((FPtr = saveGameOpen(path, true)) != INVALID_LABFH)
|
|
||||||
saveGame(RoomNum, Direction, NumQuarters, FPtr);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Reads the game from the floppy disk. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
bool readFloppy(char *path, uint16 *RoomNum, uint16 *Direction, uint16 *NumQuarters, uint16 filenum, uint16 type) {
|
|
||||||
LABFH FPtr;
|
|
||||||
|
|
||||||
g_music->checkMusic();
|
|
||||||
|
|
||||||
FileType = type;
|
|
||||||
FileNum = filenum;
|
|
||||||
|
|
||||||
if ((FPtr = saveGameOpen(path, false)) != INVALID_LABFH) {
|
|
||||||
if (!loadGame(RoomNum, Direction, NumQuarters, FPtr))
|
|
||||||
return false;
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End of namespace Lab
|
} // End of namespace Lab
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,6 +28,11 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "common/translation.h"
|
||||||
|
|
||||||
|
#include "gui/message.h"
|
||||||
|
#include "gui/saveload.h"
|
||||||
|
|
||||||
#include "lab/lab.h"
|
#include "lab/lab.h"
|
||||||
#include "lab/labfun.h"
|
#include "lab/labfun.h"
|
||||||
#include "lab/parsefun.h"
|
#include "lab/parsefun.h"
|
||||||
|
@ -40,12 +45,6 @@
|
||||||
#include "lab/stddefines.h"
|
#include "lab/stddefines.h"
|
||||||
#include "lab/parsetypes.h"
|
#include "lab/parsetypes.h"
|
||||||
|
|
||||||
#define MODERNGAMESAVE 1
|
|
||||||
|
|
||||||
#if defined(MODERNGAMESAVE)
|
|
||||||
#include "lab/modernsavegame.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Lab {
|
namespace Lab {
|
||||||
|
|
||||||
#ifdef GAME_TRIAL
|
#ifdef GAME_TRIAL
|
||||||
|
@ -109,7 +108,7 @@ static byte *loadBackPict(const char *fileName, bool tomem) {
|
||||||
static Image *Images[10];
|
static Image *Images[10];
|
||||||
|
|
||||||
|
|
||||||
uint16 combination[6] = {0, 0, 0, 0, 0, 0}, solution[] = {0, 4, 0, 8, 7, 2};
|
byte combination[6] = {0, 0, 0, 0, 0, 0}, solution[] = {0, 4, 0, 8, 7, 2};
|
||||||
|
|
||||||
static uint16 combx[] = {45, 83, 129, 166, 211, 248};
|
static uint16 combx[] = {45, 83, 129, 166, 211, 248};
|
||||||
|
|
||||||
|
@ -942,528 +941,57 @@ void doJournal() {
|
||||||
ungetVGABaseAddr();
|
ungetVGABaseAddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct SaveGameInfo {
|
||||||
|
unsigned short RoomNumber;
|
||||||
|
unsigned short Direction;
|
||||||
|
byte *SaveGameImage;
|
||||||
|
char SaveGameDate[128];
|
||||||
|
};
|
||||||
|
|
||||||
|
int getSaveGameList(SaveGameInfo *info, int maxNum);
|
||||||
|
*/
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
#define QUARTERNUM 30
|
||||||
/*------------------------- The Save/Restore stuff --------------------------*/
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
Image *Arrow1, *NoArrow1, *DriveButton;
|
|
||||||
|
|
||||||
|
|
||||||
extern InventoryData *Inventory;
|
extern InventoryData *Inventory;
|
||||||
extern uint16 RoomNum, Direction;
|
extern uint16 RoomNum, Direction;
|
||||||
|
|
||||||
extern char *SAVETEXT, *LOADTEXT, *BOOKMARKTEXT, *PERSONALTEXT, *DISKTEXT, *SAVEBOOK, *RESTOREBOOK, *SAVEFLASH, *RESTOREFLASH, *SAVEDISK, *RESTOREDISK, *SELECTDISK, *NODISKINDRIVE, *WRITEPROTECTED, *FORMATFLOPPY, *FORMATTING;
|
|
||||||
|
|
||||||
static uint16 device;
|
|
||||||
|
|
||||||
#define MAXDEVNAMES 5
|
|
||||||
|
|
||||||
static char DriveName[5] [MAXDEVNAMES];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*----- Gets the devices -----*/
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Finds all the disk drives, puts them in an array of strings, sorts them, */
|
|
||||||
/* and returned the number of drives that it found. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
uint16 doDisks(void) {
|
|
||||||
char str[5];
|
|
||||||
str[0] = 'C';
|
|
||||||
str[1] = ':';
|
|
||||||
str[2] = '\\';
|
|
||||||
str[3] = 0;
|
|
||||||
strcpy(DriveName[0], str);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Does the user interface to save or restore a game position */
|
|
||||||
/*****************************************************************************/
|
|
||||||
#if defined(MODERNGAMESAVE)
|
|
||||||
|
|
||||||
extern const byte ThePalMap[];
|
|
||||||
|
|
||||||
void getRoomMessage(int MyRoomNum, int MyDirection, char *msg);
|
|
||||||
|
|
||||||
#define QUARTERNUM 30
|
|
||||||
|
|
||||||
#define NEXTEMPTYSLOTTEXT "Next Empty Slot"
|
|
||||||
|
|
||||||
extern char g_SaveGamePath[512];
|
|
||||||
extern char g_PathSeperator[4];
|
|
||||||
|
|
||||||
SaveGameInfo g_SaveGameInfo[MAX_SAVED_GAMES];
|
|
||||||
int g_TotalSavedGames;
|
|
||||||
char g_CommonPalette[3 * 256];
|
|
||||||
int g_LastSaveGameNumber = 0;
|
|
||||||
int g_CurSaveGameNumber = 0;
|
|
||||||
int g_CurSaveSet = 0;
|
|
||||||
int g_PendingNewSave = 0;
|
|
||||||
|
|
||||||
enum UI_Ident {
|
|
||||||
ID_SAVE,
|
|
||||||
ID_LOAD,
|
|
||||||
ID_NEWSLOT,
|
|
||||||
ID_1_TO_5,
|
|
||||||
ID_6_TO_10,
|
|
||||||
ID_11_TO_15,
|
|
||||||
ID_SLOT_A,
|
|
||||||
ID_SLOT_B,
|
|
||||||
ID_SLOT_C,
|
|
||||||
ID_SLOT_D,
|
|
||||||
ID_SLOT_E,
|
|
||||||
ID_CANCEL,
|
|
||||||
ID_LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModernUI {
|
|
||||||
int id;
|
|
||||||
int x, y, w, h;
|
|
||||||
};
|
|
||||||
|
|
||||||
ModernUI theUI[ID_LAST] = {
|
|
||||||
{ ID_LOAD, 491, 182, 128, 54 },
|
|
||||||
{ ID_SAVE, 491, 255, 128, 54 },
|
|
||||||
{ ID_NEWSLOT, 491, 328, 128, 54 },
|
|
||||||
{ ID_1_TO_5, 27, 40, 146, 25 },
|
|
||||||
{ ID_6_TO_10, 175, 40, 146, 25 },
|
|
||||||
{ ID_11_TO_15, 323, 40, 146, 25 },
|
|
||||||
{ ID_SLOT_A, 27, 67, 442, 72 },
|
|
||||||
{ ID_SLOT_B, 27, 142, 442, 72 },
|
|
||||||
{ ID_SLOT_C, 27, 217, 442, 72 },
|
|
||||||
{ ID_SLOT_D, 27, 292, 442, 72 },
|
|
||||||
{ ID_SLOT_E, 27, 367, 442, 72 },
|
|
||||||
{ ID_CANCEL, 531, 405, 52, 52 }
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
SG_BLACK = 1,
|
|
||||||
SG_TAN = 14,
|
|
||||||
SG_DKTAN = 38,
|
|
||||||
SG_WHITE = 105,
|
|
||||||
SG_YELLOW = 118
|
|
||||||
};
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Draw display */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static void flowTextBold(void *font, /* the TextAttr pointer */
|
|
||||||
uint16 spacing, /* How much vertical spacing between the lines */
|
|
||||||
uint16 pencolor, /* pen number to use for text */
|
|
||||||
uint16 backpen, /* the background color */
|
|
||||||
bool outline, /* Whether to outline in background color */
|
|
||||||
bool centerh, /* Whether to center the text horizontally */
|
|
||||||
bool centerv, /* Whether to center the text vertically */
|
|
||||||
bool output, /* Whether to output any text */
|
|
||||||
uint16 x1, /* Cords */
|
|
||||||
uint16 y1, uint16 x2, uint16 y2, const char *text) { /* The text itself */
|
|
||||||
|
|
||||||
if (outline) {
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1 - 1, y1, x2 - 1, y2, text);
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1 - 1, y1 - 1, x2 - 1, y2 - 1, text);
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1, y1 + 2, x2, y2 + 2, text);
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1 - 1, y1 + 2, x2 - 1, y2 + 2, text);
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1 + 2, y1, x2 + 2, y2, text);
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1 + 2, y1 + 2, x2 + 2, y2 + 2, text);
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1, y1 - 1, x2, y2 - 1, text);
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1 + 2, y1 - 1, x2 + 2, y2 - 1, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
flowText(font, spacing, pencolor, 0, false, centerh, centerv, output, x1, y1, x2, y2, text);
|
|
||||||
flowText(font, spacing, pencolor, 0, false, centerh, centerv, output, x1 + 1, y1, x2 + 1, y2, text);
|
|
||||||
flowText(font, spacing, pencolor, 0, false, centerh, centerv, output, x1, y1 + 1, x2, y2 + 1, text);
|
|
||||||
flowText(font, spacing, pencolor, 0, false, centerh, centerv, output, x1 + 1, y1 + 1, x2 + 1, y2 + 1, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Draw display */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static void flowTextShadow(void *font, /* the TextAttr pointer */
|
|
||||||
uint16 spacing, /* How much vertical spacing between the lines */
|
|
||||||
uint16 pencolor, /* pen number to use for text */
|
|
||||||
uint16 backpen, /* the background color */
|
|
||||||
bool outline, /* Whether to outline in background color */
|
|
||||||
bool centerh, /* Whether to center the text horizontally */
|
|
||||||
bool centerv, /* Whether to center the text vertically */
|
|
||||||
bool output, /* Whether to output any text */
|
|
||||||
uint16 x1, /* Cords */
|
|
||||||
uint16 y1, uint16 x2, uint16 y2, char *text) { /* The text itself */
|
|
||||||
|
|
||||||
if (outline) {
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1 - 1, y1 - 1, x2 - 1, y2 - 1, text);
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1 - 1, y1 + 1, x2 - 1, y2 + 1, text);
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1 + 1, y1 + 1, x2 + 1, y2 + 1, text);
|
|
||||||
flowText(font, spacing, backpen, 0, false, centerh, centerv, output, x1 + 1, y1 - 1, x2 + 1, y2 - 1, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
flowText(font, spacing, pencolor, 0, false, centerh, centerv, output, x1, y1, x2, y2, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawSaveLoad() {
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
flowTextBold(MsgFont, 0, g_CurSaveGameNumber < g_TotalSavedGames ? SG_YELLOW : SG_DKTAN, SG_BLACK, true, true, true, true, 491 + 3, 182, 619 + 3, 236, LOADTEXT);
|
|
||||||
flowTextBold(MsgFont, 0, g_TotalSavedGames + g_PendingNewSave > 0 ? SG_YELLOW : SG_DKTAN, SG_BLACK, true, true, true, true, 491 + 3, 255, 619 + 3, 309, SAVETEXT);
|
|
||||||
flowTextBold(MsgFont, 0, g_PendingNewSave ? SG_DKTAN : SG_YELLOW, SG_BLACK, true, true, true, true, 491 + 3, 328, 619 + 3, 382, NEXTEMPTYSLOTTEXT);
|
|
||||||
|
|
||||||
flowTextBold(MsgFont, 0, (g_CurSaveSet == 0 ? SG_YELLOW : SG_WHITE), SG_BLACK, true, true, true, true, 27 + 3, 40, 175 + 3, 65, "Saves 1-5");
|
|
||||||
flowTextBold(MsgFont, 0, (g_CurSaveSet == 1 ? SG_YELLOW : SG_WHITE), SG_BLACK, true, true, true, true, 175 + 3, 40, 321 + 3, 65, "Saves 6-10");
|
|
||||||
flowTextBold(MsgFont, 0, (g_CurSaveSet == 2 ? SG_YELLOW : SG_WHITE), SG_BLACK, true, true, true, true, 323 + 3, 40, 469 + 3, 65, "Saves 11-15");
|
|
||||||
|
|
||||||
for (i = 0, j = 5 * g_CurSaveSet; i < 5; i++, j++) {
|
|
||||||
uint16 hue, y;
|
|
||||||
char num_text[4];
|
|
||||||
Image thumbnail, screen;
|
|
||||||
|
|
||||||
if (j < g_TotalSavedGames + g_PendingNewSave) {
|
|
||||||
char msg[256];
|
|
||||||
|
|
||||||
getRoomMessage(g_SaveGameInfo[j].RoomNumber, g_SaveGameInfo[j].Direction, msg);
|
|
||||||
|
|
||||||
hue = (j == g_CurSaveGameNumber ? SG_YELLOW : SG_WHITE);
|
|
||||||
y = 67 + 2 + i * 75;
|
|
||||||
flowText(MsgFont, 0, hue, 0, false, false, false, true, 202 + 2, y, 469 - 2, y + 48, msg);
|
|
||||||
y += 46;
|
|
||||||
flowText(MsgFont, 0, hue, 0, false, false, false, true, 202 + 2, y, 469 - 2, y + 24, g_SaveGameInfo[j].SaveGameDate);
|
|
||||||
|
|
||||||
// blast image
|
|
||||||
thumbnail.Width = 128;
|
|
||||||
thumbnail.Height = 72;
|
|
||||||
thumbnail.ImageData = g_SaveGameInfo[j].SaveGameImage;
|
|
||||||
screen.Width = VGAScreenWidth;
|
|
||||||
screen.Height = VGAScreenHeight;
|
|
||||||
screen.ImageData = getVGABaseAddr();
|
|
||||||
bltBitMap(&thumbnail, 0, 0, &screen, 72, 67 + i * 75, 128, 72);
|
|
||||||
ungetVGABaseAddr();
|
|
||||||
|
|
||||||
hue = (j == g_CurSaveGameNumber ? SG_YELLOW : SG_WHITE);
|
|
||||||
} else {
|
|
||||||
y = 67 + 2 + i * 75;
|
|
||||||
flowText(MsgFont, 0, SG_TAN, 0, false, true, true, true, 202 + 2, y, 469 - 2, y + 70, "[Empty Slot]");
|
|
||||||
|
|
||||||
hue = SG_DKTAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
y = 67 + i * 75;
|
|
||||||
sprintf(num_text, "%d", j + 1);
|
|
||||||
flowTextShadow(BigMsgFont, 0, hue, SG_BLACK, true, true, true, true, 27 + 4, y, 72 + 4, y + 72, num_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add ".1" to version number
|
|
||||||
setAPen(SG_WHITE);
|
|
||||||
rectFill(271, 454, 271, 454);
|
|
||||||
rectFill(275, 449, 275, 454);
|
|
||||||
rectFill(274, 450, 274, 450);
|
|
||||||
rectFill(274, 454, 276, 454);
|
|
||||||
|
|
||||||
WSDL_UpdateScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void makeThumbnail(SaveGameInfo *info) {
|
|
||||||
char *pictName;
|
|
||||||
CloseDataPtr CPtr = NULL;
|
|
||||||
byte *BitMapMem;
|
|
||||||
int x, y, u, v;
|
|
||||||
|
|
||||||
// load pict
|
|
||||||
pictName = getPictName(&CPtr);
|
|
||||||
nopalchange = true;
|
|
||||||
BitMapMem = readPictToMem(pictName, VGAScreenWidth, VGAScreenHeight);
|
|
||||||
nopalchange = false;
|
|
||||||
|
|
||||||
for (y = 0; y < 72; y++) {
|
|
||||||
for (x = 0; x < 128; x++) {
|
|
||||||
unsigned int r = 0, g = 0, b = 0;
|
|
||||||
|
|
||||||
for (v = 5 * y; v < 5 * y + 5; v++) {
|
|
||||||
for (u = 5 * x; u < 5 * x + 5; u++) {
|
|
||||||
byte n = (byte)BitMapMem[u + v * VGAScreenWidth];
|
|
||||||
// 6-bit color (VGA)
|
|
||||||
r += (unsigned int)diffcmap[3 * n + 0];
|
|
||||||
g += (unsigned int)diffcmap[3 * n + 1];
|
|
||||||
b += (unsigned int)diffcmap[3 * n + 2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = (r / 25) >> 1;
|
|
||||||
g = (g / 25) >> 1;
|
|
||||||
b = (b / 25) >> 1;
|
|
||||||
warning("STUB: makeThumbnail");
|
|
||||||
info->SaveGameImage[x + 128 * y] = ThePalMap[(r << 10) | (g << 5) | b];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addSaveSlot() {
|
|
||||||
SaveGameInfo *info;
|
|
||||||
|
|
||||||
if (g_PendingNewSave || g_TotalSavedGames == MAX_SAVED_GAMES)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_PendingNewSave = 1;
|
|
||||||
g_CurSaveGameNumber = g_TotalSavedGames;
|
|
||||||
g_CurSaveSet = g_CurSaveGameNumber / 5;
|
|
||||||
|
|
||||||
// set-up saved game
|
|
||||||
info = &g_SaveGameInfo[g_CurSaveGameNumber];
|
|
||||||
info->RoomNumber = RoomNum;
|
|
||||||
info->Direction = Direction;
|
|
||||||
|
|
||||||
// not really a date yet
|
|
||||||
strcpy(info->SaveGameDate, "Click SAVE GAME to Confirm");
|
|
||||||
|
|
||||||
info->SaveGameImage = (byte *)malloc(SAVED_IMAGE_SIZE);
|
|
||||||
makeThumbnail(info);
|
|
||||||
|
|
||||||
mouseHide();
|
|
||||||
WSDL_IgnoreUpdateDisplay(1);
|
|
||||||
loadBackPict("P:ModSave", false);
|
|
||||||
WSDL_IgnoreUpdateDisplay(0);
|
|
||||||
drawSaveLoad();
|
|
||||||
mouseShow();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void selectSave(int n) {
|
|
||||||
if (g_CurSaveGameNumber == n || n >= g_TotalSavedGames + g_PendingNewSave)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_CurSaveGameNumber = n;
|
|
||||||
|
|
||||||
mouseHide();
|
|
||||||
WSDL_IgnoreUpdateDisplay(1);
|
|
||||||
loadBackPict("P:ModSave", false);
|
|
||||||
WSDL_IgnoreUpdateDisplay(0);
|
|
||||||
drawSaveLoad();
|
|
||||||
mouseShow();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void selectSaveSet(int n) {
|
|
||||||
if (g_CurSaveSet != n) {
|
|
||||||
g_CurSaveSet = n;
|
|
||||||
|
|
||||||
mouseHide();
|
|
||||||
WSDL_IgnoreUpdateDisplay(1);
|
|
||||||
loadBackPict("P:ModSave", false);
|
|
||||||
WSDL_IgnoreUpdateDisplay(0);
|
|
||||||
drawSaveLoad();
|
|
||||||
mouseShow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Do modern save. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static bool doSaveGame() {
|
|
||||||
bool isok;
|
|
||||||
char DrivePath[260];
|
|
||||||
|
|
||||||
if (g_CurSaveGameNumber != g_TotalSavedGames) {
|
|
||||||
makeThumbnail(&g_SaveGameInfo[g_CurSaveGameNumber]);
|
|
||||||
} else {
|
|
||||||
// set time of save for new saved game
|
|
||||||
//struct tm *create_date;
|
|
||||||
//time_t ticks;
|
|
||||||
|
|
||||||
warning("STUB: doSaveGame");
|
|
||||||
//ticks = time(NULL);
|
|
||||||
//create_date = localtime(&ticks);
|
|
||||||
//strcpy(g_SaveGameInfo[g_CurSaveGameNumber].SaveGameDate, asctime(create_date));
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(g_SaveGameImage, g_SaveGameInfo[g_CurSaveGameNumber].SaveGameImage, SAVED_IMAGE_SIZE);
|
|
||||||
|
|
||||||
sprintf(DrivePath, "%s%s%d", g_SaveGamePath, g_PathSeperator, g_CurSaveGameNumber);
|
|
||||||
|
|
||||||
isok = saveFloppy(DrivePath, RoomNum, Direction, Inventory[QUARTERNUM].Many, g_CurSaveGameNumber, device);
|
|
||||||
g_music->resetMusic();
|
|
||||||
|
|
||||||
if (isok)
|
|
||||||
g_LastSaveGameNumber = g_CurSaveGameNumber;
|
|
||||||
|
|
||||||
return isok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Do modern load. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static bool doLoadGame() {
|
|
||||||
bool isok;
|
|
||||||
char drivePath[260];
|
|
||||||
|
|
||||||
snprintf(drivePath, 260, "%s%s%d", g_SaveGamePath, g_PathSeperator, g_CurSaveGameNumber);
|
|
||||||
|
|
||||||
isok = readFloppy(drivePath, &RoomNum, &Direction, &(Inventory[QUARTERNUM].Many), g_CurSaveGameNumber, device);
|
|
||||||
g_music->resetMusic();
|
|
||||||
|
|
||||||
if (isok)
|
|
||||||
g_LastSaveGameNumber = g_CurSaveGameNumber;
|
|
||||||
|
|
||||||
return isok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Processes user input. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static bool processSaveLoad() {
|
|
||||||
IntuiMessage *Msg;
|
|
||||||
|
|
||||||
uint32 Class;
|
|
||||||
uint16 Qualifier, MouseX, MouseY, Code;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
drawSaveLoad();
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
g_music->checkMusic(); /* Make sure we check the music at least after every message */
|
|
||||||
Msg = getMsg();
|
|
||||||
|
|
||||||
if (Msg == NULL) {
|
|
||||||
g_music->newCheckMusic();
|
|
||||||
} else {
|
|
||||||
Class = Msg->Class;
|
|
||||||
Qualifier = Msg->Qualifier;
|
|
||||||
MouseX = Msg->MouseX;
|
|
||||||
MouseY = Msg->MouseY;
|
|
||||||
Code = Msg->Code;
|
|
||||||
|
|
||||||
replyMsg(Msg);
|
|
||||||
|
|
||||||
if (((Class == MOUSEBUTTONS) && (IEQUALIFIER_RBUTTON & Qualifier)) ||
|
|
||||||
((Class == RAWKEY) && (Code == 27)))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (Class == RAWKEY) {
|
|
||||||
if (Code == 'l' || Code == 'L') {
|
|
||||||
if (g_CurSaveGameNumber < g_TotalSavedGames)
|
|
||||||
return doLoadGame();
|
|
||||||
} else if (Code == 's' || Code == 'S') {
|
|
||||||
if (g_TotalSavedGames + g_PendingNewSave > 0)
|
|
||||||
return doSaveGame();
|
|
||||||
} else if (Code == 'n' || Code == 'N') {
|
|
||||||
addSaveSlot();
|
|
||||||
} else if (Code == VKEY_LTARROW) {
|
|
||||||
i = g_CurSaveSet - 1;
|
|
||||||
|
|
||||||
if (i < 0) i = 2;
|
|
||||||
|
|
||||||
selectSaveSet(i);
|
|
||||||
} else if (Code == VKEY_RTARROW) {
|
|
||||||
i = g_CurSaveSet + 1;
|
|
||||||
|
|
||||||
if (i > 2) i = 0;
|
|
||||||
|
|
||||||
selectSaveSet(i);
|
|
||||||
} else if (Code == VKEY_UPARROW) {
|
|
||||||
if (g_TotalSavedGames + g_PendingNewSave > 0) {
|
|
||||||
i = g_CurSaveGameNumber - 1;
|
|
||||||
|
|
||||||
if (i < 0)
|
|
||||||
i = g_TotalSavedGames + g_PendingNewSave - 1;
|
|
||||||
|
|
||||||
if (i / 5 != g_CurSaveSet)
|
|
||||||
selectSaveSet(i / 5);
|
|
||||||
|
|
||||||
selectSave(i);
|
|
||||||
}
|
|
||||||
} else if (Code == VKEY_DNARROW) {
|
|
||||||
if (g_TotalSavedGames + g_PendingNewSave > 0) {
|
|
||||||
i = g_CurSaveGameNumber + 1;
|
|
||||||
|
|
||||||
if (i >= g_TotalSavedGames + g_PendingNewSave)
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
if (i / 5 != g_CurSaveSet)
|
|
||||||
selectSaveSet(i / 5);
|
|
||||||
|
|
||||||
selectSave(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((Class == MOUSEBUTTONS) && (IEQUALIFIER_LEFTBUTTON & Qualifier)) {
|
|
||||||
for (i = 0; i < ID_LAST; i++) {
|
|
||||||
if (MouseX >= theUI[i].x && MouseY >= theUI[i].y &&
|
|
||||||
MouseX < theUI[i].x + theUI[i].w && MouseY < theUI[i].y + theUI[i].h) {
|
|
||||||
switch (theUI[i].id) {
|
|
||||||
case ID_SAVE:
|
|
||||||
if (g_TotalSavedGames + g_PendingNewSave > 0)
|
|
||||||
return doSaveGame();
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ID_LOAD:
|
|
||||||
if (g_CurSaveGameNumber < g_TotalSavedGames)
|
|
||||||
return doLoadGame();
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ID_NEWSLOT:
|
|
||||||
addSaveSlot();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ID_1_TO_5:
|
|
||||||
case ID_6_TO_10:
|
|
||||||
case ID_11_TO_15:
|
|
||||||
selectSaveSet(theUI[i].id - ID_1_TO_5);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ID_SLOT_A:
|
|
||||||
case ID_SLOT_B:
|
|
||||||
case ID_SLOT_C:
|
|
||||||
case ID_SLOT_D:
|
|
||||||
case ID_SLOT_E:
|
|
||||||
selectSave(5 * g_CurSaveSet + theUI[i].id - ID_SLOT_A);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ID_CANCEL:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool saveRestoreGame(void) {
|
bool saveRestoreGame(void) {
|
||||||
byte **buffer;
|
bool isOK = false;
|
||||||
bool isok = true;
|
|
||||||
|
|
||||||
blackAllScreen();
|
// The original had one screen for saving/loading. We have two.
|
||||||
|
// Ask the user which screen to use.
|
||||||
|
GUI::MessageDialog saveOrLoad(_("Would you like to save or restore a game?"), _("Save"), _("Restore"));
|
||||||
|
|
||||||
BigMsgFont = &bmfont;
|
int choice = saveOrLoad.runModal();
|
||||||
|
if (choice == GUI::kMessageOK) {
|
||||||
|
// Save
|
||||||
|
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
|
||||||
|
int slot = dialog->runModalWithCurrentTarget();
|
||||||
|
if (slot >= 0) {
|
||||||
|
Common::String desc = dialog->getResultString();
|
||||||
|
|
||||||
if (!getFont("P:Map.fon", BigMsgFont)) {
|
if (desc.empty()) {
|
||||||
BigMsgFont = NULL;
|
// create our own description for the saved game, the user didn't enter it
|
||||||
return false;
|
desc = dialog->createDefaultSaveDescription(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = g_music->newOpen("P:ModSave");
|
isOK = saveGame(RoomNum, Direction, Inventory[QUARTERNUM].Many, slot, desc);
|
||||||
|
}
|
||||||
if (!buffer) {
|
} else {
|
||||||
freeAllStolenMem();
|
// Restore
|
||||||
return false;
|
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
|
||||||
|
int slot = dialog->runModalWithCurrentTarget();
|
||||||
|
if (slot >= 0)
|
||||||
|
isOK = loadGame(&RoomNum, &Direction, &(Inventory[QUARTERNUM].Many), slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_TotalSavedGames = getSaveGameList(g_SaveGameInfo, MAX_SAVED_GAMES);
|
if (!isOK)
|
||||||
g_CurSaveGameNumber = g_LastSaveGameNumber;
|
return false;
|
||||||
g_CurSaveSet = g_CurSaveGameNumber / 5;
|
|
||||||
g_PendingNewSave = 0;
|
|
||||||
|
|
||||||
loadBackPict("P:ModSave", false);
|
g_music->resetMusic();
|
||||||
|
|
||||||
mouseShow();
|
|
||||||
|
|
||||||
VGASetPal(diffcmap, 256);
|
|
||||||
memcpy(g_CommonPalette, diffcmap, 3 * 256);
|
|
||||||
|
|
||||||
isok = processSaveLoad();
|
|
||||||
eatMessages();
|
eatMessages();
|
||||||
|
|
||||||
mouseHide();
|
mouseHide();
|
||||||
|
@ -1478,372 +1006,8 @@ bool saveRestoreGame(void) {
|
||||||
|
|
||||||
freeAllStolenMem();
|
freeAllStolenMem();
|
||||||
|
|
||||||
freeSaveGameList(g_SaveGameInfo, g_TotalSavedGames);
|
|
||||||
|
|
||||||
return isok;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
static uint16 manydisks = 0;
|
|
||||||
|
|
||||||
static uint16 issave, ghoast, arrow, ManyDrives, DriveInitX, DriveNum = -1, FileNum = -1;
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Draws the number arrows. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static void doNumArrows(void) {
|
|
||||||
uint16 counterx, countery, curnum, cordx[3], cordy[3];
|
|
||||||
|
|
||||||
cordx[0] = VGAScaleX(53) + SVGACord(3);
|
|
||||||
cordx[1] = VGAScaleX(126) + SVGACord(1);
|
|
||||||
cordx[2] = VGAScaleX(197) + SVGACord(3);
|
|
||||||
|
|
||||||
cordy[0] = VGAScaleY(58) + SVGACord(2);
|
|
||||||
cordy[1] = VGAScaleY(86) + SVGACord(3);
|
|
||||||
cordy[2] = VGAScaleY(114) + SVGACord(3);
|
|
||||||
|
|
||||||
mouseHide();
|
|
||||||
|
|
||||||
for (countery = 0; countery < 3; countery++) {
|
|
||||||
for (counterx = 0; counterx < 3; counterx++) {
|
|
||||||
curnum = countery + counterx * 3;
|
|
||||||
|
|
||||||
if INBIT(arrow, curnum)
|
|
||||||
drawImage(Arrow1, cordx[counterx], cordy[countery]);
|
|
||||||
else
|
|
||||||
drawImage(NoArrow1, cordx[counterx], (int32) cordy[countery]);
|
|
||||||
|
|
||||||
if INBIT(ghoast, curnum)
|
|
||||||
ghoastRect(0, cordx[counterx], cordy[countery], cordx[counterx] + VGAScaleX(69), cordy[countery] + NoArrow1->Height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseShow();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Does the drive buttons for the final save/restore screen. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static void doDriveButtons(void) {
|
|
||||||
uint16 curx, counter;
|
|
||||||
|
|
||||||
if (ManyDrives > 5)
|
|
||||||
ManyDrives = 5;
|
|
||||||
|
|
||||||
DriveInitX = (VGAScreenWidth / 2) - ((ManyDrives * DriveButton->Width) / 2);
|
|
||||||
curx = DriveInitX;
|
|
||||||
|
|
||||||
mouseHide();
|
|
||||||
|
|
||||||
for (counter = 0; counter < ManyDrives; counter++) {
|
|
||||||
drawImage(DriveButton, curx, VGAScaleY(153));
|
|
||||||
|
|
||||||
flowText(BigMsgFont, 0, 1, 0, false, true, true, true, curx + VGAScaleX(5), VGAScaleY(158), curx + DriveButton->Width - VGAScaleX(5), VGAScaleY(148) + DriveButton->Height, DriveName[counter]);
|
|
||||||
|
|
||||||
curx += DriveButton->Width;
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseShow();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void drawSRMessage(char *rtext) {
|
|
||||||
mouseHide();
|
|
||||||
flowText(BigMsgFont, 0, 1, 10, true, true, true, true, VGAScaleX(22), VGAScaleY(21), VGAScaleX(289), VGAScaleY(48), rtext);
|
|
||||||
mouseShow();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Draws the correct message to the message box. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static void doSaveRestoreText(void) {
|
|
||||||
char *rtext, text[100];
|
|
||||||
|
|
||||||
if (DriveNum >= ManyDrives) {
|
|
||||||
rtext = SELECTDISK;
|
|
||||||
} else if (issave) {
|
|
||||||
strcpy(text, SAVEDISK);
|
|
||||||
strcat(text, " ");
|
|
||||||
strcat(text, DriveName[DriveNum]);
|
|
||||||
rtext = text;
|
|
||||||
} else {
|
|
||||||
strcpy(text, RESTOREDISK);
|
|
||||||
strcat(text, " ");
|
|
||||||
strcat(text, DriveName[DriveNum]);
|
|
||||||
rtext = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
drawSRMessage(rtext);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16 processSaveRestore(uint16 type);
|
|
||||||
|
|
||||||
static char DrivePath[50];
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Checks for the existence of previous saved game positions on disk. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static void floppyCheckFiles(void) {
|
|
||||||
char temp[7], *name, len;
|
|
||||||
int fl;
|
|
||||||
uint16 counter;
|
|
||||||
|
|
||||||
doSaveRestoreText();
|
|
||||||
|
|
||||||
arrow = 0;
|
|
||||||
ghoast = 0;
|
|
||||||
|
|
||||||
strcpy(DrivePath, DriveName[DriveNum]);
|
|
||||||
strcat(DrivePath, "LabSaves");
|
|
||||||
|
|
||||||
warning("STUB: floppyCheckFiles");
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#if defined(WIN32)
|
|
||||||
mkdir(DrivePath);
|
|
||||||
#else
|
|
||||||
mkdir(DrivePath, 0x644);
|
|
||||||
#endif
|
|
||||||
strcat(DrivePath, "\\");
|
|
||||||
|
|
||||||
len = strlen(DrivePath);
|
|
||||||
|
|
||||||
for (counter = 0; counter < 9; counter++) {
|
|
||||||
name = numtostr(temp, counter);
|
|
||||||
strcat(DrivePath, name);
|
|
||||||
|
|
||||||
if ((fl = open(DrivePath, O_RDONLY)) != -1) {
|
|
||||||
close(fl);
|
|
||||||
SETBIT(arrow, counter);
|
|
||||||
} else
|
|
||||||
SETBIT(ghoast, counter);
|
|
||||||
|
|
||||||
DrivePath[len] = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Checks for the existence of previously saved game positions. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static void checkFiles(void) {
|
|
||||||
ghoast = -1;
|
|
||||||
arrow = 0;
|
|
||||||
|
|
||||||
g_music->fillUpMusic(true);
|
|
||||||
|
|
||||||
/* NYI: check for empty drive */
|
|
||||||
floppyCheckFiles();
|
|
||||||
|
|
||||||
if (issave)
|
|
||||||
ghoast = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Processes user input. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static uint16 processSaveRestore(uint16 type) {
|
|
||||||
IntuiMessage *Msg;
|
|
||||||
|
|
||||||
uint32 Class;
|
|
||||||
uint16 Qualifier, MouseX, MouseY, Code, Temp;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
g_music->checkMusic(); /* Make sure we check the music at least after every message */
|
|
||||||
Msg = getMsg();
|
|
||||||
|
|
||||||
if (Msg == NULL) {
|
|
||||||
g_music->newCheckMusic();
|
|
||||||
} else {
|
|
||||||
Class = Msg->Class;
|
|
||||||
Qualifier = Msg->Qualifier;
|
|
||||||
MouseX = Msg->MouseX;
|
|
||||||
MouseY = Msg->MouseY;
|
|
||||||
Code = Msg->Code;
|
|
||||||
|
|
||||||
replyMsg(Msg);
|
|
||||||
|
|
||||||
if (((Class == MOUSEBUTTONS) && (IEQUALIFIER_RBUTTON & Qualifier)) ||
|
|
||||||
((Class == RAWKEY) && (Code == 27)))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
else if ((Class == MOUSEBUTTONS) && (IEQUALIFIER_LEFTBUTTON & Qualifier)) {
|
|
||||||
if (type == 0) { /* The save or restore screen */
|
|
||||||
if ((MouseX >= VGAScaleX(64)) && (MouseX <= VGAScaleX(257))) {
|
|
||||||
if ((MouseY >= VGAScaleY(57)) && (MouseY <= VGAScaleY(92)))
|
|
||||||
return true;
|
return true;
|
||||||
else if ((MouseY >= VGAScaleY(108)) && (MouseY <= VGAScaleY(142)))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
else if (type == 2) { /* The files screen */
|
|
||||||
if ((MouseY >= VGAScaleY(153)) && (MouseY <= VGAScaleY(180))) { /* the drive buttons */
|
|
||||||
Temp = ((MouseX - DriveInitX) / DriveButton->Width);
|
|
||||||
|
|
||||||
if (Temp < ManyDrives) {
|
|
||||||
DriveNum = Temp;
|
|
||||||
|
|
||||||
fade(false, 0);
|
|
||||||
checkFiles();
|
|
||||||
|
|
||||||
loadBackPict("P:Disk/Nums.pic", false);
|
|
||||||
doNumArrows();
|
|
||||||
doDriveButtons();
|
|
||||||
doSaveRestoreText();
|
|
||||||
|
|
||||||
fade(true, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ((MouseX >= VGAScaleX(53)) && (MouseY >= VGAScaleY(58)) &&
|
|
||||||
(MouseX <= VGAScaleX(266)) && (MouseY <= VGAScaleY(142))) {
|
|
||||||
MouseX = (MouseX - VGAScaleX(53)) / VGAScaleX(71);
|
|
||||||
MouseY = (MouseY - VGAScaleY(58)) / VGAScaleY(28);
|
|
||||||
|
|
||||||
Temp = MouseY + (MouseX * 3);
|
|
||||||
|
|
||||||
if (!(INBIT(ghoast, Temp))) {
|
|
||||||
|
|
||||||
SETBIT(arrow, Temp);
|
|
||||||
doNumArrows();
|
|
||||||
|
|
||||||
FileNum = Temp;
|
|
||||||
return FileNum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Sets up the Save or Restore screen. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static uint16 saveOrRestore(void) {
|
|
||||||
uint16 res;
|
|
||||||
|
|
||||||
mouseHide();
|
|
||||||
loadBackPict("P:Disk/Choose.pic", false);
|
|
||||||
|
|
||||||
flowText(BigMsgFont, 0, 1, 4, false, true, true, true, VGAScaleX(74), VGAScaleY(65), VGAScaleX(247), VGAScaleY(84), SAVETEXT);
|
|
||||||
flowText(BigMsgFont, 0, 1, 4, false, true, true, true, VGAScaleX(74), VGAScaleY(116), VGAScaleX(247), VGAScaleY(135), LOADTEXT);
|
|
||||||
mouseShow();
|
|
||||||
|
|
||||||
fade(true, 0);
|
|
||||||
res = processSaveRestore(0);
|
|
||||||
fade(false, 0);
|
|
||||||
eatMessages();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Sets up the final save/restore screen. */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static uint16 saveRestore(void) {
|
|
||||||
uint16 res;
|
|
||||||
|
|
||||||
loadBackPict("P:Disk/Nums.pic", false);
|
|
||||||
|
|
||||||
if ((DriveNum < ManyDrives)) {
|
|
||||||
checkFiles();
|
|
||||||
} else {
|
|
||||||
ghoast = -1;
|
|
||||||
arrow = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
doNumArrows();
|
|
||||||
doDriveButtons();
|
|
||||||
doSaveRestoreText();
|
|
||||||
g_music->newCheckMusic();
|
|
||||||
|
|
||||||
eatMessages();
|
|
||||||
fade(true, 0);
|
|
||||||
res = processSaveRestore(2);
|
|
||||||
fade(false, 0);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define QUARTERNUM 30
|
|
||||||
|
|
||||||
|
|
||||||
bool saveRestoreGame(void) {
|
|
||||||
uint16 filenum;
|
|
||||||
byte **buffer;
|
|
||||||
char temp[10], *name;
|
|
||||||
bool isok = true;
|
|
||||||
|
|
||||||
blackAllScreen();
|
|
||||||
|
|
||||||
ManyDrives = doDisks();
|
|
||||||
|
|
||||||
FadePalette = hipal;
|
|
||||||
memset(&(hipal[0]), 0, 32L);
|
|
||||||
|
|
||||||
BigMsgFont = &bmfont;
|
|
||||||
|
|
||||||
if (!getFont("P:Map.fon", BigMsgFont)) {
|
|
||||||
BigMsgFont = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = g_music->newOpen("P:SaveImage");
|
|
||||||
|
|
||||||
if (!buffer) {
|
|
||||||
freeAllStolenMem();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
readImage(buffer, &Arrow1);
|
|
||||||
readImage(buffer, &NoArrow1);
|
|
||||||
readImage(buffer, &DriveButton);
|
|
||||||
|
|
||||||
mouseShow();
|
|
||||||
|
|
||||||
if ((issave = saveOrRestore()) != (uint16) - 1) {
|
|
||||||
eatMessages();
|
|
||||||
|
|
||||||
if ((filenum = saveRestore()) != (uint16) - 1) {
|
|
||||||
name = numtostr(temp, filenum);
|
|
||||||
strcat(DrivePath, name);
|
|
||||||
|
|
||||||
eatMessages();
|
|
||||||
|
|
||||||
if (issave)
|
|
||||||
isok = saveFloppy(DrivePath, RoomNum, Direction, Inventory[QUARTERNUM].Many, filenum, device);
|
|
||||||
else {
|
|
||||||
isok = readFloppy(DrivePath, &RoomNum, &Direction, &(Inventory[QUARTERNUM].Many), filenum, device);
|
|
||||||
g_music->resetMusic();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseHide();
|
|
||||||
setAPen(0);
|
|
||||||
rectFill(0, 0, VGAScreenWidth - 1, VGAScreenHeight - 1);
|
|
||||||
blackScreen();
|
|
||||||
|
|
||||||
journalCleanUp();
|
|
||||||
|
|
||||||
freeAllStolenMem();
|
|
||||||
|
|
||||||
return isok;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/*--------------------------- The Monitors stuff ----------------------------*/
|
/*--------------------------- The Monitors stuff ----------------------------*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue