174 lines
5.1 KiB
C++
174 lines
5.1 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "glk/adrift/scare.h"
|
|
#include "glk/adrift/sxprotos.h"
|
|
#include "common/textconsole.h"
|
|
|
|
namespace Glk {
|
|
namespace Adrift {
|
|
|
|
/*
|
|
* Structure for representing a fake game save/restore file. Used to catch
|
|
* a serialized gamestate, and return it later on restore. For now we allow
|
|
* only one of these to exist.
|
|
*/
|
|
struct sx_scr_stream_t {
|
|
sc_byte *data;
|
|
sc_int length;
|
|
sc_bool is_open;
|
|
sc_bool is_writable;
|
|
};
|
|
static sx_scr_stream_t scr_serialization_stream = {nullptr, 0, FALSE, FALSE};
|
|
|
|
|
|
/*
|
|
* file_open_file_callback()
|
|
* file_read_file_callback()
|
|
* file_write_file_callback()
|
|
* file_close_file_callback()
|
|
*
|
|
* Fake a single gamestate save/restore file. Used to satisfy requests from
|
|
* the script to serialize and restore a gamestate. Only one "file" can
|
|
* exist, meaning that a script must restore a saved game before trying to
|
|
* save another.
|
|
*/
|
|
void *file_open_file_callback(sc_bool is_save) {
|
|
sx_scr_stream_t *const stream = &scr_serialization_stream;
|
|
|
|
/* Detect any problems due to scripting limitations. */
|
|
if (stream->is_open) {
|
|
error("File open error: %s",
|
|
"stream is in use (script limitation)");
|
|
return nullptr;
|
|
} else if (is_save && stream->data) {
|
|
error("File open error: %s",
|
|
"stream has not been read (script limitation)");
|
|
return nullptr;
|
|
}
|
|
|
|
/*
|
|
* Set up the stream for the requested mode. Act as if no such file if
|
|
* no data available for a read-only open.
|
|
*/
|
|
if (is_save) {
|
|
stream->data = nullptr;
|
|
stream->length = 0;
|
|
} else if (!stream->data)
|
|
return nullptr;
|
|
|
|
stream->is_open = TRUE;
|
|
stream->is_writable = is_save;
|
|
return stream;
|
|
}
|
|
|
|
sc_int file_read_file_callback(void *opaque, sc_byte *buffer, sc_int length) {
|
|
sx_scr_stream_t *const stream = (sx_scr_stream_t *)opaque;
|
|
sc_int bytes;
|
|
assert(opaque && buffer && length > 0);
|
|
|
|
/* Detect any problems with the callback parameters. */
|
|
if (stream != &scr_serialization_stream) {
|
|
error("File read error: %s", "stream is invalid");
|
|
return 0;
|
|
} else if (!stream->is_open) {
|
|
error("File read error: %s", "stream is not open");
|
|
return 0;
|
|
} else if (stream->is_writable) {
|
|
error("File read error: %s", "stream is not open for read");
|
|
return 0;
|
|
}
|
|
|
|
/* Read and remove the first block of data (or all if less than length). */
|
|
bytes = (stream->length < length) ? stream->length : length;
|
|
memcpy(buffer, stream->data, bytes);
|
|
memmove(stream->data, stream->data + bytes, stream->length - bytes);
|
|
stream->length -= bytes;
|
|
return bytes;
|
|
}
|
|
|
|
void file_write_file_callback(void *opaque, const sc_byte *buffer, sc_int length) {
|
|
sx_scr_stream_t *const stream = (sx_scr_stream_t *)opaque;
|
|
assert(opaque && buffer && length > 0);
|
|
|
|
/* Detect any problems with the callback parameters. */
|
|
if (stream != &scr_serialization_stream) {
|
|
error("File write error: %s", "stream is invalid");
|
|
return;
|
|
} else if (!stream->is_open) {
|
|
error("File write error: %s", "stream is not open");
|
|
return;
|
|
} else if (!stream->is_writable) {
|
|
error("File write error: %s", "stream is not open for write");
|
|
return;
|
|
}
|
|
|
|
/* Reallocate, then add this block of data to the buffer. */
|
|
stream->data = (sc_byte *)sx_realloc(stream->data, stream->length + length);
|
|
memcpy(stream->data + stream->length, buffer, length);
|
|
stream->length += length;
|
|
}
|
|
|
|
void file_close_file_callback(void *opaque) {
|
|
sx_scr_stream_t *const stream = (sx_scr_stream_t *)opaque;
|
|
assert(opaque);
|
|
|
|
/* Detect any problems with the callback parameters. */
|
|
if (stream != &scr_serialization_stream) {
|
|
error("File close error: %s", "stream is invalid");
|
|
return;
|
|
} else if (!stream->is_open) {
|
|
error("File close error: %s", "stream is not open");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* If closing after a read, free allocations, and return the stream to
|
|
* its empty state; if after write, leave the data for the later read.
|
|
*/
|
|
if (!stream->is_writable) {
|
|
sx_free(stream->data);
|
|
stream->data = nullptr;
|
|
stream->length = 0;
|
|
}
|
|
stream->is_writable = FALSE;
|
|
stream->is_open = FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* file_cleanup()
|
|
*
|
|
* Free any pending allocations and clean up on completion of a script.
|
|
*/
|
|
void file_cleanup(void) {
|
|
sx_scr_stream_t *const stream = &scr_serialization_stream;
|
|
|
|
sx_free(stream->data);
|
|
stream->data = nullptr;
|
|
stream->length = 0;
|
|
stream->is_writable = FALSE;
|
|
stream->is_open = FALSE;
|
|
}
|
|
|
|
} // End of namespace Adrift
|
|
} // End of namespace Glk
|