2004-01-13 01:26:18 +00:00
|
|
|
/* ScummVM - Scumm Interpreter
|
|
|
|
* Copyright (C) 2004 The ScummVM project
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* $Header$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2004-01-12 11:11:19 +00:00
|
|
|
#include "common/stdafx.h"
|
|
|
|
#include "sword2/sword2.h"
|
|
|
|
#include "sword2/driver/menu.h"
|
|
|
|
#include "sword2/driver/render.h"
|
|
|
|
|
|
|
|
#include "common/file.h"
|
|
|
|
|
|
|
|
namespace Sword2 {
|
|
|
|
|
|
|
|
// Build 'Best-Match' RGB lookup table
|
2004-01-13 01:26:18 +00:00
|
|
|
void AnimationState::buildLookup(int p, int lines) {
|
2004-01-12 11:11:19 +00:00
|
|
|
int y, cb;
|
|
|
|
int r, g, b, ii;
|
|
|
|
|
|
|
|
|
2004-01-13 01:26:18 +00:00
|
|
|
if (p != curpal) {
|
|
|
|
curpal = p;
|
|
|
|
cr = 0;
|
|
|
|
pos = 0;
|
2004-01-12 11:11:19 +00:00
|
|
|
}
|
|
|
|
|
2004-01-13 01:26:18 +00:00
|
|
|
if (cr >= BITDEPTH)
|
2004-01-12 11:11:19 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
for (ii = 0; ii < lines; ii++) {
|
2004-01-13 01:26:18 +00:00
|
|
|
r = (-16*256 + (int)(256*1.596) * ((cr<<SHIFT)-128)) / 256;
|
2004-01-12 11:11:19 +00:00
|
|
|
for (cb = 0; cb < BITDEPTH; cb++) {
|
2004-01-13 01:26:18 +00:00
|
|
|
g = (-16*256 - (int)(0.813*256) * ((cr<<SHIFT)-128) - (int)(0.391*256) * ((cb<<SHIFT)-128)) / 256;
|
2004-01-12 11:11:19 +00:00
|
|
|
b = (-16*256 + (int)(2.018*256) * ((cb<<SHIFT)-128)) / 256;
|
|
|
|
|
|
|
|
for (y = 0; y < BITDEPTH; y++) {
|
|
|
|
int idx, bst = 0;
|
2004-01-13 01:26:18 +00:00
|
|
|
int dis = 2*SQR(r-palettes[p].pal[0])+4*SQR(g-palettes[p].pal[1])+SQR(b-palettes[p].pal[2]);
|
2004-01-12 11:11:19 +00:00
|
|
|
|
|
|
|
for (idx = 1; idx < 256; idx++) {
|
2004-01-13 01:26:18 +00:00
|
|
|
long d2 = 2*SQR(r-palettes[p].pal[4*idx])+4*SQR(g-palettes[p].pal[4*idx+1])+SQR(b-palettes[p].pal[4*idx+2]);
|
2004-01-12 11:11:19 +00:00
|
|
|
if (d2 < dis) {
|
|
|
|
bst = idx;
|
|
|
|
dis = d2;
|
2004-01-13 01:26:18 +00:00
|
|
|
}
|
2004-01-12 11:11:19 +00:00
|
|
|
}
|
2004-01-13 01:26:18 +00:00
|
|
|
lut2[pos++] = bst;
|
|
|
|
|
|
|
|
r += (1 << SHIFT);
|
|
|
|
g += (1 << SHIFT);
|
|
|
|
b += (1 << SHIFT);
|
2004-01-12 11:11:19 +00:00
|
|
|
}
|
2004-01-13 01:26:18 +00:00
|
|
|
r -= 256;
|
2004-01-12 11:11:19 +00:00
|
|
|
}
|
2004-01-13 01:26:18 +00:00
|
|
|
cr++;
|
|
|
|
if (cr >= BITDEPTH)
|
|
|
|
return;
|
2004-01-12 11:11:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MoviePlayer::checkPaletteSwitch(AnimationState * st) {
|
|
|
|
// if we have reached the last image with this palette, switch to new one
|
|
|
|
if (st->framenum == st->palettes[st->palnum].end) {
|
|
|
|
unsigned char *l = st->lut2;
|
|
|
|
st->palnum++;
|
|
|
|
_vm->_graphics->setPalette(0, 256, st->palettes[st->palnum].pal, RDPAL_INSTANT);
|
|
|
|
st->lutcalcnum = (BITDEPTH + st->palettes[st->palnum].end - (st->framenum + 1) + 2) / (st->palettes[st->palnum].end - (st->framenum + 1) + 2);
|
|
|
|
st->lut2 = st->lut;
|
|
|
|
st->lut = l;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef USE_MPEG2
|
2004-01-13 01:26:18 +00:00
|
|
|
bool MoviePlayer::decodeFrame(AnimationState * st) {
|
2004-01-12 11:11:19 +00:00
|
|
|
// Dummy for MPEG2-less builds
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#else
|
2004-01-13 01:26:18 +00:00
|
|
|
bool MoviePlayer::decodeFrame(AnimationState * st) {
|
2004-01-12 11:11:19 +00:00
|
|
|
mpeg2_state_t state;
|
|
|
|
const mpeg2_sequence_t *sequence_i;
|
|
|
|
size_t size = (size_t)-1;
|
|
|
|
|
|
|
|
do {
|
|
|
|
state = mpeg2_parse (st->decoder);
|
|
|
|
sequence_i = st->info->sequence;
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case STATE_BUFFER:
|
|
|
|
size = st->mpgfile->read(st->buffer, BUFFER_SIZE);
|
|
|
|
mpeg2_buffer (st->decoder, st->buffer, st->buffer + size);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_SLICE:
|
|
|
|
case STATE_END:
|
|
|
|
if (st->info->display_fbuf) {
|
|
|
|
checkPaletteSwitch(st);
|
|
|
|
_vm->_graphics->plotYUV(st->lut, sequence_i->width, sequence_i->height, st->info->display_fbuf->buf);
|
|
|
|
st->framenum++;
|
2004-01-13 01:26:18 +00:00
|
|
|
st->buildLookup(st->palnum+1, st->lutcalcnum);
|
2004-01-12 11:11:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2004-01-13 01:26:18 +00:00
|
|
|
break;
|
2004-01-12 11:11:19 +00:00
|
|
|
}
|
|
|
|
} while (size);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef USE_MPEG2
|
2004-01-13 01:26:18 +00:00
|
|
|
AnimationState *MoviePlayer::initAnimation(const char *name) {
|
2004-01-12 11:11:19 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
2004-01-13 01:26:18 +00:00
|
|
|
AnimationState *MoviePlayer::initAnimation(const char *name) {
|
2004-01-12 11:11:19 +00:00
|
|
|
char basename[512], tempFile[512];
|
|
|
|
AnimationState *st = new AnimationState;
|
|
|
|
int i, p;
|
|
|
|
|
|
|
|
strcpy(basename, name);
|
|
|
|
basename[strlen(basename)-4] = 0;
|
|
|
|
|
|
|
|
// Load lookup palettes
|
|
|
|
// TODO: Binary format so we can use File class
|
|
|
|
sprintf(tempFile, "%s/%s.pal", _vm->getGameDataPath(), basename);
|
|
|
|
FILE *f = fopen(tempFile, "r");
|
|
|
|
|
|
|
|
if (!f) {
|
|
|
|
warning("Cutscene: %s.pal palette missing", basename);
|
|
|
|
return 0;
|
2004-01-13 01:26:18 +00:00
|
|
|
}
|
2004-01-12 11:11:19 +00:00
|
|
|
|
|
|
|
p = 0;
|
|
|
|
while (!feof(f)) {
|
|
|
|
fscanf(f, "%i %i", &st->palettes[p].end, &st->palettes[p].cnt);
|
|
|
|
for (i = 0; i < st->palettes[p].cnt; i++) {
|
2004-01-13 01:26:18 +00:00
|
|
|
int r, g, b;
|
|
|
|
fscanf(f, "%i", &r);
|
|
|
|
fscanf(f, "%i", &g);
|
|
|
|
fscanf(f, "%i", &b);
|
|
|
|
st->palettes[p].pal[4*i] = r;
|
|
|
|
st->palettes[p].pal[4*i+1] = g;
|
|
|
|
st->palettes[p].pal[4*i+2] = b;
|
2004-01-12 11:11:19 +00:00
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
st->palnum = 0;
|
|
|
|
_vm->_graphics->setPalette(0, 256, st->palettes[st->palnum].pal, RDPAL_INSTANT);
|
|
|
|
st->lut = st->lut2 = st->lookup[0];
|
|
|
|
st->curpal = -1;
|
|
|
|
st->cr = 0;
|
2004-01-13 01:26:18 +00:00
|
|
|
st->buildLookup(st->palnum, 256);
|
2004-01-12 11:11:19 +00:00
|
|
|
st->lut2 = st->lookup[1];
|
|
|
|
|
|
|
|
// Open MPEG2 stream
|
|
|
|
st->mpgfile = new File();
|
|
|
|
sprintf(tempFile, "%s.mp2", basename);
|
|
|
|
if (!st->mpgfile->open(tempFile)) {
|
|
|
|
warning("Cutscene: Could not open %s", tempFile);
|
|
|
|
delete st;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load and configure decoder
|
|
|
|
st->decoder = mpeg2_init ();
|
|
|
|
if (st->decoder == NULL) {
|
|
|
|
warning("Cutscene: Could not allocate an MPEG2 decoder");
|
|
|
|
delete st;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
st->info = mpeg2_info(st->decoder);
|
|
|
|
st->framenum = 0;
|
|
|
|
|
|
|
|
// Load in palette data
|
|
|
|
st->lutcalcnum = (BITDEPTH + st->palettes[st->palnum].end + 2) / (st->palettes[st->palnum].end + 2);
|
|
|
|
|
|
|
|
|
|
|
|
/* Play audio - TODO: Sync with video?*/
|
2004-01-13 01:26:18 +00:00
|
|
|
// Another TODO: There is no reason that this only allows OGG, and not MP3, or any other format
|
|
|
|
// the mixer might support one day... is there?
|
2004-01-12 11:11:19 +00:00
|
|
|
File *sndFile = new File;
|
|
|
|
sprintf(tempFile, "%s.ogg", basename);
|
|
|
|
if (sndFile->open(tempFile))
|
|
|
|
_vm->_mixer->playVorbis(&st->bgSound, sndFile, 100000000);
|
|
|
|
|
2004-01-13 01:26:18 +00:00
|
|
|
// FIXME: This leaks (sndFile will never be deleted)
|
|
|
|
|
2004-01-12 11:11:19 +00:00
|
|
|
return st;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef USE_MPEG2
|
2004-01-13 01:26:18 +00:00
|
|
|
void MoviePlayer::doneAnimation(AnimationState *st) {
|
2004-01-12 11:11:19 +00:00
|
|
|
}
|
|
|
|
#else
|
2004-01-13 01:26:18 +00:00
|
|
|
void MoviePlayer::doneAnimation(AnimationState *st) {
|
2004-01-12 11:11:19 +00:00
|
|
|
_vm->_mixer->stopHandle(st->bgSound);
|
|
|
|
|
|
|
|
mpeg2_close (st->decoder);
|
|
|
|
st->mpgfile->close();
|
|
|
|
delete st->mpgfile;
|
|
|
|
delete st;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
} // End of namespace Sword2
|