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 "graphics/cursorman.h"
24 
25 #include "gob/gob.h"
26 #include "gob/global.h"
27 #include "gob/util.h"
28 #include "gob/surface.h"
29 #include "gob/dataio.h"
30 #include "gob/palanim.h"
31 #include "gob/draw.h"
32 #include "gob/video.h"
33 #include "gob/aniobject.h"
34 
35 #include "gob/sound/sound.h"
36 
37 #include "gob/pregob/pregob.h"
38 #include "gob/pregob/gctfile.h"
39 
40 
41 namespace Gob {
42 
43 const char  PreGob::kLanguageSuffixShort[5] = { 't',  'g',  'a',  'e',  'i'};
44 const char *PreGob::kLanguageSuffixLong [5] = {"fr", "al", "an", "it", "es"};
45 
46 
PreGob(GobEngine * vm)47 PreGob::PreGob(GobEngine *vm) : _vm(vm), _fadedOut(false) {
48 }
49 
~PreGob()50 PreGob::~PreGob() {
51 }
52 
fadeOut()53 void PreGob::fadeOut() {
54 	if (_fadedOut || _vm->shouldQuit())
55 		return;
56 
57 	// Fade to black
58 	_vm->_palAnim->fade(0, 0, 0);
59 
60 	_fadedOut = true;
61 }
62 
fadeIn()63 void PreGob::fadeIn() {
64 	if (!_fadedOut || _vm->shouldQuit())
65 		return;
66 
67 	// Fade to palette
68 	_vm->_draw->blitInvalidated();
69 	_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, 0);
70 	_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 0, 0, 319, 199);
71 
72 	_fadedOut = false;
73 }
74 
clearScreen()75 void PreGob::clearScreen() {
76 	_vm->_draw->_backSurface->clear();
77 	_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 0, 0, 319, 199);
78 	_vm->_draw->blitInvalidated();
79 	_vm->_video->retrace();
80 }
81 
initScreen()82 void PreGob::initScreen() {
83 	_vm->_util->setFrameRate(15);
84 
85 	_fadedOut = true;
86 
87 	_vm->_draw->initScreen();
88 
89 	_vm->_draw->_backSurface->clear();
90 	_vm->_util->clearPalette();
91 
92 	_vm->_draw->forceBlit();
93 	_vm->_video->retrace();
94 
95 	_vm->_util->processInput();
96 }
97 
setPalette(const byte * palette,uint16 size)98 void PreGob::setPalette(const byte *palette, uint16 size) {
99 	memcpy(_vm->_draw->_vgaPalette, palette, 3 * size);
100 
101 	// If we didn't fade out prior, immediately set the palette
102 	if (!_fadedOut)
103 		_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
104 }
105 
addCursor()106 void PreGob::addCursor() {
107 	CursorMan.pushCursor(0, 0, 0, 0, 0, 0);
108 }
109 
removeCursor()110 void PreGob::removeCursor() {
111 	CursorMan.popCursor();
112 }
113 
setCursor(Surface & sprite,int16 hotspotX,int16 hotspotY)114 void PreGob::setCursor(Surface &sprite, int16 hotspotX, int16 hotspotY) {
115 	CursorMan.replaceCursor(sprite.getData(), sprite.getWidth(), sprite.getHeight(), hotspotX, hotspotY, 0);
116 }
117 
setCursor(Surface & sprite,int16 left,int16 top,int16 right,int16 bottom,int16 hotspotX,int16 hotspotY)118 void PreGob::setCursor(Surface &sprite, int16 left, int16 top, int16 right, int16 bottom,
119 					   int16 hotspotX, int16 hotspotY) {
120 
121 	const int width  = right  - left + 1;
122 	const int height = bottom - top  + 1;
123 
124 	if ((width <= 0) || (height <= 0))
125 		return;
126 
127 	Surface cursor(width, height, 1);
128 
129 	cursor.blit(sprite, left, top, right, bottom, 0, 0);
130 
131 	setCursor(cursor, hotspotX, hotspotX);
132 }
133 
showCursor()134 void PreGob::showCursor() {
135 	CursorMan.showMouse(true);
136 
137 	_vm->_draw->_showCursor = 4;
138 }
139 
hideCursor()140 void PreGob::hideCursor() {
141 	CursorMan.showMouse(false);
142 
143 	_vm->_draw->_showCursor = 0;
144 }
145 
isCursorVisible() const146 bool PreGob::isCursorVisible() const {
147 	return CursorMan.isVisible();
148 }
149 
loadSounds(const char * const * sounds,uint soundCount)150 void PreGob::loadSounds(const char * const *sounds, uint soundCount) {
151 	freeSounds();
152 
153 	_sounds.resize(soundCount);
154 
155 	for (uint i = 0; i < soundCount; i++)
156 		loadSound(_sounds[i], sounds[i]);
157 }
158 
freeSounds()159 void PreGob::freeSounds() {
160 	_sounds.clear();
161 }
162 
loadSound(SoundDesc & sound,const Common::String & file) const163 bool PreGob::loadSound(SoundDesc &sound, const Common::String &file) const {
164 	return _vm->_sound->sampleLoad(&sound, SOUND_SND, file.c_str());
165 }
166 
playSound(uint sound,int16 frequency,int16 repCount)167 void PreGob::playSound(uint sound, int16 frequency, int16 repCount) {
168 	if (sound >= _sounds.size())
169 		return;
170 
171 	_vm->_sound->blasterPlay(&_sounds[sound], repCount, frequency);
172 }
173 
stopSound()174 void PreGob::stopSound() {
175 	_vm->_sound->blasterStop(0);
176 }
177 
playSoundFile(const Common::String & file,int16 frequency,int16 repCount,bool interruptible)178 void PreGob::playSoundFile(const Common::String &file, int16 frequency, int16 repCount, bool interruptible) {
179 	stopSound();
180 
181 	SoundDesc sound;
182 	if (!loadSound(sound, file))
183 		return;
184 
185 	_vm->_sound->blasterPlay(&sound, repCount, frequency);
186 
187 	_vm->_util->forceMouseUp();
188 
189 	bool finished = false;
190 	while (!_vm->shouldQuit() && !finished && _vm->_sound->blasterPlayingSound()) {
191 		endFrame(true);
192 
193 		finished = hasInput();
194 	}
195 
196 	_vm->_util->forceMouseUp();
197 
198 	stopSound();
199 }
200 
beep(int16 frequency,int32 length)201 void PreGob::beep(int16 frequency, int32 length) {
202 	_vm->_sound->speakerOn(frequency, length);
203 }
204 
endFrame(bool doInput)205 void PreGob::endFrame(bool doInput) {
206 	_vm->_draw->blitInvalidated();
207 	_vm->_util->waitEndFrame();
208 
209 	if (doInput)
210 		_vm->_util->processInput();
211 }
212 
checkInput(int16 & mouseX,int16 & mouseY,MouseButtons & mouseButtons)213 int16 PreGob::checkInput(int16 &mouseX, int16 &mouseY, MouseButtons &mouseButtons) {
214 	_vm->_util->getMouseState(&mouseX, &mouseY, &mouseButtons);
215 	_vm->_util->forceMouseUp();
216 
217 	return _vm->_util->checkKey();
218 }
219 
waitInput(int16 & mouseX,int16 & mouseY,MouseButtons & mouseButtons)220 int16 PreGob::waitInput(int16 &mouseX, int16 &mouseY, MouseButtons &mouseButtons) {
221 	bool finished = false;
222 
223 	int16 key = 0;
224 	while (!_vm->shouldQuit() && !finished) {
225 		endFrame(true);
226 
227 		key = checkInput(mouseX, mouseY, mouseButtons);
228 
229 		finished = (mouseButtons != kMouseButtonsNone) || (key != 0);
230 	}
231 
232 	return key;
233 }
234 
waitInput()235 int16 PreGob::waitInput() {
236 	int16 mouseX, mouseY;
237 	MouseButtons mouseButtons;
238 
239 	return waitInput(mouseX, mouseY, mouseButtons);
240 }
241 
hasInput()242 bool PreGob::hasInput() {
243 	int16 mouseX, mouseY;
244 	MouseButtons mouseButtons;
245 
246 	return checkInput(mouseX, mouseY, mouseButtons) || (mouseButtons != kMouseButtonsNone);
247 }
248 
clearAnim(ANIObject & anim)249 void PreGob::clearAnim(ANIObject &anim) {
250 	int16 left, top, right, bottom;
251 
252 	if (anim.clear(*_vm->_draw->_backSurface, left, top, right, bottom))
253 		_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
254 }
255 
drawAnim(ANIObject & anim)256 void PreGob::drawAnim(ANIObject &anim) {
257 	int16 left, top, right, bottom;
258 
259 	if (anim.draw(*_vm->_draw->_backSurface, left, top, right, bottom))
260 		_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
261 	anim.advance();
262 }
263 
redrawAnim(ANIObject & anim)264 void PreGob::redrawAnim(ANIObject &anim) {
265 	clearAnim(anim);
266 	drawAnim(anim);
267 }
268 
clearAnim(const ANIList & anims)269 void PreGob::clearAnim(const ANIList &anims) {
270 	for (int i = (anims.size() - 1); i >= 0; i--)
271 		clearAnim(*anims[i]);
272 }
273 
drawAnim(const ANIList & anims)274 void PreGob::drawAnim(const ANIList &anims) {
275 	for (ANIList::const_iterator a = anims.begin(); a != anims.end(); ++a)
276 		drawAnim(**a);
277 }
278 
redrawAnim(const ANIList & anims)279 void PreGob::redrawAnim(const ANIList &anims) {
280 	clearAnim(anims);
281 	drawAnim(anims);
282 }
283 
loadAnims(ANIList & anims,ANIFile & ani,uint count,const AnimProperties * props) const284 void PreGob::loadAnims(ANIList &anims, ANIFile &ani, uint count, const AnimProperties *props) const {
285 	freeAnims(anims);
286 
287 	anims.resize(count);
288 	for (uint i = 0; i < count; i++) {
289 		anims[i] = new ANIObject(ani);
290 
291 		setAnim(*anims[i], props[i]);
292 	}
293 }
294 
freeAnims(ANIList & anims) const295 void PreGob::freeAnims(ANIList &anims) const {
296 	for (ANIList::iterator a = anims.begin(); a != anims.end(); ++a)
297 		delete *a;
298 
299 	anims.clear();
300 }
301 
setAnim(ANIObject & anim,const AnimProperties & props) const302 void PreGob::setAnim(ANIObject &anim, const AnimProperties &props) const {
303 	anim.setAnimation(props.animation);
304 	anim.setFrame(props.frame);
305 	anim.setMode(props.mode);
306 	anim.setPause(props.paused);
307 	anim.setVisible(props.visible);
308 
309 	if (props.hasPosition)
310 		anim.setPosition(props.x, props.y);
311 	else
312 		anim.setPosition();
313 }
314 
getLocFile(const Common::String & file) const315 Common::String PreGob::getLocFile(const Common::String &file) const {
316 	if (_vm->_global->_language >= ARRAYSIZE(kLanguageSuffixShort))
317 		return file;
318 
319 	return file + kLanguageSuffixShort[_vm->_global->_language];
320 }
321 
loadTXT(const Common::String & txtFile,TXTFile::Format format) const322 TXTFile *PreGob::loadTXT(const Common::String &txtFile, TXTFile::Format format) const {
323 	Common::SeekableReadStream *txtStream = _vm->_dataIO->getFile(txtFile);
324 	if (!txtStream)
325 		error("PreGob::loadTXT(): Failed to open \"%s\"", txtFile.c_str());
326 
327 	TXTFile *txt = new TXTFile(*txtStream, format);
328 
329 	delete txtStream;
330 
331 	fixTXTStrings(*txt);
332 
333 	return txt;
334 }
335 
fixTXTStrings(TXTFile & txt) const336 void PreGob::fixTXTStrings(TXTFile &txt) const {
337 }
338 
loadGCT(const Common::String & gctFile) const339 GCTFile *PreGob::loadGCT(const Common::String &gctFile) const {
340 	Common::SeekableReadStream *gctStream = _vm->_dataIO->getFile(gctFile);
341 	if (!gctStream)
342 		error("PreGob::loadGCT(): Failed to open \"%s\"", gctFile.c_str());
343 
344 	GCTFile *gct = new GCTFile(*gctStream, _vm->_rnd);
345 
346 	delete gctStream;
347 
348 	return gct;
349 }
350 
351 } // End of namespace Gob
352