mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-16 06:39:17 +00:00
e27b05ef35
This is a first step towards getting rid of all uses of regular printf, fprintf, vprintf, vfprintf, puts, fputs, etc. in our codebase. The name format() reflects the purpose of the function, and parallels String.format() in Java, boost::format, and others. svn-id: r54004
1694 lines
38 KiB
C++
1694 lines
38 KiB
C++
/* 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.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "common/file.h"
|
|
#include "common/savefile.h"
|
|
#include "common/system.h"
|
|
#include "common/translation.h"
|
|
|
|
#include "gui/about.h"
|
|
#include "gui/message.h"
|
|
|
|
#include "agos/agos.h"
|
|
#include "agos/intern.h"
|
|
|
|
namespace AGOS {
|
|
|
|
int AGOSEngine::countSaveGames() {
|
|
Common::InSaveFile *f;
|
|
Common::StringArray filenames;
|
|
uint i = 1;
|
|
char slot[4];
|
|
int slotNum;
|
|
bool marks[256];
|
|
|
|
char *prefix = genSaveName(998);
|
|
prefix[strlen(prefix)-3] = '*';
|
|
prefix[strlen(prefix)-2] = '\0';
|
|
memset(marks, false, 256 * sizeof(bool)); //assume no savegames for this title
|
|
filenames = _saveFileMan->listSavefiles(prefix);
|
|
|
|
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
|
|
slot[0] = file->c_str()[file->size()-3];
|
|
slot[1] = file->c_str()[file->size()-2];
|
|
slot[2] = file->c_str()[file->size()-1];
|
|
slot[3] = '\0';
|
|
|
|
slotNum = atoi(slot);
|
|
if (slotNum >= 0 && slotNum < 256)
|
|
marks[slotNum] = true; //mark this slot as valid
|
|
}
|
|
|
|
while (i < 256) {
|
|
if (marks[i] &&
|
|
(f = _saveFileMan->openForLoading(genSaveName(i)))) {
|
|
i++;
|
|
delete f;
|
|
} else
|
|
break;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
#ifdef ENABLE_AGOS2
|
|
char *AGOSEngine_PuzzlePack::genSaveName(int slot) {
|
|
static char buf[20];
|
|
|
|
if (getGameId() == GID_DIMP)
|
|
sprintf(buf, "dimp.sav");
|
|
else
|
|
sprintf(buf, "swampy.sav");
|
|
|
|
return buf;
|
|
}
|
|
|
|
char *AGOSEngine_Feeble::genSaveName(int slot) {
|
|
static char buf[20];
|
|
sprintf(buf, "feeble.%.3d", slot);
|
|
return buf;
|
|
}
|
|
#endif
|
|
|
|
char *AGOSEngine_Simon2::genSaveName(int slot) {
|
|
static char buf[20];
|
|
sprintf(buf, "simon2.%.3d", slot);
|
|
return buf;
|
|
}
|
|
|
|
char *AGOSEngine_Simon1::genSaveName(int slot) {
|
|
static char buf[20];
|
|
sprintf(buf, "simon1.%.3d", slot);
|
|
return buf;
|
|
}
|
|
|
|
char *AGOSEngine_Waxworks::genSaveName(int slot) {
|
|
static char buf[20];
|
|
|
|
if (getPlatform() == Common::kPlatformPC)
|
|
sprintf(buf, "waxworks-pc.%.3d", slot);
|
|
else
|
|
sprintf(buf, "waxworks.%.3d", slot);
|
|
|
|
return buf;
|
|
}
|
|
|
|
char *AGOSEngine_Elvira2::genSaveName(int slot) {
|
|
static char buf[20];
|
|
|
|
if (getPlatform() == Common::kPlatformPC)
|
|
sprintf(buf, "elvira2-pc.%.3d", slot);
|
|
else
|
|
sprintf(buf, "elvira2.%.3d", slot);
|
|
|
|
return buf;
|
|
}
|
|
|
|
char *AGOSEngine_Elvira1::genSaveName(int slot) {
|
|
static char buf[20];
|
|
sprintf(buf, "elvira1.%.3d", slot);
|
|
return buf;
|
|
}
|
|
|
|
char *AGOSEngine::genSaveName(int slot) {
|
|
static char buf[20];
|
|
sprintf(buf, "pn.%.3d", slot);
|
|
return buf;
|
|
}
|
|
|
|
void AGOSEngine::quickLoadOrSave() {
|
|
// Quick load & save is only supported complete version of Simon the Sorcerer 1/2
|
|
if (getGameType() == GType_PP || getGameType() == GType_FF ||
|
|
(getFeatures() & GF_DEMO)) {
|
|
return;
|
|
}
|
|
|
|
bool success;
|
|
Common::String buf;
|
|
|
|
char *filename = genSaveName(_saveLoadSlot);
|
|
if (_saveLoadType == 2) {
|
|
Subroutine *sub;
|
|
success = loadGame(genSaveName(_saveLoadSlot));
|
|
if (!success) {
|
|
buf = Common::String::format(_("Failed to load game state from file:\n\n%s"), filename);
|
|
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
|
|
drawIconArray(2, me(), 0, 0);
|
|
setBitFlag(97, true);
|
|
sub = getSubroutineByID(100);
|
|
startSubroutine(sub);
|
|
} else if (getGameType() == GType_WW) {
|
|
sub = getSubroutineByID(66);
|
|
startSubroutine(sub);
|
|
} else if (getGameType() == GType_ELVIRA2) {
|
|
sub = getSubroutineByID(87);
|
|
startSubroutine(sub);
|
|
setBitFlag(7, false);
|
|
sub = getSubroutineByID(19);
|
|
startSubroutine(sub);
|
|
printStats();
|
|
sub = getSubroutineByID(28);
|
|
startSubroutine(sub);
|
|
setBitFlag(17, false);
|
|
sub = getSubroutineByID(207);
|
|
startSubroutine(sub);
|
|
sub = getSubroutineByID(71);
|
|
startSubroutine(sub);
|
|
} else if (getGameType() == GType_ELVIRA1) {
|
|
drawIconArray(2, me(), 0, 0);
|
|
sub = getSubroutineByID(265);
|
|
startSubroutine(sub);
|
|
sub = getSubroutineByID(129);
|
|
startSubroutine(sub);
|
|
sub = getSubroutineByID(131);
|
|
startSubroutine(sub);
|
|
}
|
|
} else {
|
|
success = saveGame(_saveLoadSlot, _saveLoadName);
|
|
if (!success)
|
|
buf = Common::String::format(_("Failed to save game state to file:\n\n%s"), filename);
|
|
}
|
|
|
|
if (!success) {
|
|
GUI::MessageDialog dialog(buf, "OK");
|
|
dialog.runModal();
|
|
|
|
} else if (_saveLoadType == 1) {
|
|
buf = Common::String::format(_("Successfully saved game state in file:\n\n%s"), filename);
|
|
GUI::TimedMessageDialog dialog(buf, 1500);
|
|
dialog.runModal();
|
|
|
|
}
|
|
|
|
_saveLoadType = 0;
|
|
}
|
|
|
|
bool AGOSEngine_Waxworks::confirmOverWrite(WindowBlock *window) {
|
|
Subroutine *sub = getSubroutineByID(80);
|
|
if (sub != NULL)
|
|
startSubroutineEx(sub);
|
|
|
|
if (_variableArray[253] == 0)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AGOSEngine_Elvira2::confirmOverWrite(WindowBlock *window) {
|
|
// Original verison never confirmed
|
|
return true;
|
|
}
|
|
|
|
bool AGOSEngine::confirmOverWrite(WindowBlock *window) {
|
|
const char *message1, *message2, *message3;
|
|
|
|
switch (_language) {
|
|
case Common::FR_FRA:
|
|
message1 = "\rFichier d/j; existant.\r\r";
|
|
message2 = " Ecrire pardessus ?\r\r";
|
|
message3 = " Oui Non";
|
|
break;
|
|
case Common::DE_DEU:
|
|
message1 = "\rDatei existiert bereits.\r\r";
|
|
message2 = " Ueberschreiben ?\r\r";
|
|
message3 = " Ja Nein";
|
|
break;
|
|
default:
|
|
message1 = "\r File already exists.\r\r";
|
|
message2 = " Overwrite it ?\r\r";
|
|
message3 = " Yes No";
|
|
break;
|
|
}
|
|
|
|
printScroll();
|
|
window->textColumn = 0;
|
|
window->textRow = 0;
|
|
window->textColumnOffset = 0;
|
|
window->textLength = 0; // Difference
|
|
|
|
for (; *message1; message1++)
|
|
windowPutChar(window, *message1);
|
|
for (; *message2; message2++)
|
|
windowPutChar(window, *message2);
|
|
for (; *message3; message3++)
|
|
windowPutChar(window, *message3);
|
|
|
|
if (confirmYesOrNo(120, 78) == 0x7FFF)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
int16 AGOSEngine::matchSaveGame(const char *name, uint16 max) {
|
|
Common::InSaveFile *in;
|
|
char dst[10];
|
|
uint16 slot;
|
|
|
|
memset(dst, 0, sizeof(dst));
|
|
for (slot = 0; slot < max; slot++) {
|
|
if ((in = _saveFileMan->openForLoading(genSaveName(slot)))) {
|
|
in->read(dst, 8);
|
|
delete in;
|
|
|
|
if (!scumm_stricmp(name, dst)) {
|
|
return slot;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void AGOSEngine::userGame(bool load) {
|
|
WindowBlock *window = _windowArray[4];
|
|
const char *message1;
|
|
int i = 0, numSaveGames;
|
|
char *name;
|
|
char buf[10];
|
|
|
|
numSaveGames = countSaveGames();
|
|
|
|
uint32 saveTime = getTime();
|
|
haltAnimation();
|
|
|
|
restart:
|
|
printScroll();
|
|
window->textColumn = 0;
|
|
window->textRow = 0;
|
|
window->textColumnOffset = 0;
|
|
window->textLength = 0; // Difference
|
|
|
|
switch (_language) {
|
|
case Common::FR_FRA:
|
|
message1 = "\rIns/rez disquette de\rsauvegarde de jeux &\rentrez nom de fichier:\r\r ";
|
|
break;
|
|
case Common::DE_DEU:
|
|
message1 = "\rLege Spielstandsdiskette ein. Dateinamen eingeben:\r\r ";
|
|
break;
|
|
default:
|
|
message1 = "\r Insert savegame data disk & enter filename:\r\r ";
|
|
break;
|
|
}
|
|
|
|
for (; *message1; message1++)
|
|
windowPutChar(window, *message1);
|
|
|
|
memset(buf, 0, 10);
|
|
name = buf;
|
|
_saveGameNameLen = 0;
|
|
|
|
while (!shouldQuit()) {
|
|
windowPutChar(window, 128);
|
|
_keyPressed.reset();
|
|
|
|
while (!shouldQuit()) {
|
|
delay(10);
|
|
if (_keyPressed.ascii && _keyPressed.ascii < 128) {
|
|
i = _keyPressed.ascii;
|
|
break;
|
|
}
|
|
}
|
|
|
|
userGameBackSpace(_windowArray[4], 8);
|
|
if (i == 10 || i == 13) {
|
|
break;
|
|
} else if (i == 8) {
|
|
// do_backspace
|
|
if (_saveGameNameLen) {
|
|
_saveGameNameLen--;
|
|
name[_saveGameNameLen] = 0;
|
|
userGameBackSpace(_windowArray[4], 8);
|
|
}
|
|
} else if (i >= 32 && _saveGameNameLen != 8) {
|
|
name[_saveGameNameLen++] = i;
|
|
windowPutChar(_windowArray[4], i);
|
|
}
|
|
}
|
|
|
|
if (_saveGameNameLen != 0) {
|
|
int16 slot = matchSaveGame(name, numSaveGames);
|
|
if (!load) {
|
|
if (slot >= 0 && !confirmOverWrite(window))
|
|
goto restart;
|
|
|
|
if (slot < 0)
|
|
slot = numSaveGames;
|
|
|
|
if (!saveGame(slot, name))
|
|
fileError(_windowArray[4], true);
|
|
} else {
|
|
if (slot < 0) {
|
|
fileError(_windowArray[4], false);
|
|
} else {
|
|
if (!loadGame(genSaveName(slot)))
|
|
fileError(_windowArray[4], false);
|
|
}
|
|
}
|
|
|
|
printStats();
|
|
}
|
|
|
|
restartAnimation();
|
|
_gameStoppedClock = getTime() - saveTime + _gameStoppedClock;
|
|
}
|
|
|
|
void AGOSEngine_Elvira2::listSaveGames(char *dst) {
|
|
Common::InSaveFile *in;
|
|
uint y, slot;
|
|
|
|
const uint8 num = (getGameType() == GType_WW) ? 3 : 4;
|
|
|
|
disableFileBoxes();
|
|
|
|
WindowBlock *window = _windowArray[num];
|
|
window->textRow = 0;
|
|
window->textColumn = 0;
|
|
window->textColumnOffset = 4;
|
|
|
|
windowPutChar(window, 12);
|
|
|
|
memset(dst, 0, 200);
|
|
|
|
slot = _saveLoadRowCurPos;
|
|
for (y = 0; y < 8; y++) {
|
|
window->textColumn = 0;
|
|
window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0;
|
|
window->textLength = 0;
|
|
if ((in = _saveFileMan->openForLoading(genSaveName(slot++)))) {
|
|
in->read(dst, 8);
|
|
delete in;
|
|
|
|
const char *name = dst;
|
|
for (; *name; name++)
|
|
windowPutChar(window, *name);
|
|
|
|
enableBox(200 + y * 3 + 0);
|
|
}
|
|
dst+= 8;
|
|
|
|
if (getGameType() == GType_WW) {
|
|
window->textColumn = 7;
|
|
window->textColumnOffset = 4;
|
|
} else if (getGameType() == GType_ELVIRA2) {
|
|
window->textColumn = 8;
|
|
window->textColumnOffset = 0;
|
|
}
|
|
window->textLength = 0;
|
|
if ((in = _saveFileMan->openForLoading(genSaveName(slot++)))) {
|
|
in->read(dst, 8);
|
|
delete in;
|
|
|
|
const char *name = dst;
|
|
for (; *name; name++)
|
|
windowPutChar(window, *name);
|
|
|
|
enableBox(200 + y * 3 + 1);
|
|
}
|
|
dst+= 8;
|
|
|
|
window->textColumn = 15;
|
|
window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0;
|
|
window->textLength = 0;
|
|
if ((in = _saveFileMan->openForLoading(genSaveName(slot++)))) {
|
|
in->read(dst, 8);
|
|
delete in;
|
|
|
|
const char *name = dst;
|
|
for (; *name; name++)
|
|
windowPutChar(window, *name);
|
|
|
|
enableBox(200 + y * 3 + 2);
|
|
}
|
|
dst+= 8;
|
|
|
|
windowPutChar(window, 13);
|
|
}
|
|
|
|
window->textRow = 9;
|
|
window->textColumn = 0;
|
|
window->textColumnOffset = 4;
|
|
window->textLength = 0;
|
|
|
|
_saveGameNameLen = 0;
|
|
}
|
|
|
|
void AGOSEngine_Elvira2::userGame(bool load) {
|
|
uint32 saveTime;
|
|
int i, numSaveGames;
|
|
char *name;
|
|
bool b;
|
|
char buf[200];
|
|
|
|
_saveOrLoad = load;
|
|
|
|
saveTime = getTime();
|
|
|
|
if (getGameType() == GType_ELVIRA2)
|
|
haltAnimation();
|
|
|
|
numSaveGames = countSaveGames();
|
|
_numSaveGameRows = numSaveGames;
|
|
_saveLoadRowCurPos = 1;
|
|
_saveLoadEdit = false;
|
|
|
|
const uint8 num = (getGameType() == GType_WW) ? 3 : 4;
|
|
|
|
listSaveGames(buf);
|
|
|
|
if (!load) {
|
|
WindowBlock *window = _windowArray[num];
|
|
int16 slot = -1;
|
|
|
|
name = buf + 192;
|
|
|
|
while (!shouldQuit()) {
|
|
windowPutChar(window, 128);
|
|
|
|
_saveLoadEdit = true;
|
|
|
|
i = userGameGetKey(&b, buf, 128);
|
|
if (b) {
|
|
if (i <= 223) {
|
|
if (!confirmOverWrite(window)) {
|
|
listSaveGames(buf);
|
|
continue;
|
|
}
|
|
|
|
if (!saveGame(_saveLoadRowCurPos + i, buf + i * 8))
|
|
fileError(_windowArray[num], true);
|
|
}
|
|
|
|
goto get_out;
|
|
}
|
|
|
|
userGameBackSpace(_windowArray[num], 8);
|
|
if (i == 10 || i == 13) {
|
|
slot = matchSaveGame(name, numSaveGames);
|
|
if (slot >= 0) {
|
|
if (!confirmOverWrite(window)) {
|
|
listSaveGames(buf);
|
|
continue;
|
|
}
|
|
}
|
|
break;
|
|
} else if (i == 8) {
|
|
// do_backspace
|
|
if (_saveGameNameLen) {
|
|
_saveGameNameLen--;
|
|
name[_saveGameNameLen] = 0;
|
|
userGameBackSpace(_windowArray[num], 8);
|
|
}
|
|
} else if (i >= 32 && _saveGameNameLen != 8) {
|
|
name[_saveGameNameLen++] = i;
|
|
windowPutChar(_windowArray[num], i);
|
|
}
|
|
}
|
|
|
|
if (_saveGameNameLen != 0) {
|
|
if (slot < 0)
|
|
slot = numSaveGames;
|
|
|
|
if (!saveGame(slot, buf + 192))
|
|
fileError(_windowArray[num], true);
|
|
}
|
|
} else {
|
|
i = userGameGetKey(&b, buf, 128);
|
|
if (i != 225) {
|
|
if (!loadGame(genSaveName(_saveLoadRowCurPos + i)))
|
|
fileError(_windowArray[num], false);
|
|
}
|
|
}
|
|
|
|
get_out:;
|
|
disableFileBoxes();
|
|
|
|
_gameStoppedClock = getTime() - saveTime + _gameStoppedClock;
|
|
|
|
if (getGameType() == GType_ELVIRA2)
|
|
restartAnimation();
|
|
}
|
|
|
|
int AGOSEngine_Elvira2::userGameGetKey(bool *b, char *buf, uint maxChar) {
|
|
HitArea *ha;
|
|
*b = true;
|
|
|
|
_keyPressed.reset();
|
|
|
|
while (!shouldQuit()) {
|
|
_lastHitArea = NULL;
|
|
_lastHitArea3 = NULL;
|
|
|
|
do {
|
|
if (_saveLoadEdit && _keyPressed.ascii && _keyPressed.ascii < maxChar) {
|
|
*b = false;
|
|
return _keyPressed.ascii;
|
|
}
|
|
delay(10);
|
|
} while (_lastHitArea3 == 0 && !shouldQuit());
|
|
|
|
ha = _lastHitArea;
|
|
if (ha == NULL || ha->id < 200) {
|
|
} else if (ha->id == 225) {
|
|
return ha->id;
|
|
} else if (ha->id == 224) {
|
|
_saveGameNameLen = 0;
|
|
_saveLoadRowCurPos += 24;
|
|
if (_saveLoadRowCurPos >= _numSaveGameRows)
|
|
_saveLoadRowCurPos = 1;
|
|
|
|
listSaveGames(buf);
|
|
} else if (ha->id < 224) {
|
|
return ha->id - 200;
|
|
}
|
|
}
|
|
|
|
return 225;
|
|
}
|
|
|
|
void AGOSEngine_Simon1::listSaveGames(char *dst) {
|
|
Common::InSaveFile *in;
|
|
uint16 i, slot, lastSlot;
|
|
|
|
disableFileBoxes();
|
|
|
|
showMessageFormat("\xC");
|
|
|
|
memset(dst, 0, 108);
|
|
|
|
slot = _saveLoadRowCurPos;
|
|
while (_saveLoadRowCurPos + 6 > slot) {
|
|
if (!(in = _saveFileMan->openForLoading(genSaveName(slot))))
|
|
break;
|
|
|
|
in->read(dst, 18);
|
|
delete in;
|
|
|
|
lastSlot = slot;
|
|
if (slot < 10) {
|
|
showMessageFormat(" ");
|
|
} else if (_language == Common::HE_ISR) {
|
|
lastSlot = (slot % 10) * 10;
|
|
lastSlot += slot / 10;
|
|
}
|
|
|
|
showMessageFormat("%d", lastSlot);
|
|
if (_language == Common::HE_ISR && !(slot % 10))
|
|
showMessageFormat("0");
|
|
showMessageFormat(".%s\n", dst);
|
|
dst += 18;
|
|
slot++;
|
|
}
|
|
|
|
if (!_saveOrLoad) {
|
|
if (_saveLoadRowCurPos + 6 == slot) {
|
|
slot++;
|
|
} else {
|
|
if (slot < 10)
|
|
showMessageFormat(" ");
|
|
showMessageFormat("%d.\n", slot);
|
|
}
|
|
} else {
|
|
if (_saveLoadRowCurPos + 6 == slot) {
|
|
if ((in = _saveFileMan->openForLoading(genSaveName(slot)))) {
|
|
slot++;
|
|
delete in;
|
|
}
|
|
}
|
|
}
|
|
|
|
_saveDialogFlag = true;
|
|
|
|
i = slot - _saveLoadRowCurPos;
|
|
if (i != 7) {
|
|
i++;
|
|
if (!_saveOrLoad)
|
|
i++;
|
|
_saveDialogFlag = false;
|
|
}
|
|
|
|
if (!--i)
|
|
return;
|
|
|
|
do {
|
|
enableBox(208 + i - 1);
|
|
} while (--i);
|
|
}
|
|
|
|
const byte hebrewKeyTable[96] = {
|
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 90, 45, 85, 47, 48, 49, 50,
|
|
51, 52, 53, 54, 55, 56, 57, 83, 83, 90, 61, 85, 63, 35, 89, 80, 65, 66, 87,
|
|
75, 82, 73, 79, 71, 76, 74, 86, 78, 77, 84, 47, 88, 67, 64, 69, 68, 44, 81,
|
|
72, 70, 91, 92, 93, 94, 95, 96, 89, 80, 65, 66, 87, 75, 82, 73, 79, 71, 76,
|
|
74, 86, 78, 77, 84, 47, 88, 67, 64, 69, 68, 44, 81, 72, 70,
|
|
123, 124, 125, 126, 127,
|
|
};
|
|
|
|
void AGOSEngine_Simon1::userGame(bool load) {
|
|
uint32 saveTime;
|
|
int i, numSaveGames, result;
|
|
WindowBlock *window;
|
|
char *name;
|
|
bool b;
|
|
char buf[108];
|
|
int maxChar = (_language == Common::HE_ISR) ? 155: 128;
|
|
|
|
_saveOrLoad = load;
|
|
|
|
saveTime = getTime();
|
|
|
|
numSaveGames = countSaveGames();
|
|
if (!load)
|
|
numSaveGames++;
|
|
numSaveGames -= 6;
|
|
if (numSaveGames < 0)
|
|
numSaveGames = 0;
|
|
numSaveGames++;
|
|
_numSaveGameRows = numSaveGames;
|
|
|
|
_saveLoadRowCurPos = 1;
|
|
if (!load)
|
|
_saveLoadRowCurPos = numSaveGames;
|
|
|
|
_saveLoadEdit = false;
|
|
|
|
restart:;
|
|
i = userGameGetKey(&b, buf, maxChar);
|
|
|
|
if (i == 205)
|
|
goto get_out;
|
|
if (!load) {
|
|
// if_1
|
|
if_1:;
|
|
result = i;
|
|
|
|
disableBox(208 + i);
|
|
leaveHitAreaById(208 + i);
|
|
|
|
window = _windowArray[5];
|
|
|
|
window->textRow = result;
|
|
|
|
// init x offset with a 2 character savegame number + a period (18 pix)
|
|
if (_language == Common::HE_ISR) {
|
|
window->textColumn = 3;
|
|
window->textColumnOffset = 6;
|
|
} else {
|
|
window->textColumn = 2;
|
|
window->textColumnOffset = 2;
|
|
}
|
|
window->textLength = 3;
|
|
|
|
name = buf + i * 18;
|
|
|
|
// now process entire savegame name to get correct x offset for cursor
|
|
_saveGameNameLen = 0;
|
|
while (name[_saveGameNameLen]) {
|
|
if (_language == Common::HE_ISR) {
|
|
byte width = 6;
|
|
if (name[_saveGameNameLen] >= 64 && name[_saveGameNameLen] < 91)
|
|
width = _hebrewCharWidths [name[_saveGameNameLen] - 64];
|
|
window->textLength++;
|
|
window->textColumnOffset -= width;
|
|
if (window->textColumnOffset < width) {
|
|
window->textColumnOffset += 8;
|
|
window->textColumn++;
|
|
}
|
|
} else {
|
|
window->textLength++;
|
|
window->textColumnOffset += 6;
|
|
if (name[_saveGameNameLen] == 'i' || name[_saveGameNameLen] == 'l')
|
|
window->textColumnOffset -= 2;
|
|
if (window->textColumnOffset >= 8) {
|
|
window->textColumnOffset -= 8;
|
|
window->textColumn++;
|
|
}
|
|
}
|
|
_saveGameNameLen++;
|
|
}
|
|
|
|
while (!shouldQuit()) {
|
|
windowPutChar(window, 127);
|
|
|
|
_saveLoadEdit = true;
|
|
|
|
i = userGameGetKey(&b, buf, maxChar);
|
|
|
|
if (b) {
|
|
if (i == 205)
|
|
goto get_out;
|
|
enableBox(208 + result);
|
|
if (_saveLoadEdit) {
|
|
userGameBackSpace(_windowArray[5], 8);
|
|
}
|
|
goto if_1;
|
|
}
|
|
|
|
if (!_saveLoadEdit) {
|
|
enableBox(208 + result);
|
|
goto restart;
|
|
}
|
|
|
|
if (_language == Common::HE_ISR) {
|
|
if (i >= 128)
|
|
i -= 64;
|
|
else if (i >= 32)
|
|
i = hebrewKeyTable[i - 32];
|
|
}
|
|
|
|
userGameBackSpace(_windowArray[5], 8);
|
|
if (i == 10 || i == 13) {
|
|
break;
|
|
} else if (i == 8) {
|
|
// do_backspace
|
|
if (_saveGameNameLen) {
|
|
byte m, x;
|
|
|
|
_saveGameNameLen--;
|
|
m = name[_saveGameNameLen];
|
|
|
|
if (_language == Common::HE_ISR)
|
|
x = 8;
|
|
else
|
|
x = (name[_saveGameNameLen] == 'i' || name[_saveGameNameLen] == 'l') ? 1 : 8;
|
|
|
|
name[_saveGameNameLen] = 0;
|
|
|
|
userGameBackSpace(_windowArray[5], x, m);
|
|
}
|
|
} else if (i >= 32 && _saveGameNameLen != 17) {
|
|
name[_saveGameNameLen++] = i;
|
|
|
|
windowPutChar(_windowArray[5], i);
|
|
}
|
|
}
|
|
|
|
if (!saveGame(_saveLoadRowCurPos + result, buf + result * 18))
|
|
fileError(_windowArray[5], true);
|
|
} else {
|
|
if (!loadGame(genSaveName(_saveLoadRowCurPos + i)))
|
|
fileError(_windowArray[5], false);
|
|
}
|
|
|
|
get_out:;
|
|
disableFileBoxes();
|
|
|
|
_gameStoppedClock = getTime() - saveTime + _gameStoppedClock;
|
|
}
|
|
|
|
int AGOSEngine_Simon1::userGameGetKey(bool *b, char *buf, uint maxChar) {
|
|
HitArea *ha;
|
|
*b = true;
|
|
|
|
if (!_saveLoadEdit) {
|
|
listSaveGames(buf);
|
|
}
|
|
|
|
_keyPressed.reset();
|
|
|
|
while (!shouldQuit()) {
|
|
_lastHitArea = NULL;
|
|
_lastHitArea3 = NULL;
|
|
|
|
do {
|
|
if (_saveLoadEdit && _keyPressed.ascii && _keyPressed.ascii < maxChar) {
|
|
*b = false;
|
|
return _keyPressed.ascii;
|
|
}
|
|
delay(10);
|
|
} while (_lastHitArea3 == 0 && !shouldQuit());
|
|
|
|
ha = _lastHitArea;
|
|
if (ha == NULL || ha->id < 205) {
|
|
} else if (ha->id == 205) {
|
|
return ha->id;
|
|
} else if (ha->id == 206) {
|
|
if (_saveLoadRowCurPos != 1) {
|
|
if (_saveLoadRowCurPos < 7)
|
|
_saveLoadRowCurPos = 1;
|
|
else
|
|
_saveLoadRowCurPos -= 6;
|
|
|
|
_saveLoadEdit = false;
|
|
listSaveGames(buf);
|
|
}
|
|
} else if (ha->id == 207) {
|
|
if (_saveDialogFlag) {
|
|
_saveLoadRowCurPos += 6;
|
|
if (_saveLoadRowCurPos >= _numSaveGameRows)
|
|
_saveLoadRowCurPos = _numSaveGameRows;
|
|
|
|
_saveLoadEdit = false;
|
|
listSaveGames(buf);
|
|
}
|
|
} else if (ha->id < 214) {
|
|
return ha->id - 208;
|
|
}
|
|
}
|
|
|
|
return 205;
|
|
}
|
|
|
|
void AGOSEngine::disableFileBoxes() {
|
|
int i;
|
|
|
|
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
|
|
for (i = 208; i != 214; i++)
|
|
disableBox(i);
|
|
} else {
|
|
for (i = 200; i != 224; i++)
|
|
disableBox(i);
|
|
}
|
|
}
|
|
|
|
void AGOSEngine::userGameBackSpace(WindowBlock *window, int x, byte b) {
|
|
byte oldTextColor;
|
|
|
|
windowPutChar(window, x, b);
|
|
oldTextColor = window->textColor;
|
|
window->textColor = window->fillColor;
|
|
|
|
if (_language == Common::HE_ISR) {
|
|
x = 128;
|
|
} else {
|
|
x += 120;
|
|
if (x != 128)
|
|
x = 129;
|
|
}
|
|
|
|
windowPutChar(window, x);
|
|
|
|
window->textColor = oldTextColor;
|
|
windowPutChar(window, 8);
|
|
}
|
|
|
|
void AGOSEngine::fileError(WindowBlock *window, bool saveError) {
|
|
const char *message1, *message2;
|
|
|
|
if (saveError) {
|
|
switch (_language) {
|
|
case Common::RU_RUS:
|
|
if (getGameType() == GType_SIMON2) {
|
|
message1 = "\r Mf sowrap+fts+.";
|
|
message2 = "\r Nzjb#a ejs#a.";
|
|
} else {
|
|
message1 = "\r Mf sowrap]fts].";
|
|
message2 = "\r Nzjb_a ejs_a.";
|
|
}
|
|
break;
|
|
case Common::PL_POL:
|
|
message1 = "\r Blad zapisu. ";
|
|
message2 = "\rBlad dysku. ";
|
|
break;
|
|
case Common::ES_ESP:
|
|
message1 = "\r Error al salvar";
|
|
message2 = "\r Intenta con otro disco";
|
|
break;
|
|
case Common::IT_ITA:
|
|
message1 = "\r Salvataggio non riuscito";
|
|
message2 = "\r Prova un""\x27""altro disco";
|
|
break;
|
|
case Common::FR_FRA:
|
|
message1 = "\r Echec sauvegarde";
|
|
message2 = "\rEssayez une autre disquette";
|
|
break;
|
|
case Common::DE_DEU:
|
|
message1 = "\r Sicherung erfolglos.";
|
|
message2 = "\rVersuche eine andere Diskette.";
|
|
break;
|
|
default:
|
|
message1 = "\r Save failed.";
|
|
message2 = "\r Disk error.";
|
|
break;
|
|
}
|
|
} else {
|
|
switch (_language) {
|
|
case Common::RU_RUS:
|
|
if (getGameType() == GType_SIMON2) {
|
|
message1 = "\r Mf ^adruhafts+.";
|
|
message2 = "\r Takm pf pakefp.";
|
|
} else {
|
|
message1 = "\r Mf ^adruhafts].";
|
|
message2 = "\r Takm pf pakefp.";
|
|
}
|
|
break;
|
|
case Common::PL_POL:
|
|
message1 = "\r Blad odczytu. ";
|
|
message2 = "\r Nie znaleziono pliku.";
|
|
break;
|
|
case Common::ES_ESP:
|
|
message1 = "\r Error al cargar";
|
|
message2 = "\r Archivo no encontrado";
|
|
break;
|
|
case Common::IT_ITA:
|
|
message1 = "\r Caricamento non riuscito";
|
|
message2 = "\r File non trovato";
|
|
break;
|
|
case Common::FR_FRA:
|
|
message1 = "\r Echec chargement";
|
|
message2 = "\r Fichier introuvable";
|
|
break;
|
|
case Common::DE_DEU:
|
|
message1 = "\r Laden erfolglos.";
|
|
message2 = "\r Datei nicht gefunden.";
|
|
break;
|
|
default:
|
|
message1 = "\r Load failed.";
|
|
message2 = "\r File not found.";
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (getGameType() == GType_ELVIRA1) {
|
|
printScroll();
|
|
window->textColumn = 0;
|
|
window->textRow = 0;
|
|
window->textColumnOffset = 0;
|
|
window->textLength = 0; // Difference
|
|
} else {
|
|
windowPutChar(window, 12);
|
|
}
|
|
|
|
for (; *message1; message1++)
|
|
windowPutChar(window, *message1);
|
|
for (; *message2; message2++)
|
|
windowPutChar(window, *message2);
|
|
|
|
waitWindow(window);
|
|
}
|
|
|
|
uint16 readItemID(Common::SeekableReadStream *f) {
|
|
uint32 val = f->readUint32BE();
|
|
if (val == 0xFFFFFFFF)
|
|
return 0;
|
|
return val + 1;
|
|
}
|
|
|
|
void writeItemID(Common::WriteStream *f, uint16 val) {
|
|
if (val == 0)
|
|
f->writeUint32BE(0xFFFFFFFF);
|
|
else
|
|
f->writeUint32BE(val - 1);
|
|
}
|
|
|
|
bool AGOSEngine::loadGame(const char *filename, bool restartMode) {
|
|
char ident[100];
|
|
Common::SeekableReadStream *f = NULL;
|
|
uint num, item_index, i;
|
|
|
|
_videoLockOut |= 0x100;
|
|
|
|
if (restartMode) {
|
|
// Load restart state
|
|
Common::File *file = new Common::File();
|
|
file->open(filename);
|
|
f = file;
|
|
} else {
|
|
f = _saveFileMan->openForLoading(filename);
|
|
}
|
|
|
|
if (f == NULL) {
|
|
_videoLockOut &= ~0x100;
|
|
return false;
|
|
}
|
|
|
|
if (!restartMode) {
|
|
f->read(ident, 8);
|
|
}
|
|
|
|
num = f->readUint32BE();
|
|
|
|
if (f->readUint32BE() != 0xFFFFFFFF || num != _itemArrayInited - 1) {
|
|
delete f;
|
|
_videoLockOut &= ~0x100;
|
|
return false;
|
|
}
|
|
|
|
f->readUint32BE();
|
|
f->readUint32BE();
|
|
_noParentNotify = true;
|
|
|
|
// add all timers
|
|
killAllTimers();
|
|
for (num = f->readUint32BE(); num; num--) {
|
|
uint32 timeout = f->readUint32BE();
|
|
uint16 subroutine_id = f->readUint16BE();
|
|
addTimeEvent(timeout, subroutine_id);
|
|
}
|
|
|
|
item_index = 1;
|
|
for (num = _itemArrayInited - 1; num; num--) {
|
|
Item *item = _itemArrayPtr[item_index++], *parent_item;
|
|
|
|
parent_item = derefItem(readItemID(f));
|
|
setItemParent(item, parent_item);
|
|
|
|
item->state = f->readUint16BE();
|
|
item->classFlags = f->readUint16BE();
|
|
|
|
SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
|
|
if (o) {
|
|
o->objectSize = f->readUint16BE();
|
|
o->objectWeight = f->readUint16BE();
|
|
}
|
|
|
|
SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType);
|
|
if (p) {
|
|
p->score = f->readUint32BE();
|
|
p->level = f->readUint16BE();
|
|
p->size = f->readUint16BE();
|
|
p->weight = f->readUint16BE();
|
|
p->strength = f->readUint16BE();
|
|
}
|
|
|
|
SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
|
|
if (u) {
|
|
for (i = 0; i != 8; i++) {
|
|
u->userFlags[i] = f->readUint16BE();
|
|
}
|
|
u->userItems[0] = readItemID(f);
|
|
}
|
|
}
|
|
|
|
// read the variables
|
|
for (i = 0; i != _numVars; i++) {
|
|
writeVariable(i, f->readUint16BE());
|
|
}
|
|
|
|
if (f->err()) {
|
|
error("load failed");
|
|
}
|
|
|
|
delete f;
|
|
|
|
_noParentNotify = false;
|
|
|
|
_videoLockOut &= ~0x100;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AGOSEngine::saveGame(uint slot, const char *caption) {
|
|
Common::OutSaveFile *f;
|
|
uint item_index, num_item, i;
|
|
TimeEvent *te;
|
|
uint32 curTime = getTime();
|
|
uint32 gsc = _gameStoppedClock;
|
|
|
|
_videoLockOut |= 0x100;
|
|
|
|
f = _saveFileMan->openForSaving(genSaveName(slot));
|
|
if (f == NULL) {
|
|
_videoLockOut &= ~0x100;
|
|
return false;
|
|
}
|
|
|
|
f->write(caption, 8);
|
|
|
|
f->writeUint32BE(_itemArrayInited - 1);
|
|
f->writeUint32BE(0xFFFFFFFF);
|
|
f->writeUint32BE(curTime);
|
|
f->writeUint32BE(0);
|
|
|
|
i = 0;
|
|
for (te = _firstTimeStruct; te; te = te->next)
|
|
i++;
|
|
f->writeUint32BE(i);
|
|
|
|
for (te = _firstTimeStruct; te; te = te->next) {
|
|
f->writeUint32BE(te->time - curTime + gsc);
|
|
f->writeUint16BE(te->subroutine_id);
|
|
}
|
|
|
|
item_index = 1;
|
|
for (num_item = _itemArrayInited - 1; num_item; num_item--) {
|
|
Item *item = _itemArrayPtr[item_index++];
|
|
|
|
writeItemID(f, item->parent);
|
|
|
|
f->writeUint16BE(item->state);
|
|
f->writeUint16BE(item->classFlags);
|
|
|
|
SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
|
|
if (o) {
|
|
f->writeUint16BE(o->objectSize);
|
|
f->writeUint16BE(o->objectWeight);
|
|
}
|
|
|
|
SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType);
|
|
if (p) {
|
|
f->writeUint32BE(p->score);
|
|
f->writeUint16BE(p->level);
|
|
f->writeUint16BE(p->size);
|
|
f->writeUint16BE(p->weight);
|
|
f->writeUint16BE(p->strength);
|
|
}
|
|
|
|
SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
|
|
if (u) {
|
|
for (i = 0; i != 8; i++) {
|
|
f->writeUint16BE(u->userFlags[i]);
|
|
}
|
|
writeItemID(f, u->userItems[0]);
|
|
}
|
|
}
|
|
|
|
// write the variables
|
|
for (i = 0; i != _numVars; i++) {
|
|
f->writeUint16BE(readVariable(i));
|
|
}
|
|
|
|
f->finalize();
|
|
bool result = !f->err();
|
|
|
|
delete f;
|
|
_videoLockOut &= ~0x100;
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) {
|
|
char ident[100];
|
|
Common::SeekableReadStream *f = NULL;
|
|
uint num, item_index, i, j;
|
|
|
|
_videoLockOut |= 0x100;
|
|
|
|
if (restartMode) {
|
|
// Load restart state
|
|
Common::File *file = new Common::File();
|
|
file->open(filename);
|
|
f = file;
|
|
} else {
|
|
f = _saveFileMan->openForLoading(filename);
|
|
}
|
|
|
|
if (f == NULL) {
|
|
_videoLockOut &= ~0x100;
|
|
return false;
|
|
}
|
|
|
|
if (getGameType() == GType_PP) {
|
|
// No caption
|
|
} else if (getGameType() == GType_FF) {
|
|
f->read(ident, 100);
|
|
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
|
|
f->read(ident, 18);
|
|
} else if (!restartMode) {
|
|
f->read(ident, 8);
|
|
}
|
|
|
|
num = f->readUint32BE();
|
|
|
|
if (f->readUint32BE() != 0xFFFFFFFF || num != _itemArrayInited - 1) {
|
|
delete f;
|
|
_videoLockOut &= ~0x100;
|
|
return false;
|
|
}
|
|
|
|
f->readUint32BE();
|
|
f->readUint32BE();
|
|
_noParentNotify = true;
|
|
|
|
// add all timers
|
|
killAllTimers();
|
|
for (num = f->readUint32BE(); num; num--) {
|
|
uint32 timeout = f->readUint32BE();
|
|
uint16 subroutine_id = f->readUint16BE();
|
|
addTimeEvent(timeout, subroutine_id);
|
|
}
|
|
|
|
if (getGameType() == GType_WW && getPlatform() == Common::kPlatformPC) {
|
|
for (uint s = 0; s < _numRoomStates; s++) {
|
|
_roomStates[s].state = f->readUint16BE();
|
|
_roomStates[s].classFlags = f->readUint16BE();
|
|
_roomStates[s].roomExitStates = f->readUint16BE();
|
|
}
|
|
f->readUint16BE();
|
|
|
|
uint16 room = _currentRoom;
|
|
_currentRoom = f->readUint16BE();
|
|
|
|
if (_roomsListPtr) {
|
|
byte *p = _roomsListPtr;
|
|
if (room == _currentRoom) {
|
|
for (;;) {
|
|
uint16 minNum = READ_BE_UINT16(p); p += 2;
|
|
if (minNum == 0)
|
|
break;
|
|
|
|
uint16 maxNum = READ_BE_UINT16(p); p += 2;
|
|
|
|
for (uint16 z = minNum; z <= maxNum; z++) {
|
|
uint16 itemNum = z + 2;
|
|
Item *item = derefItem(itemNum);
|
|
|
|
num = (itemNum - _itemArrayInited);
|
|
item->state = _roomStates[num].state;
|
|
item->classFlags = _roomStates[num].classFlags;
|
|
SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
|
|
subRoom->roomExitStates = _roomStates[num].roomExitStates;
|
|
}
|
|
}
|
|
} else {
|
|
for (;;) {
|
|
uint16 minNum = READ_BE_UINT16(p); p += 2;
|
|
if (minNum == 0)
|
|
break;
|
|
|
|
uint16 maxNum = READ_BE_UINT16(p); p += 2;
|
|
|
|
for (uint16 z = minNum; z <= maxNum; z++) {
|
|
uint16 itemNum = z + 2;
|
|
Item *item = derefItem(itemNum);
|
|
item->parent = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (room != _currentRoom) {
|
|
_roomsListPtr = 0;
|
|
loadRoomItems(_currentRoom);
|
|
}
|
|
}
|
|
|
|
item_index = 1;
|
|
for (num = _itemArrayInited - 1; num; num--) {
|
|
Item *item = _itemArrayPtr[item_index++], *parent_item;
|
|
|
|
if ((getGameType() == GType_WW && getPlatform() == Common::kPlatformAmiga) ||
|
|
getGameType() == GType_ELVIRA2) {
|
|
parent_item = derefItem(readItemID(f));
|
|
setItemParent(item, parent_item);
|
|
} else {
|
|
uint parent = f->readUint16BE();
|
|
uint next = f->readUint16BE();
|
|
|
|
parent_item = derefItem(parent);
|
|
setItemParent(item, parent_item);
|
|
|
|
if (parent_item == NULL) {
|
|
item->parent = parent;
|
|
item->next = next;
|
|
}
|
|
}
|
|
|
|
item->state = f->readUint16BE();
|
|
item->classFlags = f->readUint16BE();
|
|
|
|
SubRoom *r = (SubRoom *)findChildOfType(item, kRoomType);
|
|
if (r) {
|
|
r->roomExitStates = f->readUint16BE();
|
|
}
|
|
|
|
SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, kSuperRoomType);
|
|
if (sr) {
|
|
uint16 n = sr->roomX * sr->roomY * sr->roomZ;
|
|
for (i = j = 0; i != n; i++)
|
|
sr->roomExitStates[j++] = f->readUint16BE();
|
|
}
|
|
|
|
SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
|
|
if (o) {
|
|
o->objectFlags = f->readUint32BE();
|
|
i = o->objectFlags & 1;
|
|
|
|
for (j = 1; j < 16; j++) {
|
|
if (o->objectFlags & (1 << j)) {
|
|
o->objectFlagValue[i++] = f->readUint16BE();
|
|
}
|
|
}
|
|
}
|
|
|
|
SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
|
|
if (u) {
|
|
for (i = 0; i != 4; i++) {
|
|
u->userFlags[i] = f->readUint16BE();
|
|
}
|
|
}
|
|
}
|
|
|
|
// read the variables
|
|
for (i = 0; i != _numVars; i++) {
|
|
writeVariable(i, f->readUint16BE());
|
|
}
|
|
|
|
// read the items in item store
|
|
for (i = 0; i != _numItemStore; i++) {
|
|
if (getGameType() == GType_WW && getPlatform() == Common::kPlatformAmiga) {
|
|
_itemStore[i] = derefItem(f->readUint16BE() / 16);
|
|
} else if (getGameType() == GType_ELVIRA2) {
|
|
if (getPlatform() == Common::kPlatformPC) {
|
|
_itemStore[i] = derefItem(readItemID(f));
|
|
} else {
|
|
_itemStore[i] = derefItem(f->readUint16BE() / 18);
|
|
}
|
|
} else {
|
|
_itemStore[i] = derefItem(f->readUint16BE());
|
|
}
|
|
}
|
|
|
|
// Read the bits in array 1
|
|
for (i = 0; i != _numBitArray1; i++)
|
|
_bitArray[i] = f->readUint16BE();
|
|
|
|
// Read the bits in array 2
|
|
for (i = 0; i != _numBitArray2; i++)
|
|
_bitArrayTwo[i] = f->readUint16BE();
|
|
|
|
// Read the bits in array 3
|
|
for (i = 0; i != _numBitArray3; i++)
|
|
_bitArrayThree[i] = f->readUint16BE();
|
|
|
|
if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
|
_superRoomNumber = f->readUint16BE();
|
|
}
|
|
|
|
if (f->err()) {
|
|
error("load failed");
|
|
}
|
|
|
|
delete f;
|
|
|
|
_noParentNotify = false;
|
|
|
|
_videoLockOut &= ~0x100;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
|
|
Common::OutSaveFile *f;
|
|
uint item_index, num_item, i, j;
|
|
TimeEvent *te;
|
|
uint32 curTime = getTime();
|
|
uint32 gsc = _gameStoppedClock;
|
|
|
|
_videoLockOut |= 0x100;
|
|
|
|
f = _saveFileMan->openForSaving(genSaveName(slot));
|
|
if (f == NULL) {
|
|
_videoLockOut &= ~0x100;
|
|
return false;
|
|
}
|
|
|
|
if (getGameType() == GType_PP) {
|
|
// No caption
|
|
} else if (getGameType() == GType_FF) {
|
|
f->write(caption, 100);
|
|
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
|
|
f->write(caption, 18);
|
|
} else {
|
|
f->write(caption, 8);
|
|
}
|
|
|
|
f->writeUint32BE(_itemArrayInited - 1);
|
|
f->writeUint32BE(0xFFFFFFFF);
|
|
f->writeUint32BE(curTime);
|
|
f->writeUint32BE(0);
|
|
|
|
i = 0;
|
|
for (te = _firstTimeStruct; te; te = te->next)
|
|
i++;
|
|
f->writeUint32BE(i);
|
|
|
|
if (getGameType() == GType_FF && _clockStopped)
|
|
gsc += (getTime() - _clockStopped);
|
|
for (te = _firstTimeStruct; te; te = te->next) {
|
|
f->writeUint32BE(te->time - curTime + gsc);
|
|
f->writeUint16BE(te->subroutine_id);
|
|
}
|
|
|
|
if (getGameType() == GType_WW && getPlatform() == Common::kPlatformPC) {
|
|
if (_roomsListPtr) {
|
|
byte *p = _roomsListPtr;
|
|
for (;;) {
|
|
uint16 minNum = READ_BE_UINT16(p); p += 2;
|
|
if (minNum == 0)
|
|
break;
|
|
|
|
uint16 maxNum = READ_BE_UINT16(p); p += 2;
|
|
|
|
for (uint16 z = minNum; z <= maxNum; z++) {
|
|
uint16 itemNum = z + 2;
|
|
Item *item = derefItem(itemNum);
|
|
|
|
uint16 num = (itemNum - _itemArrayInited);
|
|
_roomStates[num].state = item->state;
|
|
_roomStates[num].classFlags = item->classFlags;
|
|
SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
|
|
_roomStates[num].roomExitStates = subRoom->roomExitStates;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (uint s = 0; s < _numRoomStates; s++) {
|
|
f->writeUint16BE(_roomStates[s].state);
|
|
f->writeUint16BE(_roomStates[s].classFlags);
|
|
f->writeUint16BE(_roomStates[s].roomExitStates);
|
|
}
|
|
f->writeUint16BE(0);
|
|
f->writeUint16BE(_currentRoom);
|
|
}
|
|
|
|
item_index = 1;
|
|
for (num_item = _itemArrayInited - 1; num_item; num_item--) {
|
|
Item *item = _itemArrayPtr[item_index++];
|
|
|
|
if ((getGameType() == GType_WW && getPlatform() == Common::kPlatformAmiga) ||
|
|
getGameType() == GType_ELVIRA2) {
|
|
writeItemID(f, item->parent);
|
|
} else {
|
|
f->writeUint16BE(item->parent);
|
|
f->writeUint16BE(item->next);
|
|
}
|
|
|
|
f->writeUint16BE(item->state);
|
|
f->writeUint16BE(item->classFlags);
|
|
|
|
SubRoom *r = (SubRoom *)findChildOfType(item, kRoomType);
|
|
if (r) {
|
|
f->writeUint16BE(r->roomExitStates);
|
|
}
|
|
|
|
SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, kSuperRoomType);
|
|
if (sr) {
|
|
uint16 n = sr->roomX * sr->roomY * sr->roomZ;
|
|
for (i = j = 0; i != n; i++)
|
|
f->writeUint16BE(sr->roomExitStates[j++]);
|
|
}
|
|
|
|
SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
|
|
if (o) {
|
|
f->writeUint32BE(o->objectFlags);
|
|
i = o->objectFlags & 1;
|
|
|
|
for (j = 1; j < 16; j++) {
|
|
if (o->objectFlags & (1 << j)) {
|
|
f->writeUint16BE(o->objectFlagValue[i++]);
|
|
}
|
|
}
|
|
}
|
|
|
|
SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
|
|
if (u) {
|
|
for (i = 0; i != 4; i++) {
|
|
f->writeUint16BE(u->userFlags[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// write the variables
|
|
for (i = 0; i != _numVars; i++) {
|
|
f->writeUint16BE(readVariable(i));
|
|
}
|
|
|
|
// write the items in item store
|
|
for (i = 0; i != _numItemStore; i++) {
|
|
if (getGameType() == GType_WW && getPlatform() == Common::kPlatformAmiga) {
|
|
f->writeUint16BE(itemPtrToID(_itemStore[i]) * 16);
|
|
} else if (getGameType() == GType_ELVIRA2) {
|
|
if (getPlatform() == Common::kPlatformPC) {
|
|
writeItemID(f, itemPtrToID(_itemStore[i]));
|
|
} else {
|
|
f->writeUint16BE(itemPtrToID(_itemStore[i]) * 18);
|
|
}
|
|
} else {
|
|
f->writeUint16BE(itemPtrToID(_itemStore[i]));
|
|
}
|
|
}
|
|
|
|
// Write the bits in array 1
|
|
for (i = 0; i != _numBitArray1; i++)
|
|
f->writeUint16BE(_bitArray[i]);
|
|
|
|
// Write the bits in array 2
|
|
for (i = 0; i != _numBitArray2; i++)
|
|
f->writeUint16BE(_bitArrayTwo[i]);
|
|
|
|
// Write the bits in array 3
|
|
for (i = 0; i != _numBitArray3; i++)
|
|
f->writeUint16BE(_bitArrayThree[i]);
|
|
|
|
if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
|
f->writeUint16BE(_superRoomNumber);
|
|
}
|
|
|
|
f->finalize();
|
|
bool result = !f->err();
|
|
|
|
delete f;
|
|
_videoLockOut &= ~0x100;
|
|
|
|
return result;
|
|
}
|
|
|
|
// Personal Nightmare specific
|
|
bool AGOSEngine_PN::badload(int8 errorNum) {
|
|
if (errorNum == -2)
|
|
return 0;
|
|
// Load error recovery routine
|
|
|
|
// Clear any stack
|
|
while (_stackbase != NULL) {
|
|
dumpstack();
|
|
}
|
|
|
|
// Restart from process 1
|
|
_tagOfActiveDoline = 1;
|
|
_dolineReturnVal = 3;
|
|
return 1;
|
|
}
|
|
|
|
void AGOSEngine_PN::getFilename() {
|
|
_noScanFlag = 1;
|
|
clearInputLine();
|
|
|
|
memset(_saveFile, 0, sizeof(_saveFile));
|
|
while (!shouldQuit() && !strlen(_saveFile)) {
|
|
const char *msg = "File name : ";
|
|
pcf((unsigned char)'\n');
|
|
while (*msg)
|
|
pcf((unsigned char)*msg++);
|
|
|
|
interact(_saveFile, 8);
|
|
pcf((unsigned char)'\n');
|
|
_noScanFlag = 0;
|
|
}
|
|
}
|
|
|
|
int AGOSEngine_PN::loadFile(char *name) {
|
|
Common::InSaveFile *f;
|
|
haltAnimation();
|
|
|
|
f = _saveFileMan->openForLoading(name);
|
|
if (f == NULL) {
|
|
restartAnimation();
|
|
return -2;
|
|
}
|
|
f->read(_saveFile, 8);
|
|
|
|
if (f->readByte() != 41) {
|
|
restartAnimation();
|
|
delete f;
|
|
return -2;
|
|
}
|
|
if (f->readByte() != 33) {
|
|
restartAnimation();
|
|
delete f;
|
|
return -2;
|
|
}
|
|
// TODO: Make endian safe
|
|
if (!f->read(_dataBase + _quickptr[2], (int)(_quickptr[6] - _quickptr[2]))) {
|
|
restartAnimation();
|
|
delete f;
|
|
return -1;
|
|
}
|
|
delete f;
|
|
restartAnimation();
|
|
dbtosysf();
|
|
return 0;
|
|
}
|
|
|
|
int AGOSEngine_PN::saveFile(char *name) {
|
|
Common::OutSaveFile *f;
|
|
sysftodb();
|
|
haltAnimation();
|
|
|
|
f = _saveFileMan->openForSaving(name);
|
|
if (f == NULL) {
|
|
restartAnimation();
|
|
|
|
const char *msg = "Couldn't save. ";
|
|
pcf((unsigned char)'\n');
|
|
while (*msg)
|
|
pcf((unsigned char)*msg++);
|
|
|
|
return 0;
|
|
}
|
|
f->write(_saveFile, 8);
|
|
|
|
f->writeByte(41);
|
|
f->writeByte(33);
|
|
// TODO: Make endian safe
|
|
if (!f->write(_dataBase + _quickptr[2], (int)(_quickptr[6] - _quickptr[2]))) {
|
|
delete f;
|
|
restartAnimation();
|
|
error("Couldn't save ");
|
|
return 0; // for compilers that don't support NORETURN
|
|
}
|
|
f->finalize();
|
|
delete f;
|
|
|
|
restartAnimation();
|
|
return 1;
|
|
}
|
|
|
|
void AGOSEngine_PN::sysftodb() {
|
|
uint32 pos = _quickptr[2];
|
|
int ct = 0;
|
|
|
|
while (ct < (getptr(49L) / 2)) {
|
|
_dataBase[pos] = (uint8)(_variableArray[ct] % 256);
|
|
_dataBase[pos + 1] = (uint8)(_variableArray[ct] / 256);
|
|
pos+=2;
|
|
ct++;
|
|
}
|
|
}
|
|
|
|
void AGOSEngine_PN::dbtosysf() {
|
|
uint32 pos = _quickptr[2];
|
|
int ct = 0;
|
|
|
|
while (ct < (getptr(49L) / 2)) {
|
|
_variableArray[ct] = _dataBase[pos] + 256 * _dataBase[pos + 1];
|
|
pos += 2;
|
|
ct++;
|
|
}
|
|
}
|
|
|
|
} // End of namespace AGOS
|