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:
Filippos Karapetis 2015-02-19 15:41:15 +02:00 committed by Eugene Sandulenko
parent 6af7abeab2
commit 0a71969018
10 changed files with 324 additions and 4628 deletions

View file

@ -28,6 +28,11 @@
*
*/
#include "common/translation.h"
#include "gui/message.h"
#include "gui/saveload.h"
#include "lab/lab.h"
#include "lab/labfun.h"
#include "lab/parsefun.h"
@ -40,12 +45,6 @@
#include "lab/stddefines.h"
#include "lab/parsetypes.h"
#define MODERNGAMESAVE 1
#if defined(MODERNGAMESAVE)
#include "lab/modernsavegame.h"
#endif
namespace Lab {
#ifdef GAME_TRIAL
@ -109,7 +108,7 @@ static byte *loadBackPict(const char *fileName, bool tomem) {
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};
@ -942,528 +941,57 @@ void doJournal() {
ungetVGABaseAddr();
}
/*
struct SaveGameInfo {
unsigned short RoomNumber;
unsigned short Direction;
byte *SaveGameImage;
char SaveGameDate[128];
};
int getSaveGameList(SaveGameInfo *info, int maxNum);
*/
/*---------------------------------------------------------------------------*/
/*------------------------- The Save/Restore stuff --------------------------*/
/*---------------------------------------------------------------------------*/
Image *Arrow1, *NoArrow1, *DriveButton;
#define QUARTERNUM 30
extern InventoryData *Inventory;
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) {
byte **buffer;
bool isok = true;
bool isOK = false;
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)) {
BigMsgFont = NULL;
return false;
if (desc.empty()) {
// create our own description for the saved game, the user didn't enter it
desc = dialog->createDefaultSaveDescription(slot);
}
isOK = saveGame(RoomNum, Direction, Inventory[QUARTERNUM].Many, slot, desc);
}
} else {
// Restore
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);
}
buffer = g_music->newOpen("P:ModSave");
if (!buffer) {
freeAllStolenMem();
if (!isOK)
return false;
}
g_TotalSavedGames = getSaveGameList(g_SaveGameInfo, MAX_SAVED_GAMES);
g_CurSaveGameNumber = g_LastSaveGameNumber;
g_CurSaveSet = g_CurSaveGameNumber / 5;
g_PendingNewSave = 0;
g_music->resetMusic();
loadBackPict("P:ModSave", false);
mouseShow();
VGASetPal(diffcmap, 256);
memcpy(g_CommonPalette, diffcmap, 3 * 256);
isok = processSaveLoad();
eatMessages();
mouseHide();
@ -1478,372 +1006,8 @@ bool saveRestoreGame(void) {
freeAllStolenMem();
freeSaveGameList(g_SaveGameInfo, g_TotalSavedGames);
return isok;
return true;
}
#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;
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 ----------------------------*/