Files
scummvm/engines/glk/magnetic/emu.cpp
T

267 lines
6.6 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.
*
*/
#include "glk/magnetic/magnetic.h"
namespace Glk {
namespace Magnetic {
//static const char *no_hints = "[Hints are not available.]\n";
//static const char *not_supported = "[This function is not supported.]\n";
int Magnetic::ms_init(bool restarting) {
byte header[42];
uint32 i, j, dict_size, string2_size, code_size, dec;
ms_stop();
if (restarting) {
if (!restart)
return 0;
else {
memcpy(code, restart, undo_size);
undo_stat[0] = undo_stat[1] = 0;
ms_showpic(0, 0);
}
} else {
undo_stat[0] = undo_stat[1] = 0;
if (_gameFile.read(header, 42) != 42 || READ_BE_UINT32(header) != MKTAG('M', 'a', 'S', 'c')
|| READ_LE_UINT32(header + 8) != 42)
return 0;
ms_freemem();
version = header[13];
code_size = READ_LE_UINT32(header + 14);
string_size = READ_LE_UINT32(header + 18);
string2_size = READ_LE_UINT32(header + 22);
dict_size = READ_LE_UINT32(header + 26);
undo_size = READ_LE_UINT32(header + 34);
undo_pc = READ_LE_UINT32(header + 38);
if ((version < 4) && (code_size < 65536))
mem_size = 65536;
else
mem_size = code_size;
sd = (byte)((dict_size != 0L) ? 1 : 0); // if (sd) => separate dict
if (!(code = new byte[mem_size]) || !(string2 = new byte[string2_size]) ||
!(restart = new byte[undo_size]) || (sd &&
!(dict = new byte[dict_size]))) {
ms_freemem();
return 0;
}
if (string_size > MAX_STRING_SIZE) {
if (!(string = new byte[MAX_STRING_SIZE]) ||
!(string3 = new byte[string_size - MAX_STRING_SIZE])) {
ms_freemem();
return 0;
}
} else {
if (!(string = new byte[string_size])) {
ms_freemem();
return 0;
}
}
if (!(undo[0] = new byte[undo_size]) || !(undo[1] = new byte[undo_size])) {
ms_freemem();
return 0;
}
if (_gameFile.read(code, code_size) != code_size) {
ms_freemem();
return 0;
}
memcpy(restart, code, undo_size); // fast restarts
if (string_size > MAX_STRING_SIZE) {
if (_gameFile.read(string, MAX_STRING_SIZE) != MAX_STRING_SIZE) {
ms_freemem();
return 0;
}
if (_gameFile.read(string3, string_size - MAX_STRING_SIZE) != (string_size - MAX_STRING_SIZE)) {
ms_freemem();
return 0;
}
} else {
if (_gameFile.read(string, string_size) != string_size) {
ms_freemem();
return 0;
}
}
if (_gameFile.read(string2, string2_size) != string2_size) {
ms_freemem();
return 0;
}
if (sd && _gameFile.read(dict, dict_size) != dict_size) {
ms_freemem();
return 0;
}
dec = READ_LE_UINT32(header + 30);
if (dec >= string_size) {
decode_table = string2 + dec - string_size;
} else {
if (dec >= MAX_STRING_SIZE)
decode_table = string3 + dec - MAX_STRING_SIZE;
else
decode_table = string + dec;
}
}
for (i = 0; i < 8; i++)
dreg[i] = areg[i] = 0;
write_reg(8 + 7, 2, 0xfffe); // Stack-pointer, -2 due to MS-DOS segments
pc = 0;
zflag = nflag = cflag = vflag = 0;
i_count = 0;
running = 1;
if (restarting)
return (byte)(gfx_buf ? 2 : 1); // Restarted
if (version == 4) {
// Try loading a hint file
if (_hintFile.isOpen()) {
_hintFile.seek(0);
if (_hintFile.readUint32BE() == MKTAG('M', 'a', 'H', 't')) {
uint16 blkcnt, elcnt, ntype, elsize, conidx;
// Allocate memory for hints
hints = new ms_hint[MAX_HINTS];
hint_contents = new byte[MAX_HCONTENTS];
if ((hints != 0) && (hint_contents != 0)) {
// Read number of blocks
blkcnt = _hintFile.readUint16LE();
conidx = 0;
for (i = 0; i < blkcnt; i++) {
// Read number of elements
elcnt = _hintFile.readUint16LE();
hints[i].elcount = elcnt;
// Read node type
ntype = _hintFile.readUint16LE();
hints[i].nodetype = ntype;
hints[i].content = hint_contents + conidx;
for (j = 0; j < elcnt; j++) {
elsize = _hintFile.readUint16LE();
if (_hintFile.read(hint_contents + conidx, elsize) != elsize || _hintFile.eos())
return 0;
hint_contents[conidx + elsize - 1] = '\0';
conidx += elsize;
}
// Do we need a jump table?
if (ntype == 1) {
for (j = 0; j < elcnt; j++) {
hints[i].links[j] = _hintFile.readUint16LE();
}
}
// Read the parent block
hints[i].parent = _hintFile.readUint16LE();
}
} else {
delete[] hints;
delete[] hint_contents;
hints = nullptr;
hint_contents = nullptr;
}
}
}
// Try loading a music file
if (_sndFile.isOpen() && _sndFile.size() >= 8) {
_sndFile.seek(0);
if (_sndFile.readUint32BE() != MKTAG('M', 'a', 'S', 'd'))
return 0;
init_snd(_sndFile.readUint32LE());
}
}
if (!_gfxFile.isOpen() || _gfxFile.size() < 8)
return 1;
_gfxFile.seek(0);
uint tag = _gfxFile.readUint32BE();
if (version < 4 && tag == MKTAG('M', 'a', 'P', 'i'))
return init_gfx1(_gfxFile.readUint32LE() - 8);
else if (version == 4 && tag == MKTAG('M', 'a', 'P', '2'))
return init_gfx2(_gfxFile.readUint16LE());
return 1;
}
void Magnetic::ms_freemem() {
delete[] code;
delete[] string;
delete[] string2;
delete[] string3;
delete[] dict;
delete[] undo[0];
delete[] undo[1];
delete[] restart;
code = string = string2 = string3 = dict = nullptr;
undo[0] = undo[1] = restart = nullptr;
delete[] gfx_data;
delete[] gfx_buf;
delete[] gfx2_hdr;
delete[] gfx2_buf;
gfx_data = gfx_buf = gfx2_hdr = gfx2_buf = 0;
gfx_fp.close();
gfx2_name.clear();
gfx_ver = 0;
gfxtable = table_dist = 0;
pos_table_size = 0;
command_index = 0;
anim_repeat = 0;
pos_table_index = -1;
pos_table_max = -1;
lastchar = 0;
delete[] hints;
delete[] hint_contents;
hints = nullptr;
hint_contents = nullptr;
delete[] snd_hdr;
delete[] snd_buf;
snd_hdr = nullptr;
snd_hsize = 0;
snd_buf = nullptr;
}
} // End of namespace Magnetic
} // End of namespace Glk