| 36 | | AnimationState::AnimationState(Screen *scr, Audio::Mixer *snd, OSystem *sys) |
| 37 | | : BaseAnimationState(snd, sys, 640, 400), _scr(scr) { |
| 38 | | } |
| | 37 | static const char *sequenceList[20] = { |
| | 38 | "ferrari", // 0 CD2 ferrari running down fitz in sc19 |
| | 39 | "ladder", // 1 CD2 george walking down ladder to dig sc24->sc$ |
| | 40 | "steps", // 2 CD2 george walking down steps sc23->sc24 |
| | 41 | "sewer", // 3 CD1 george entering sewer sc2->sc6 |
| | 42 | "intro", // 4 CD1 intro sequence ->sc1 |
| | 43 | "river", // 5 CD1 george being thrown into river by flap & g$ |
| | 44 | "truck", // 6 CD2 truck arriving at bull's head sc45->sc53/4 |
| | 45 | "grave", // 7 BOTH george's grave in scotland, from sc73 + from sc38 $ |
| | 46 | "montfcon", // 8 CD2 monfaucon clue in ireland dig, sc25 |
| | 47 | "tapestry", // 9 CD2 tapestry room beyond spain well, sc61 |
| | 48 | "ireland", // 10 CD2 ireland establishing shot europe_map->sc19 |
| | 49 | "finale", // 11 CD2 grand finale at very end, from sc73 |
| | 50 | "history", // 12 CD1 George's history lesson from Nico, in sc10 |
| | 51 | "spanish", // 13 CD2 establishing shot for 1st visit to Spain, europe_m$ |
| | 52 | "well", // 14 CD2 first time being lowered down well in Spai$ |
| | 53 | "candle", // 15 CD2 Candle burning down in Spain mausoleum sc59 |
| | 54 | "geodrop", // 16 CD2 from sc54, George jumping down onto truck |
| | 55 | "vulture", // 17 CD2 from sc54, vultures circling George's dead body |
| | 56 | "enddemo", // 18 --- for end of single CD demo |
| | 57 | "credits", // 19 CD2 credits, to follow "finale" sequence |
| | 58 | }; |
| 167 | | void MoviePlayer::insertOverlay(OverlayColor *buf, uint8 *ovl, OverlayColor *pal) { |
| 168 | | if (ovl != NULL) |
| 169 | | for (uint32 cnt = 0; cnt < 640 * 400; cnt++) |
| 170 | | if (ovl[cnt]) |
| 171 | | buf[cnt] = pal[ovl[cnt]]; |
| 172 | | } |
| 173 | | |
| 174 | | void MoviePlayer::processFrame(uint32 animId, AnimationState *anim, uint32 frameNo) { |
| 175 | | #if defined(USE_MPEG2) && !defined(BACKEND_8BIT) |
| 176 | | if ((animId != 4) || (SwordEngine::_systemVars.cutscenePackVersion == 0)) |
| 177 | | return; |
| 178 | | OverlayColor *buf = anim->giveRgbBuffer(); |
| 179 | | if ((frameNo > 397) && (frameNo < 444)) { // Broken Sword Logo |
| 180 | | if (frameNo <= 403) |
| 181 | | insertOverlay(buf, _logoOvls[frameNo - 398], _introPal); // fade up |
| 182 | | else if (frameNo <= 437) |
| 183 | | insertOverlay(buf, _logoOvls[(frameNo - 404) % 6 + 6], _introPal); // animation |
| 184 | | else { |
| 185 | | insertOverlay(buf, _logoOvls[5 - (frameNo - 438)], _introPal); // fade down |
| 186 | | } |
| 187 | | } |
| 188 | | #endif |
| 189 | | } |
| 190 | | |
| 191 | | bool MoviePlayer::initOverlays(uint32 id) { |
| 192 | | #if defined(USE_MPEG2) && !defined(BACKEND_8BIT) |
| 193 | | if (id == SEQ_INTRO) { |
| 194 | | ArcFile ovlFile; |
| 195 | | if (!ovlFile.open("intro.dat")) { |
| 196 | | warning("\"intro.dat\" not found"); |
| 197 | | return false; |
| 198 | | } |
| 199 | | ovlFile.enterPath(SwordEngine::_systemVars.language); |
| 200 | | for (uint8 fcnt = 0; fcnt < 12; fcnt++) { |
| 201 | | _logoOvls[fcnt] = ovlFile.decompressFile(fcnt); |
| 202 | | if (fcnt > 0) |
| 203 | | for (uint32 cnt = 0; cnt < 640 * 400; cnt++) |
| 204 | | if (_logoOvls[fcnt - 1][cnt] && !_logoOvls[fcnt][cnt]) |
| 205 | | _logoOvls[fcnt][cnt] = _logoOvls[fcnt - 1][cnt]; |
| 206 | | } |
| 207 | | uint8 *pal = ovlFile.fetchFile(12); |
| 208 | | _introPal = (OverlayColor*)malloc(256 * sizeof(OverlayColor)); |
| 209 | | for (uint16 cnt = 0; cnt < 256; cnt++) |
| 210 | | _introPal[cnt] = _sys->RGBToColor(pal[cnt * 3 + 0], pal[cnt * 3 + 1], pal[cnt * 3 + 2]); |
| 211 | | } |
| 212 | | #endif |
| 213 | | |
| 214 | | return true; |
| 215 | | } |
| 216 | | |
| 278 | | const char * MoviePlayer::_sequenceList[20] = { |
| 279 | | "ferrari", // 0 CD2 ferrari running down fitz in sc19 |
| 280 | | "ladder", // 1 CD2 george walking down ladder to dig sc24->sc$ |
| 281 | | "steps", // 2 CD2 george walking down steps sc23->sc24 |
| 282 | | "sewer", // 3 CD1 george entering sewer sc2->sc6 |
| 283 | | "intro", // 4 CD1 intro sequence ->sc1 |
| 284 | | "river", // 5 CD1 george being thrown into river by flap & g$ |
| 285 | | "truck", // 6 CD2 truck arriving at bull's head sc45->sc53/4 |
| 286 | | "grave", // 7 BOTH george's grave in scotland, from sc73 + from sc38 $ |
| 287 | | "montfcon", // 8 CD2 monfaucon clue in ireland dig, sc25 |
| 288 | | "tapestry", // 9 CD2 tapestry room beyond spain well, sc61 |
| 289 | | "ireland", // 10 CD2 ireland establishing shot europe_map->sc19 |
| 290 | | "finale", // 11 CD2 grand finale at very end, from sc73 |
| 291 | | "history", // 12 CD1 George's history lesson from Nico, in sc10 |
| 292 | | "spanish", // 13 CD2 establishing shot for 1st visit to Spain, europe_m$ |
| 293 | | "well", // 14 CD2 first time being lowered down well in Spai$ |
| 294 | | "candle", // 15 CD2 Candle burning down in Spain mausoleum sc59 |
| 295 | | "geodrop", // 16 CD2 from sc54, George jumping down onto truck |
| 296 | | "vulture", // 17 CD2 from sc54, vultures circling George's dead body |
| 297 | | "enddemo", // 18 --- for end of single CD demo |
| 298 | | "credits", // 19 CD2 credits, to follow "finale" sequence |
| 299 | | }; |
| | 280 | #ifdef USE_ZLIB |
| | 282 | /////////////////////////////////////////////////////////////////////////////// |
| | 283 | // Movie player for the new DXA movies |
| | 284 | /////////////////////////////////////////////////////////////////////////////// |
| | 285 | |
| | 286 | MoviePlayerDXA::MoviePlayerDXA(Screen *src, Audio::Mixer *snd, OSystem *sys) |
| | 287 | : MoviePlayer(src, snd, sys) { |
| | 288 | } |
| | 289 | |
| | 290 | MoviePlayerDXA::~MoviePlayerDXA(void) { |
| | 291 | // free(_frameBuffer); |
| | 292 | } |
| | 293 | |
| | 294 | bool MoviePlayerDXA::load(uint32 id) { |
| | 295 | if (!MoviePlayer::load(id)) |
| | 296 | return false; |
| | 297 | |
| | 298 | char filename[20]; |
| | 299 | snprintf(filename, sizeof(filename), "%s.dxa", sequenceList[id]); |
| | 300 | if (loadFile(filename)) { |
| | 301 | // The Broken Sword games always use external audio tracks. |
| | 302 | if (_fd.readUint32BE() != MKID_BE('NULL')) |
| | 303 | return false; |
| | 304 | _frameWidth = getWidth(); |
| | 305 | _frameHeight = getHeight(); |
| | 306 | _frameX = (640 - _frameWidth) / 2; |
| | 307 | _frameY = (480 - _frameHeight) / 2; |
| | 308 | if (!_bgSoundStream) { |
| | 309 | _bgSoundStream = Audio::AudioStream::openStreamFile(sequenceList[id]); |
| | 310 | } |
| | 311 | return true; |
| | 312 | } |
| | 313 | return false; |
| | 314 | } |
| | 315 | |
| | 316 | bool MoviePlayerDXA::initOverlays(uint32 id) { |
| | 317 | // TODO |
| | 318 | return true; |
| | 319 | } |
| | 320 | |
| | 321 | void MoviePlayerDXA::setPalette(byte *pal) { |
| | 322 | updatePalette(pal, true); |
| | 323 | } |
| | 324 | |
| | 325 | bool MoviePlayerDXA::decodeFrame(void) { |
| | 326 | if (_currentFrame < _framesCount) { |
| | 327 | decodeNextFrame(); |
| | 328 | return true; |
| | 329 | } |
| | 330 | return false; |
| | 331 | } |
| | 332 | |
| | 333 | void MoviePlayerDXA::processFrame(void) { |
| | 334 | // TODO |
| | 335 | } |
| | 336 | |
| | 337 | void MoviePlayerDXA::updateScreen(void) { |
| | 338 | // Using _frameBuffer1 directly should work, as long as we don't do any |
| | 339 | // post-processing of the frame. |
| | 340 | _sys->copyRectToScreen(_frameBuffer1, _frameWidth, _frameX, _frameY, _frameWidth, _frameHeight); |
| | 341 | _sys->updateScreen(); |
| | 342 | } |
| | 343 | |
| | 344 | #endif |
| | 345 | |
| | 346 | #ifdef USE_MPEG2 |
| | 347 | |
| | 348 | /////////////////////////////////////////////////////////////////////////////// |
| | 349 | // Movie player for the old MPEG movies |
| | 350 | /////////////////////////////////////////////////////////////////////////////// |
| | 351 | |
| | 352 | MoviePlayerMPEG::MoviePlayerMPEG(Screen *src, Audio::Mixer *snd, OSystem *sys) |
| | 353 | : MoviePlayer(src, snd, sys) { |
| | 354 | for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++) |
| | 355 | _logoOvls[cnt] = NULL; |
| | 356 | _introPal = NULL; |
| | 357 | } |
| | 358 | |
| | 359 | MoviePlayerMPEG::~MoviePlayerMPEG(void) { |
| | 360 | free(_introPal); |
| | 361 | for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++) |
| | 362 | free(_logoOvls[cnt]); |
| | 363 | } |
| | 364 | |
| | 365 | void MoviePlayerMPEG::handleScreenChanged(void) { |
| | 366 | _anim->handleScreenChanged(); |
| | 367 | } |
| | 368 | |
| | 369 | void MoviePlayerMPEG::insertOverlay(OverlayColor *buf, uint8 *ovl, OverlayColor *pal) { |
| | 370 | if (ovl != NULL) |
| | 371 | for (uint32 cnt = 0; cnt < 640 * 400; cnt++) |
| | 372 | if (ovl[cnt]) |
| | 373 | buf[cnt] = pal[ovl[cnt]]; |
| | 374 | } |
| | 375 | |
| | 376 | bool MoviePlayerMPEG::load(uint32 id) { |
| | 377 | if (MoviePlayer::load(id)) { |
| | 378 | _anim = new AnimationState(this, _scr, _snd, _sys); |
| | 379 | return _anim->init(sequenceList[id], _bgSoundStream); |
| | 380 | } |
| | 381 | return false; |
| | 382 | } |
| | 383 | |
| | 384 | bool MoviePlayerMPEG::initOverlays(uint32 id) { |
| | 385 | if (id == SEQ_INTRO) { |
| | 386 | ArcFile ovlFile; |
| | 387 | if (!ovlFile.open("intro.dat")) { |
| | 388 | warning("\"intro.dat\" not found"); |
| | 389 | return false; |
| | 390 | } |
| | 391 | ovlFile.enterPath(SwordEngine::_systemVars.language); |
| | 392 | for (uint8 fcnt = 0; fcnt < 12; fcnt++) { |
| | 393 | _logoOvls[fcnt] = ovlFile.decompressFile(fcnt); |
| | 394 | if (fcnt > 0) |
| | 395 | for (uint32 cnt = 0; cnt < 640 * 400; cnt++) |
| | 396 | if (_logoOvls[fcnt - 1][cnt] && !_logoOvls[fcnt][cnt]) |
| | 397 | _logoOvls[fcnt][cnt] = _logoOvls[fcnt - 1][cnt]; |
| | 398 | } |
| | 399 | uint8 *pal = ovlFile.fetchFile(12); |
| | 400 | _introPal = (OverlayColor*)malloc(256 * sizeof(OverlayColor)); |
| | 401 | for (uint16 cnt = 0; cnt < 256; cnt++) |
| | 402 | _introPal[cnt] = _sys->RGBToColor(pal[cnt * 3 + 0], pal[cnt * 3 + 1], pal[cnt * 3 + 2]); |
| | 403 | } |
| | 404 | |
| | 405 | return true; |
| | 406 | } |
| | 407 | |
| | 408 | bool MoviePlayerMPEG::decodeFrame(void) { |
| | 409 | return _anim->decodeFrame(); |
| | 410 | } |
| | 411 | |
| | 412 | void MoviePlayerMPEG::updateScreen(void) { |
| | 413 | _anim->updateScreen(); |
| | 414 | } |
| | 415 | |
| | 416 | void MoviePlayerMPEG::processFrame(void) { |
| | 417 | #ifndef BACKEND_8BIT |
| | 418 | if ((_id != 4) || (SwordEngine::_systemVars.cutscenePackVersion == 0)) |
| | 419 | return; |
| | 420 | OverlayColor *buf = _anim->giveRgbBuffer(); |
| | 421 | if ((_currentFrame > 397) && (_currentFrame < 444)) { // Broken Sword Logo |
| | 422 | if (_currentFrame <= 403) |
| | 423 | insertOverlay(buf, _logoOvls[_currentFrame - 398], _introPal); // fade up |
| | 424 | else if (_currentFrame <= 437) |
| | 425 | insertOverlay(buf, _logoOvls[(_currentFrame - 404) % 6 + 6], _introPal); // animation |
| | 426 | else { |
| | 427 | insertOverlay(buf, _logoOvls[5 - (_currentFrame - 438)], _introPal); // fade down |
| | 428 | } |
| | 429 | } |
| | 430 | #endif |
| | 431 | } |
| | 432 | |
| | 433 | void MoviePlayerMPEG::syncFrame(void) { |
| | 434 | } |
| | 435 | |
| | 436 | AnimationState::AnimationState(MoviePlayer *player, Screen *scr, Audio::Mixer *snd, OSystem *sys) |
| | 437 | : BaseAnimationState(snd, sys, 640, 400), _player(player), _scr(scr) { |
| | 438 | } |
| | 439 | |
| | 440 | AnimationState::~AnimationState(void) { |
| | 441 | } |
| | 442 | |
| | 443 | #ifdef BACKEND_8BIT |
| | 444 | void AnimationState::setPalette(byte *pal) { |
| | 445 | _player->updatePalette(pal, false); |
| | 446 | } |
| | 447 | #endif |
| | 448 | |
| | 449 | void AnimationState::drawYUV(int width, int height, byte *const *dat) { |
| | 450 | _frameWidth = width; |
| | 451 | _frameHeight = height; |
| | 452 | |
| | 453 | #ifdef BACKEND_8BIT |
| | 454 | _scr->plotYUV(_lut, width, height, dat); |
| | 455 | #else |
| | 456 | plotYUV(width, height, dat); |
| | 457 | #endif |
| | 458 | } |
| | 459 | |
| | 460 | OverlayColor *AnimationState::giveRgbBuffer(void) { |
| | 461 | #ifdef BACKEND_8BIT |
| | 462 | return NULL; |
| | 463 | #else |
| | 464 | return _overlay; |
| | 465 | #endif |
| | 466 | } |
| | 467 | |
| | 468 | Audio::AudioStream *AnimationState::createAudioStream(const char *name, void *arg) { |
| | 469 | if (arg) |
| | 470 | return (Audio::AudioStream*)arg; |
| | 471 | else |
| | 472 | return Audio::AudioStream::openStreamFile(name); |
| | 473 | } |
| | 474 | |
| | 475 | #endif |
| | 476 | |
| | 477 | /////////////////////////////////////////////////////////////////////////////// |
| | 478 | // Factory function for creating the appropriate cutscene player |
| | 479 | /////////////////////////////////////////////////////////////////////////////// |
| | 480 | |
| | 481 | MoviePlayer *makeMoviePlayer(uint32 id, Screen *scr, Audio::Mixer *snd, OSystem *sys) { |
| | 482 | #if defined(USE_ZLIB) || defined(USE_MPEG2) |
| | 483 | char filename[20]; |
| | 484 | #endif |
| | 485 | |
| | 486 | #ifdef USE_ZLIB |
| | 487 | snprintf(filename, sizeof(filename), "%s.dxa", sequenceList[id]); |
| | 488 | |
| | 489 | if (Common::File::exists(filename)) { |
| | 490 | return new MoviePlayerDXA(scr, snd, sys); |
| | 491 | } |
| | 492 | #endif |
| | 493 | |
| | 494 | #ifdef USE_MPEG2 |
| | 495 | snprintf(filename, sizeof(filename), "%s.mp2", sequenceList[id]); |
| | 496 | |
| | 497 | if (Common::File::exists(filename)) { |
| | 498 | return new MoviePlayerMPEG(scr, snd, sys); |
| | 499 | } |
| | 500 | #endif |
| | 501 | |
| | 502 | return NULL; |
| | 503 | } |
| | 504 | |