1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/* 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/advsys/game.h"
#include "common/memstream.h"
namespace Glk {
namespace AdvSys {
void Decrypter::decrypt(byte *data, size_t size) {
for (; --size; ++data)
*data = ~(*data + 30);
}
/*--------------------------------------------------------------------------*/
#define HEADER_SIZE 62
bool Header::load(Common::ReadStream &s) {
_valid = false;
byte data[HEADER_SIZE];
// Read in the data
if (s.read(data, HEADER_SIZE) != HEADER_SIZE)
return false;
decrypt(data, HEADER_SIZE);
Common::MemoryReadStream ms(data, HEADER_SIZE, DisposeAfterUse::NO);
// Validate the header
_valid = !strncmp((const char*)data + 2, "ADVSYS", 6);
if (!_valid)
return false;
_size = ms.readUint16LE();
ms.skip(6);
_headerVersion = ms.readUint16LE();
_name = Common::String((const char *)data + 10, (const char *)data + 28);
ms.skip(18);
_version = ms.readUint16LE();
_wordTableOffset = ms.readUint16LE();
_wordTypeTableOffset = ms.readUint16LE();
_objectTableOffset = ms.readUint16LE();
_actionTableOffset = ms.readUint16LE();
_variableTableOffset = ms.readUint16LE();
_dataSpaceOffset = ms.readUint16LE();
_codeSpaceOffset = ms.readUint16LE();
_dataBlockOffset = ms.readUint16LE();
_messageBlockOffset = ms.readUint16LE();
_initCodeOffset = ms.readUint16LE();
_updateCodeOffset = ms.readUint16LE();
_beforeOffset = ms.readUint16LE();
_afterOffset = ms.readUint16LE();
_errorHandlerOffset = ms.readUint16LE();
_saveAreaOffset = ms.readUint16LE();
_saveSize = ms.readUint16LE();
return true;
}
/*--------------------------------------------------------------------------*/
#define MAX_VERSION 102
bool Game::load(Common::SeekableReadStream &s) {
// Load the header
s.seek(0);
if (!Header::load(s))
return false;
if (_headerVersion < 101 || _headerVersion > MAX_VERSION)
error("Wrong version number");
// Load the needed resident game data and decrypt it
_residentOffset = _dataBlockOffset * 512;
s.seek(_residentOffset);
_data.resize(_size);
if (!s.read(&_data[0], _size))
return false;
decrypt(&_data[0], _size);
_residentBase = &_data[0];
_wordTable = &_data[_wordTableOffset];
_wordTypeTable = &_data[_wordTypeTableOffset];
_objectTable = &_data[_objectTableOffset];
_actionTable = &_data[_actionTableOffset];
_variableTable = &_data[_variableTableOffset];
_saveArea = &_data[_saveAreaOffset];
_dataSpace = &_data[_dataSpaceOffset];
_codeSpace = &_data[_codeSpaceOffset];
return true;
}
} // End of namespace AdvSys
} // End of namespace Glk
|