1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/file.h"
24 #include "common/system.h"
25 #include "common/textconsole.h"
26
27 #include "graphics/surface.h"
28
29 #include "agos/agos.h"
30 #include "agos/intern.h"
31
32 namespace AGOS {
33
loadMenuFile()34 void AGOSEngine::loadMenuFile() {
35 Common::File in;
36
37 in.open(getFileName(GAME_MENUFILE));
38 if (in.isOpen() == false) {
39 error("loadMenuFile: Can't load menus file '%s'", getFileName(GAME_MENUFILE));
40 }
41
42 uint fileSize = in.size();
43 _menuBase = (byte *)malloc(fileSize);
44 if (_menuBase == NULL)
45 error("loadMenuFile: Out of memory for menu data");
46 in.read(_menuBase, fileSize);
47 in.close();
48 }
49
50 // Personal Nightmare specific
restoreMenu()51 void AGOSEngine::restoreMenu() {
52 _wiped = 0;
53
54 _videoLockOut |= 0x80;
55
56 clearVideoWindow(3, 0);
57
58 uint16 oldWindowNum = _windowNum;
59
60 setWindowImage(1, 1);
61 setWindowImage(2, 2);
62
63 drawEdging();
64
65 _windowNum = oldWindowNum;
66
67 _videoLockOut |= 0x20;
68 _videoLockOut &= ~0x80;
69 }
70
71 // Elvira 1 specific
drawMenuStrip(uint windowNum,uint menuNum)72 void AGOSEngine::drawMenuStrip(uint windowNum, uint menuNum) {
73 WindowBlock *window = _windowArray[windowNum % 8];
74
75 mouseOff();
76
77 byte *srcPtr = _menuBase;
78 int menu = (menuNum != 0) ? menuNum * 4 + 1 : 0;
79
80 while (menu--) {
81 if (READ_LE_UINT16(srcPtr) != 0xFFFF) {
82 srcPtr += 2;
83 while (*srcPtr != 0)
84 srcPtr++;
85 srcPtr++;
86 } else {
87 srcPtr += 2;
88 }
89 }
90
91 clearWindow(window);
92
93 int newline = 0;
94 while (READ_LE_UINT16(srcPtr) != 0xFFFF) {
95 byte *tmp = srcPtr;
96 srcPtr += 2;
97
98 if (newline != 0) {
99 windowPutChar(window, 10);
100 }
101
102 uint len = 0;
103 while (*srcPtr != 0 && *srcPtr != 1) {
104 len++;
105 srcPtr++;
106 }
107 if (*srcPtr == 1)
108 srcPtr++;
109
110 uint maxLen = window->textMaxLength - len;
111
112 if (window->flags & 1)
113 window->textColumnOffset += 4;
114
115 maxLen /= 2;
116 while (maxLen--)
117 windowPutChar(window, 32);
118
119 srcPtr = tmp;
120 uint verb = READ_BE_UINT16(srcPtr); srcPtr += 2;
121
122 while (*srcPtr != 0) {
123 windowPutChar(window, *srcPtr++);
124 }
125 srcPtr++;
126
127 if (verb != 0xFFFE) {
128 HitArea *ha = findEmptyHitArea();
129 ha->x = window->x * 8 + 3;
130 ha->y = window->textRow * 8 + window->y;
131 ha->data = menuNum;
132 ha->width = window->width * 8 - 6;
133 ha->height = 7;
134 ha->flags = kBFBoxInUse | kBFInvertTouch;
135 ha->id = 30000;
136 ha->priority = 1;
137 ha->verb = verb;
138 }
139
140 newline = 0xFFFF;
141 }
142
143 mouseOn();
144 }
145
lightMenuStrip(int a)146 void AGOSEngine::lightMenuStrip(int a) {
147 mouseOff();
148 unlightMenuStrip();
149
150 for (int i = 0; i != 10; i++) {
151 if (a & (1 << i)) {
152 enableBox(120 + i);
153 lightMenuBox(120 + i);
154 }
155 }
156
157 mouseOn();
158 }
159
unlightMenuStrip()160 void AGOSEngine::unlightMenuStrip() {
161 byte *src;
162 int w, h, i;
163
164 mouseOff();
165
166 Graphics::Surface *screen = _system->lockScreen();
167 src = (byte *)screen->getBasePtr(272, 8);
168 w = 48;
169 h = 82;
170
171 do {
172 for (i = 0; i != w; ++i) {
173 if (src[i] != 0)
174 src[i] = 14;
175 }
176 src += screen->pitch;
177 } while (--h);
178
179 for (i = 120; i != 130; i++)
180 disableBox(i);
181
182 _system->unlockScreen();
183
184 mouseOn();
185 }
186
lightMenuBox(uint hitarea)187 void AGOSEngine::lightMenuBox(uint hitarea) {
188 HitArea *ha = findBox(hitarea);
189 byte *src;
190 int w, h, i;
191
192 mouseOff();
193
194 Graphics::Surface *screen = _system->lockScreen();
195 src = (byte *)screen->getBasePtr(ha->x, ha->y);
196 w = ha->width;
197 h = ha->height;
198
199 do {
200 for (i = 0; i != w; ++i) {
201 if (src[i] == 14)
202 src[i] = 15;
203 }
204 src += screen->pitch;
205 } while (--h);
206
207 _system->unlockScreen();
208
209 mouseOn();
210 }
211
212 // Elvira 2 specific
menuFor_e2(Item * item)213 uint AGOSEngine::menuFor_e2(Item *item) {
214 if (item == NULL || item == _dummyItem2 || item == _dummyItem3)
215 return 0xFFFF;
216
217 SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
218 if (subObject != NULL && subObject->objectFlags & kOFMenu) {
219 uint offs = getOffsetOfChild2Param(subObject, kOFMenu);
220 return subObject->objectFlagValue[offs];
221 }
222
223 return _agosMenu;
224 }
225
226 // Waxworks specific
menuFor_ww(Item * item,uint id)227 uint AGOSEngine::menuFor_ww(Item *item, uint id) {
228 if (id != 0xFFFF && id < 10 && _textMenu[id] != 0)
229 return _textMenu[id];
230
231 if (item == NULL || item == _dummyItem2 || item == _dummyItem3)
232 return _agosMenu;
233
234 SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
235 if (subObject != NULL && subObject->objectFlags & kOFMenu) {
236 uint offs = getOffsetOfChild2Param(subObject, kOFMenu);
237 return subObject->objectFlagValue[offs];
238 }
239
240 return _agosMenu;
241 }
242
clearMenuStrip()243 void AGOSEngine::clearMenuStrip() {
244 int i;
245
246 for (i = 111; i != 115; i++)
247 disableBox(i);
248
249 if (getGameType() == GType_WW) {
250 setWindowImageEx(2, 101);
251 } else {
252 setWindowImageEx(2, 102);
253 }
254 }
255
256 // Elvira 2 and Waxworks specific
doMenuStrip(uint menuNum)257 void AGOSEngine::doMenuStrip(uint menuNum) {
258 uint i;
259 const uint var = (getGameType() == GType_WW) ? 11 : 1;
260
261 for (i = 111; i != 115; i++)
262 disableBox(i);
263
264 for (i = var; i != (var + 5); i++)
265 _variableArray[i] = 0;
266
267 byte *srcPtr = _menuBase;
268 while (menuNum--) {
269 while (READ_BE_UINT16(srcPtr) != 0)
270 srcPtr += 2;
271 srcPtr += 2;
272 }
273
274 uint id = 111;
275 uint v = var;
276
277 while (READ_BE_UINT16(srcPtr) != 0) {
278 uint verb = READ_BE_UINT16(srcPtr);
279 _variableArray[v] = verb;
280
281 HitArea *ha = findBox(id);
282 if (ha != NULL) {
283 ha->flags &= ~kBFBoxDead;
284 ha->verb = verb;
285 }
286
287 id++;
288 srcPtr += 2;
289 v++;
290 }
291
292 _variableArray[var + 4] = id - 111;
293 if (getGameType() == GType_WW) {
294 setWindowImageEx(2, 102);
295 } else {
296 setWindowImageEx(2, 103);
297 }
298 }
299
300 } // End of namespace AGOS
301