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