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/endian.h"
24 #include "common/file.h"
25 #include "common/memstream.h"
26
27 #include "gob/gob.h"
28 #include "gob/demos/demoplayer.h"
29 #include "gob/global.h"
30 #include "gob/util.h"
31 #include "gob/draw.h"
32 #include "gob/inter.h"
33 #include "gob/videoplayer.h"
34 #include "gob/sound/sound.h"
35
36 namespace Gob {
37
38 DemoPlayer::Script DemoPlayer::_scripts[] = {
39 {kScriptSourceFile, "demo.scn"},
40 {kScriptSourceFile, "wdemo.s24"},
41 {kScriptSourceFile, "play123.scn"},
42 {kScriptSourceFile, "e.scn"},
43 {kScriptSourceFile, "i.scn"},
44 {kScriptSourceFile, "s.scn"},
45 {kScriptSourceDirect,
46 "slide machu.imd 20\nslide conseil.imd 20\nslide cons.imd 20\n" \
47 "slide tumia.imd 1\nslide tumib.imd 1\nslide tumic.imd 1\n" \
48 "slide tumid.imd 1\nslide post.imd 1\nslide posta.imd 1\n" \
49 "slide postb.imd 1\nslide postc.imd 1\nslide xdome.imd 20\n" \
50 "slide xant.imd 20\nslide tum.imd 20\nslide voile.imd 20\n" \
51 "slide int.imd 20\nslide voila.imd 1\nslide voilb.imd 1\n"},
52 {kScriptSourceFile, "coktelplayer.scn"},
53 {kScriptSourceFile, "demogb.scn"},
54 {kScriptSourceFile, "demoall.scn"},
55 {kScriptSourceFile, "demofra.scn"}
56 };
57
DemoPlayer(GobEngine * vm)58 DemoPlayer::DemoPlayer(GobEngine *vm) : _vm(vm) {
59 _autoDouble = false;
60 _doubleMode = false;
61 _rebase0 = false;
62 }
63
~DemoPlayer()64 DemoPlayer::~DemoPlayer() {
65 }
66
play(const char * fileName)67 bool DemoPlayer::play(const char *fileName) {
68 if (!fileName)
69 return false;
70
71 debugC(1, kDebugDemo, "Playing \"%s\"", fileName);
72
73 init();
74
75 Common::File bat;
76
77 if (!bat.open(fileName))
78 return false;
79
80 return playStream(bat);
81 }
82
play(uint32 index)83 bool DemoPlayer::play(uint32 index) {
84 if (index >= ARRAYSIZE(_scripts))
85 return false;
86
87 Script &script = _scripts[index];
88
89 debugC(1, kDebugDemo, "Playing demoIndex %d: %d", index, script.source);
90
91 switch (script.source) {
92 case kScriptSourceFile:
93 return play(script.script);
94
95 case kScriptSourceDirect:
96 {
97 Common::MemoryReadStream stream((const byte *)script.script, strlen(script.script));
98
99 init();
100 return playStream(stream);
101 }
102
103 default:
104 return false;
105 }
106 }
107
lineStartsWith(const Common::String & line,const char * start)108 bool DemoPlayer::lineStartsWith(const Common::String &line, const char *start) {
109 return (strstr(line.c_str(), start) == line.c_str());
110 }
111
init()112 void DemoPlayer::init() {
113 // The video player needs some fake variables
114 _vm->_inter->allocateVars(32);
115
116 // Init the screen
117 _vm->_draw->initScreen();
118 _vm->_draw->_cursorIndex = -1;
119
120 _vm->_util->longDelay(200); // Letting everything settle
121
122 }
123
clearScreen()124 void DemoPlayer::clearScreen() {
125 debugC(1, kDebugDemo, "Clearing the screen");
126 _vm->_draw->_backSurface->clear();
127 _vm->_draw->forceBlit();
128 _vm->_video->retrace();
129 }
130
playVideo(const char * fileName)131 void DemoPlayer::playVideo(const char *fileName) {
132 uint32 waitTime = 0;
133 Common::String filePtr(fileName);
134 Common::String::iterator file = filePtr.begin();
135
136 // Trimming spaces front
137 while (*file == ' ')
138 file++;
139
140 Common::String::iterator spaceBack = Common::find(file, filePtr.end(), ' ');
141 if (spaceBack != filePtr.end()) {
142 Common::String::iterator nextSpace = Common::find(spaceBack, filePtr.end(), ' ');
143
144 if (nextSpace != filePtr.end())
145 *nextSpace = '\0';
146
147 *spaceBack++ = '\0';
148
149 waitTime = atoi(spaceBack) * 100;
150 }
151
152 debugC(1, kDebugDemo, "Playing video \"%s\"", file);
153
154 VideoPlayer::Properties props;
155
156 props.x = _rebase0 ? 0 : -1;
157 props.y = _rebase0 ? 0 : -1;
158
159 props.switchColorMode = true;
160
161 int slot;
162 if ((slot = _vm->_vidPlayer->openVideo(true, file, props)) >= 0) {
163 if (_autoDouble) {
164 int16 defX = _rebase0 ? 0 : _vm->_vidPlayer->getDefaultX();
165 int16 defY = _rebase0 ? 0 : _vm->_vidPlayer->getDefaultY();
166 int16 right = defX + _vm->_vidPlayer->getWidth() - 1;
167 int16 bottom = defY + _vm->_vidPlayer->getHeight() - 1;
168
169 _doubleMode = ((right < 320) && (bottom < 200));
170 }
171
172 if (_doubleMode)
173 playVideoDoubled(slot);
174 else
175 playVideoNormal(slot);
176
177 _vm->_vidPlayer->closeVideo(slot);
178
179 if (waitTime > 0)
180 _vm->_util->longDelay(waitTime);
181 }
182 }
183
playADL(const char * params)184 void DemoPlayer::playADL(const char *params) {
185 const char *end;
186
187 end = strchr(params, ' ');
188 if (!end)
189 end = params + strlen(params);
190
191 Common::String fileName(params, end);
192 bool waitEsc = true;
193 int32 repeat = -1;
194
195 if (*end != '\0') {
196 const char *start = end + 1;
197
198 waitEsc = (*start != '0');
199
200 end = strchr(start, ' ');
201 if (end)
202 repeat = atoi(end + 1);
203 }
204
205 playADL(fileName, waitEsc, repeat);
206 }
207
playVideoNormal(int slot)208 void DemoPlayer::playVideoNormal(int slot) {
209 VideoPlayer::Properties props;
210
211 _vm->_vidPlayer->play(slot, props);
212 }
213
playVideoDoubled(int slot)214 void DemoPlayer::playVideoDoubled(int slot) {
215 Common::String fileNameOpened = _vm->_vidPlayer->getFileName(slot);
216 _vm->_vidPlayer->closeVideo(slot);
217
218 VideoPlayer::Properties props;
219
220 props.x = _rebase0 ? 0 : -1;
221 props.y = _rebase0 ? 0 : -1;
222 props.flags = VideoPlayer::kFlagScreenSurface;
223 props.waitEndFrame = false;
224
225 _vm->_vidPlayer->evaluateFlags(props);
226
227 slot = _vm->_vidPlayer->openVideo(true, fileNameOpened, props);
228 if (slot < 0)
229 return;
230
231 for (uint i = 0; i < _vm->_vidPlayer->getFrameCount(slot); i++) {
232 props.startFrame = _vm->_vidPlayer->getCurrentFrame(slot) + 1;
233 props.lastFrame = _vm->_vidPlayer->getCurrentFrame(slot) + 1;
234
235 _vm->_vidPlayer->play(slot, props);
236
237 const Common::List<Common::Rect> *rects = _vm->_vidPlayer->getDirtyRects(slot);
238 if (rects) {
239 for (Common::List<Common::Rect>::const_iterator rect = rects->begin(); rect != rects->end(); ++rect) {
240 int16 w = rect->right - rect->left;
241 int16 h = rect->bottom - rect->top;
242 int16 wD = (rect->left * 2) + (w * 2);
243 int16 hD = (rect->top * 2) + (h * 2);
244
245 _vm->_draw->_frontSurface->blitScaled(*_vm->_draw->_spritesArray[0],
246 rect->left, rect->top, rect->right - 1, rect->bottom - 1, rect->left * 2, rect->top * 2, 2);
247
248 _vm->_draw->dirtiedRect(_vm->_draw->_frontSurface,
249 rect->left * 2, rect->top * 2, wD, hD);
250 }
251 }
252
253 _vm->_video->retrace();
254
255 _vm->_util->processInput();
256 if (_vm->shouldQuit())
257 break;
258
259 int16 key;
260 bool end = false;
261 while (_vm->_util->checkKey(key))
262 if (key == kKeyEscape)
263 end = true;
264 if (end)
265 break;
266
267 _vm->_vidPlayer->waitEndFrame(slot);
268 }
269
270 }
271
playADL(const Common::String & fileName,bool waitEsc,int32 repeat)272 void DemoPlayer::playADL(const Common::String &fileName, bool waitEsc, int32 repeat) {
273 debugC(1, kDebugDemo, "Playing ADL \"%s\" (%d, %d)", fileName.c_str(), waitEsc, repeat);
274
275 _vm->_sound->adlibUnload();
276 _vm->_sound->adlibLoadADL(fileName.c_str());
277 _vm->_sound->adlibSetRepeating(repeat);
278 _vm->_sound->adlibPlay();
279
280 if (!waitEsc)
281 return;
282
283 int16 key = 0;
284 while (!_vm->shouldQuit() && (key != kKeyEscape) && _vm->_sound->adlibIsPlaying()) {
285 _vm->_util->longDelay(1);
286 while (_vm->_util->checkKey(key))
287 if (key == kKeyEscape)
288 break;
289 }
290 }
291
evaluateVideoMode(const char * mode)292 void DemoPlayer::evaluateVideoMode(const char *mode) {
293 debugC(2, kDebugDemo, "Video mode \"%s\"", mode);
294
295 _autoDouble = false;
296 _doubleMode = false;
297
298 // Only applicable when we actually can double
299 if (_vm->is640x480() || _vm->is800x600()) {
300 if (!scumm_strnicmp(mode, "AUTO", 4))
301 _autoDouble = true;
302 else if (!scumm_strnicmp(mode, "VGA", 3))
303 _doubleMode = true;
304 }
305 }
306
307 } // End of namespace Gob
308