mirror of
https://github.com/libretro/scummvm.git
synced 2024-11-30 21:00:39 +00:00
BS1 cutscene support. Also bugfixes (don't crash if cutscene ogg unavailable)
svn-id: r12465
This commit is contained in:
parent
a95818d29a
commit
ad46828d1c
2
NEWS
2
NEWS
@ -3,7 +3,7 @@ For a more comprehensive changelog for the latest experimental CVS code, see:
|
||||
|
||||
0.5.7(CVS) (2003-??-??)
|
||||
New Games:
|
||||
- Added Broken Sword 1 engine, Cutscene support pending...
|
||||
- Added Broken Sword 1 engine.
|
||||
- Added Broken Sword 2 engine.
|
||||
- Added Flight of the Amazon Queen engine
|
||||
- Added support for V1 SCUMM games 'Maniac Mansion' and 'Zak McKracken'
|
||||
|
1
README
1
README
@ -984,6 +984,7 @@ X.X Credits:
|
||||
Ludvig Strigeus - Original ScummVM and SimonVM author
|
||||
|
||||
Contributors:
|
||||
Andreas Rover - Broken Sword 1/2 MPEG2 cutscene support
|
||||
Quietust - Sound support for Amiga SCUMM V2 - V3 games
|
||||
Stuart Caie - Decoders for Simon 1 Amiga data files
|
||||
Janne Huttunen - V3 actor mask support, Dig/FT Smush audio
|
||||
|
389
sword1/animation.cpp
Normal file
389
sword1/animation.cpp
Normal file
@ -0,0 +1,389 @@
|
||||
/* 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$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stdafx.h"
|
||||
#include "common/file.h"
|
||||
#include "sound/vorbis.h"
|
||||
|
||||
#include "sword1/animation.h"
|
||||
|
||||
namespace Sword1 {
|
||||
|
||||
AnimationState::AnimationState(Screen *scr, SoundMixer *snd, OSystem *sys)
|
||||
: _scr(scr), _snd(snd), _sys(sys) {
|
||||
}
|
||||
|
||||
AnimationState::~AnimationState() {
|
||||
#ifdef USE_MPEG2
|
||||
_snd->stopHandle(bgSound);
|
||||
if (decoder)
|
||||
mpeg2_close(decoder);
|
||||
delete mpgfile;
|
||||
delete sndfile;
|
||||
#ifndef BACKEND_8BIT
|
||||
_sys->hide_overlay();
|
||||
delete overlay;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool AnimationState::init(const char *basename) {
|
||||
#ifdef USE_MPEG2
|
||||
|
||||
char tempFile[512];
|
||||
|
||||
decoder = NULL;
|
||||
mpgfile = NULL;
|
||||
sndfile = NULL;
|
||||
bgSoundStream = NULL;
|
||||
|
||||
#ifdef BACKEND_8BIT
|
||||
|
||||
int i, p;
|
||||
|
||||
// Load lookup palettes
|
||||
// TODO: Binary format so we can use File class
|
||||
sprintf(tempFile, "%s.pal", basename);
|
||||
FILE *f = fopen(tempFile, "r");
|
||||
|
||||
if (!f) {
|
||||
warning("Cutscene: %s.pal palette missing", basename);
|
||||
return false;
|
||||
}
|
||||
|
||||
p = 0;
|
||||
while (!feof(f)) {
|
||||
if (fscanf(f, "%i %i", &palettes[p].end, &palettes[p].cnt) != 2)
|
||||
break;
|
||||
for (i = 0; i < palettes[p].cnt; i++) {
|
||||
int r, g, b;
|
||||
fscanf(f, "%i", &r);
|
||||
fscanf(f, "%i", &g);
|
||||
fscanf(f, "%i", &b);
|
||||
palettes[p].pal[4 * i] = r;
|
||||
palettes[p].pal[4 * i + 1] = g;
|
||||
palettes[p].pal[4 * i + 2] = b;
|
||||
palettes[p].pal[4 * i + 3] = 0;
|
||||
}
|
||||
for (; i < 256; i++) {
|
||||
palettes[p].pal[4 * i] = 0;
|
||||
palettes[p].pal[4 * i + 1] = 0;
|
||||
palettes[p].pal[4 * i + 2] = 0;
|
||||
palettes[p].pal[4 * i + 3] = 0;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
palnum = 0;
|
||||
maxPalnum = p;
|
||||
_sys->set_palette(palettes[palnum].pal, 0, 256);
|
||||
lut = lut2 = lookup[0];
|
||||
curpal = -1;
|
||||
cr = 0;
|
||||
buildLookup(palnum, 256);
|
||||
lut2 = lookup[1];
|
||||
lutcalcnum = (BITDEPTH + palettes[palnum].end + 2) / (palettes[palnum].end + 2);
|
||||
#else
|
||||
buildLookup2();
|
||||
overlay = (NewGuiColor*)calloc(640 * 400, sizeof(NewGuiColor));
|
||||
_sys->show_overlay();
|
||||
#endif
|
||||
|
||||
// Open MPEG2 stream
|
||||
mpgfile = new File();
|
||||
sprintf(tempFile, "%s.mp2", basename);
|
||||
if (!mpgfile->open(tempFile)) {
|
||||
warning("Cutscene: Could not open %s", tempFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load and configure decoder
|
||||
decoder = mpeg2_init();
|
||||
if (decoder == NULL) {
|
||||
warning("Cutscene: Could not allocate an MPEG2 decoder");
|
||||
return false;
|
||||
}
|
||||
|
||||
info = mpeg2_info(decoder);
|
||||
framenum = 0;
|
||||
ticks = _sys->get_msecs();
|
||||
|
||||
/* Play audio - TODO: Sync with video?*/
|
||||
|
||||
#ifdef USE_VORBIS
|
||||
// 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?
|
||||
sndfile = new File;
|
||||
sprintf(tempFile, "%s.ogg", basename);
|
||||
if (sndfile->open(tempFile)) {
|
||||
bgSoundStream = makeVorbisStream(sndfile, sndfile->size());
|
||||
_snd->playInputStream(&bgSound, bgSoundStream, false, 255, 0, -1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return true;
|
||||
#else /* USE_MPEG2 */
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef BACKEND_8BIT
|
||||
/**
|
||||
* Build 'Best-Match' RGB lookup table
|
||||
*/
|
||||
void AnimationState::buildLookup(int p, int lines) {
|
||||
int y, cb;
|
||||
int r, g, b, ii;
|
||||
|
||||
if (p >= maxPalnum)
|
||||
return;
|
||||
|
||||
if (p != curpal) {
|
||||
curpal = p;
|
||||
cr = 0;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
if (cr >= BITDEPTH)
|
||||
return;
|
||||
|
||||
for (ii = 0; ii < lines; ii++) {
|
||||
r = (-16 * 256 + (int) (256 * 1.596) * ((cr << SHIFT) - 128)) / 256;
|
||||
for (cb = 0; cb < BITDEPTH; cb++) {
|
||||
g = (-16 * 256 - (int) (0.813 * 256) * ((cr << SHIFT) - 128) - (int) (0.391 * 256) * ((cb << SHIFT) - 128)) / 256;
|
||||
b = (-16 * 256 + (int) (2.018 * 256) * ((cb << SHIFT) - 128)) / 256;
|
||||
|
||||
for (y = 0; y < BITDEPTH; y++) {
|
||||
int idx, bst = 0;
|
||||
int dis = 2 * SQR(r - palettes[p].pal[0]) + 4 * SQR(g - palettes[p].pal[1]) + SQR(b - palettes[p].pal[2]);
|
||||
|
||||
for (idx = 1; idx < 256; idx++) {
|
||||
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]);
|
||||
if (d2 < dis) {
|
||||
bst = idx;
|
||||
dis = d2;
|
||||
}
|
||||
}
|
||||
lut2[pos++] = bst;
|
||||
|
||||
r += (1 << SHIFT);
|
||||
g += (1 << SHIFT);
|
||||
b += (1 << SHIFT);
|
||||
}
|
||||
r -= 256;
|
||||
}
|
||||
cr++;
|
||||
if (cr >= BITDEPTH)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool AnimationState::checkPaletteSwitch() {
|
||||
// if we have reached the last image with this palette, switch to new one
|
||||
if (framenum == palettes[palnum].end) {
|
||||
unsigned char *l = lut2;
|
||||
palnum++;
|
||||
_sys->set_palette(palettes[palnum].pal, 0, 256);
|
||||
lutcalcnum = (BITDEPTH + palettes[palnum].end - (framenum + 1) + 2) / (palettes[palnum].end - (framenum + 1) + 2);
|
||||
lut2 = lut;
|
||||
lut = l;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool AnimationState::lookupInit = false;
|
||||
NewGuiColor AnimationState::lookup2[BITDEPTH * BITDEPTH * 256];
|
||||
|
||||
void AnimationState::buildLookup2() {
|
||||
|
||||
if (lookupInit) return;
|
||||
lookupInit = true;
|
||||
|
||||
int y, cb, cr;
|
||||
int r, g, b;
|
||||
int pos = 0;
|
||||
|
||||
for (cr = 0; cr < BITDEPTH; cr++) {
|
||||
for (cb = 0; cb < BITDEPTH; cb++) {
|
||||
for (y = 0; y < 256; y++) {
|
||||
r = ((y-16) * 256 + (int) (256 * 1.596) * ((cr << SHIFT) - 128)) / 256;
|
||||
g = ((y-16) * 256 - (int) (0.813 * 256) * ((cr << SHIFT) - 128) - (int) (0.391 * 256) * ((cb << SHIFT) - 128)) / 256;
|
||||
b = ((y-16) * 256 + (int) (2.018 * 256) * ((cb << SHIFT) - 128)) / 256;
|
||||
|
||||
if (r < 0) r = 0;
|
||||
if (r > 255) r = 255;
|
||||
if (g < 0) g = 0;
|
||||
if (g > 255) g = 255;
|
||||
if (b < 0) b = 0;
|
||||
if (b > 255) b = 255;
|
||||
|
||||
lookup2[pos++] = _sys->RGBToColor(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationState::plotYUV(NewGuiColor *lut, int width, int height, byte *const *dat) {
|
||||
|
||||
NewGuiColor *ptr = overlay + (400-height)/2 * 640 + (640-width)/2;
|
||||
|
||||
int x, y;
|
||||
|
||||
int ypos = 0;
|
||||
int cpos = 0;
|
||||
int linepos = 0;
|
||||
|
||||
for (y = 0; y < height; y += 2) {
|
||||
for (x = 0; x < width; x += 2) {
|
||||
int i = ((((dat[2][cpos] + ROUNDADD) >> SHIFT) * BITDEPTH) + ((dat[1][cpos] + ROUNDADD)>>SHIFT)) * 256;
|
||||
cpos++;
|
||||
|
||||
ptr[linepos ] = lut[i + dat[0][ ypos ]];
|
||||
ptr[640 + linepos++] = lut[i + dat[0][width + ypos++]];
|
||||
ptr[linepos ] = lut[i + dat[0][ ypos ]];
|
||||
ptr[640 + linepos++] = lut[i + dat[0][width + ypos++]];
|
||||
|
||||
}
|
||||
linepos += (2 * 640 - width);
|
||||
ypos += width;
|
||||
}
|
||||
|
||||
_sys->copy_rect_overlay(overlay, 640, 0, 40, 640, 400);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool AnimationState::decodeFrame() {
|
||||
#ifdef USE_MPEG2
|
||||
mpeg2_state_t state;
|
||||
const mpeg2_sequence_t *sequence_i;
|
||||
size_t size = (size_t) -1;
|
||||
|
||||
do {
|
||||
state = mpeg2_parse(decoder);
|
||||
sequence_i = info->sequence;
|
||||
|
||||
switch (state) {
|
||||
case STATE_BUFFER:
|
||||
size = mpgfile->read(buffer, BUFFER_SIZE);
|
||||
mpeg2_buffer(decoder, buffer, buffer + size);
|
||||
break;
|
||||
|
||||
case STATE_SLICE:
|
||||
case STATE_END:
|
||||
if (info->display_fbuf) {
|
||||
/* simple audio video sync code:
|
||||
* we calculate the actual frame by taking the delivered audio samples
|
||||
* we add 2 frames as the number of samples delivered is higher than the
|
||||
* number actually played due to buffering
|
||||
*
|
||||
* we then try to stay inside +- 1 frame of this calculated frame number by
|
||||
* dropping frames if we run behind and delaying if we are too fast
|
||||
*/
|
||||
|
||||
#ifdef BACKEND_8BIT
|
||||
if (checkPaletteSwitch() || (bgSoundStream == 0) ||
|
||||
(bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < (framenum+3)){
|
||||
_scr->plotYUV(lut, sequence_i->width, sequence_i->height, info->display_fbuf->buf);
|
||||
|
||||
if (bgSoundStream) {
|
||||
while ((bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < framenum+1);
|
||||
_sys->delay_msecs(10);
|
||||
} else {
|
||||
ticks += 83;
|
||||
while (_sys->get_msecs() < ticks)
|
||||
_sys->delay_msecs(10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else
|
||||
printf("dropped frame %i\n", framenum);
|
||||
|
||||
buildLookup(palnum + 1, lutcalcnum);
|
||||
|
||||
#else
|
||||
|
||||
if ((bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < (framenum+3)){
|
||||
plotYUV(lookup2, sequence_i->width, sequence_i->height, info->display_fbuf->buf);
|
||||
|
||||
if (bgSoundStream) {
|
||||
while ((bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < framenum+1);
|
||||
_sys->delay_msecs(10);
|
||||
} else {
|
||||
ticks += 83;
|
||||
while (_sys->get_msecs() < ticks)
|
||||
_sys->delay_msecs(10);
|
||||
}
|
||||
|
||||
} else
|
||||
printf("dropped frame %i\n", framenum);
|
||||
|
||||
#endif
|
||||
|
||||
framenum++;
|
||||
return true;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (size);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays an animated cutscene.
|
||||
* @param filename the file name of the cutscene file
|
||||
* @param text the subtitles and voiceovers for the cutscene
|
||||
* @param musicOut lead-out music
|
||||
*/
|
||||
|
||||
void MoviePlayer::play(const char *filename) {
|
||||
#ifdef USE_MPEG2
|
||||
AnimationState *anim = new AnimationState(_scr, _snd, _sys);
|
||||
|
||||
if (anim->init(filename)) {
|
||||
while (anim->decodeFrame()) {
|
||||
#ifndef BACKEND_8BIT
|
||||
_sys->update_screen();
|
||||
#endif
|
||||
// FIXME: check for ESC and abbort animation be just returning from the function
|
||||
}
|
||||
}
|
||||
|
||||
delete anim;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
} // End of namespace Sword2
|
144
sword1/animation.h
Normal file
144
sword1/animation.h
Normal file
@ -0,0 +1,144 @@
|
||||
/* 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$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANIMATION_H
|
||||
#define ANIMATION_H
|
||||
|
||||
// Uncomment this if you are using libmpeg2 0.3.1.
|
||||
// #define USE_MPEG2_0_3_1
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_MPEG2
|
||||
extern "C" {
|
||||
#include <mpeg2dec/mpeg2.h>
|
||||
}
|
||||
|
||||
#ifdef USE_MPEG2_0_3_1
|
||||
typedef int mpeg2_state_t;
|
||||
typedef sequence_t mpeg2_sequence_t;
|
||||
#define STATE_BUFFER -1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "sword1/screen.h"
|
||||
#include "sword1/sound.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
|
||||
namespace Sword1 {
|
||||
|
||||
|
||||
#ifdef BACKEND_8BIT
|
||||
#define SQR(x) ((x) * (x))
|
||||
#define SHIFT 3
|
||||
#else
|
||||
#define SHIFT 1
|
||||
#endif
|
||||
|
||||
#define BITDEPTH (1 << (8 - SHIFT))
|
||||
#define ROUNDADD (1 << (SHIFT - 1))
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
class AnimationState {
|
||||
private:
|
||||
Screen *_scr;
|
||||
SoundMixer *_snd;
|
||||
OSystem *_sys;
|
||||
|
||||
int framenum;
|
||||
uint32 ticks;
|
||||
|
||||
#ifdef USE_MPEG2
|
||||
mpeg2dec_t *decoder;
|
||||
const mpeg2_info_t *info;
|
||||
#endif
|
||||
|
||||
File *mpgfile;
|
||||
File *sndfile;
|
||||
|
||||
byte buffer[BUFFER_SIZE];
|
||||
|
||||
PlayingSoundHandle bgSound;
|
||||
AudioStream *bgSoundStream;
|
||||
|
||||
#ifdef BACKEND_8BIT
|
||||
int palnum;
|
||||
int maxPalnum;
|
||||
|
||||
byte lookup[2][BITDEPTH * BITDEPTH * BITDEPTH];
|
||||
byte *lut;
|
||||
byte *lut2;
|
||||
int lutcalcnum;
|
||||
|
||||
int curpal;
|
||||
int cr;
|
||||
int pos;
|
||||
|
||||
struct {
|
||||
int cnt;
|
||||
int end;
|
||||
byte pal[4 * 256];
|
||||
} palettes[50];
|
||||
#else
|
||||
static NewGuiColor lookup2[BITDEPTH * BITDEPTH * 256];
|
||||
NewGuiColor * overlay;
|
||||
static bool lookupInit;
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
AnimationState(Screen *scr, SoundMixer *snd, OSystem *sys);
|
||||
~AnimationState();
|
||||
|
||||
bool init(const char *name);
|
||||
bool decodeFrame();
|
||||
|
||||
private:
|
||||
|
||||
#ifdef BACKEND_8BIT
|
||||
void buildLookup(int p, int lines);
|
||||
bool checkPaletteSwitch();
|
||||
#else
|
||||
void buildLookup2(void);
|
||||
void plotYUV(NewGuiColor *lut, int width, int height, byte *const *dat);
|
||||
#endif
|
||||
};
|
||||
|
||||
class MoviePlayer {
|
||||
private:
|
||||
Screen *_scr;
|
||||
SoundMixer *_snd;
|
||||
OSystem *_sys;
|
||||
|
||||
public:
|
||||
MoviePlayer(Screen *scr, SoundMixer *snd, OSystem *sys) : _scr(scr), _snd(snd), _sys(sys) {}
|
||||
void play(const char *filename);
|
||||
};
|
||||
|
||||
} // End of namespace Sword2
|
||||
|
||||
#endif
|
@ -32,6 +32,7 @@
|
||||
#include "sword1.h"
|
||||
#include "music.h"
|
||||
#include "swordres.h"
|
||||
#include "animation.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
@ -43,7 +44,7 @@ namespace Sword1 {
|
||||
|
||||
uint32 Logic::_scriptVars[NUM_SCRIPT_VARS];
|
||||
|
||||
Logic::Logic(ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse, Sound *pSound, Music *pMusic, Menu *pMenu) {
|
||||
Logic::Logic(ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse, Sound *pSound, Music *pMusic, Menu *pMenu, OSystem *system, SoundMixer *mixer) {
|
||||
_objMan = pObjMan;
|
||||
_resMan = resMan;
|
||||
_screen = pScreen;
|
||||
@ -55,6 +56,8 @@ Logic::Logic(ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse,
|
||||
_screen->useTextManager(_textMan);
|
||||
_router = new Router(_objMan, _resMan);
|
||||
_eventMan = NULL;
|
||||
_system = system;
|
||||
_mixer = mixer;
|
||||
}
|
||||
|
||||
void Logic::initialize(void) {
|
||||
@ -903,7 +906,36 @@ int Logic::fnSetPaletteToCut(Object *cpt, int32 id, int32 c, int32 d, int32 e, i
|
||||
}
|
||||
|
||||
int Logic::fnPlaySequence(Object *cpt, int32 id, int32 sequenceId, int32 d, int32 e, int32 f, int32 z, int32 x) {
|
||||
warning("fnPlaySequence(%d) called", sequenceId);
|
||||
|
||||
static char *sequence_list[20] = {
|
||||
"ferrari", // 0 CD2 ferrari running down fitz in sc19
|
||||
"ladder", // 1 CD2 george walking down ladder to dig sc24->sc$
|
||||
"steps", // 2 CD2 george walking down steps sc23->sc24
|
||||
"sewer", // 3 CD1 george entering sewer sc2->sc6
|
||||
"intro", // 4 CD1 intro sequence ->sc1
|
||||
"river", // 5 CD1 george being thrown into river by flap & g$
|
||||
"truck", // 6 CD2 truck arriving at bull's head sc45->sc53/4
|
||||
"grave", // 7 BOTH george's grave in scotland, from sc73 + from sc38 $
|
||||
"montfcon", // 8 CD2 monfaucon clue in ireland dig, sc25
|
||||
"tapestry", // 9 CD2 tapestry room beyond spain well, sc61
|
||||
"ireland", // 10 CD2 ireland establishing shot europe_map->sc19
|
||||
"finale", // 11 CD2 grand finale at very end, from sc73
|
||||
"history", // 12 CD1 George's history lesson from Nico, in sc10
|
||||
"spanish", // 13 CD2 establishing shot for 1st visit to Spain, europe_m$
|
||||
"well", // 14 CD2 first time being lowered down well in Spai$
|
||||
"candle", // 15 CD2 Candle burning down in Spain mausoleum sc59
|
||||
"geodrop", // 16 CD2 from sc54, George jumping down onto truck
|
||||
"vulture", // 17 CD2 from sc54, vultures circling George's dead body
|
||||
"enddemo", // 18 --- for end of single CD demo
|
||||
"credits", // 19 CD2 credits, to follow "finale" sequence
|
||||
// etc.
|
||||
};
|
||||
|
||||
warning("fnPlaySequence(%d) called", sequenceId);
|
||||
MoviePlayer player(_screen, _mixer, _system);
|
||||
|
||||
player.play(sequence_list[sequenceId]);
|
||||
|
||||
//_scriptVars[NEW_PALETTE] = 1;
|
||||
/* the logic usually calls fnFadeDown before playing the sequence, so we have to
|
||||
set NEW_PALETTE now to force a palette refresh */
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "sworddefs.h"
|
||||
#include "objectman.h"
|
||||
#include "common/util.h"
|
||||
#include "sound/mixer.h"
|
||||
|
||||
namespace Sword1 {
|
||||
|
||||
@ -46,7 +47,7 @@ typedef int (Logic::*BSMcodeTable)(Object *, int32, int32, int32, int32, int32,
|
||||
|
||||
class Logic {
|
||||
public:
|
||||
Logic(ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse, Sound *pSound, Music *pMusic, Menu *pMenu);
|
||||
Logic(ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse, Sound *pSound, Music *pMusic, Menu *pMenu, OSystem *system, SoundMixer *mixer);
|
||||
~Logic(void);
|
||||
void initialize(void);
|
||||
void newScreen(uint32 screen);
|
||||
@ -66,6 +67,8 @@ public:
|
||||
int cfnPresetScript (Object *cpt, int32 id, int32 c, int32 d, int32 e, int32 f, int32 z, int32 x);
|
||||
private:
|
||||
ObjectMan *_objMan;
|
||||
OSystem *_system;
|
||||
SoundMixer *_mixer;
|
||||
ResMan *_resMan;
|
||||
Screen *_screen;
|
||||
Sound *_sound;
|
||||
|
@ -1,6 +1,7 @@
|
||||
MODULE := sword1
|
||||
|
||||
MODULE_OBJS := \
|
||||
sword1/animation.o \
|
||||
sword1/control.o \
|
||||
sword1/debug.o \
|
||||
sword1/eventman.o \
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "system.h"
|
||||
#include "menu.h"
|
||||
#include "sword1.h"
|
||||
#include "animation.h"
|
||||
|
||||
namespace Sword1 {
|
||||
|
||||
@ -925,4 +926,39 @@ void Screen::drawLine(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BACKEND_8BIT
|
||||
void Screen::plotYUV(byte *lut, int width, int height, byte *const *dat) {
|
||||
|
||||
byte * buf = (uint8*)malloc(width * height);
|
||||
|
||||
int x, y;
|
||||
|
||||
int ypos = 0;
|
||||
int cpos = 0;
|
||||
int linepos = 0;
|
||||
|
||||
for (y = 0; y < height; y += 2) {
|
||||
for (x = 0; x < width; x += 2) {
|
||||
int i = ((((dat[2][cpos] + ROUNDADD) >> SHIFT) * BITDEPTH) + ((dat[1][cpos] + ROUNDADD)>>SHIFT)) * BITDEPTH;
|
||||
cpos++;
|
||||
|
||||
buf[linepos ] = lut[i + ((dat[0][ ypos ] + ROUNDADD) >> SHIFT)];
|
||||
buf[width + linepos++] = lut[i + ((dat[0][width + ypos++] + ROUNDADD) >> SHIFT)];
|
||||
buf[linepos ] = lut[i + ((dat[0][ ypos ] + ROUNDADD) >> SHIFT)];
|
||||
buf[width + linepos++] = lut[i + ((dat[0][width + ypos++] + ROUNDADD) >> SHIFT)];
|
||||
}
|
||||
linepos += (2 * width - width);
|
||||
ypos += width;
|
||||
}
|
||||
|
||||
_system->copy_rect(buf, width, (640-width)/2, (480-height)/2, width, height);
|
||||
_system->update_screen();
|
||||
|
||||
free(buf);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
} // End of namespace Sword1
|
||||
|
@ -91,6 +91,12 @@ public:
|
||||
void fnFlash(uint8 color);
|
||||
void fnBorder(uint8 color);
|
||||
|
||||
#ifdef BACKEND_8BIT
|
||||
void plotYUV(byte *lut, int width, int height, byte *const *dat);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
private:
|
||||
// for router debugging
|
||||
void drawLine(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
|
||||
|
@ -110,7 +110,7 @@ void SwordEngine::initialize(void) {
|
||||
_music = new Music(_system, _mixer);
|
||||
_sound = new Sound("", _mixer, _resMan);
|
||||
_menu = new Menu(_screen, _mouse);
|
||||
_logic = new Logic(_objectMan, _resMan, _screen, _mouse, _sound, _music, _menu);
|
||||
_logic = new Logic(_objectMan, _resMan, _screen, _mouse, _sound, _music, _menu, _system, _mixer);
|
||||
_mouse->useLogicAndMenu(_logic, _menu);
|
||||
|
||||
uint8 musicVol = (uint8)ConfMan.getInt("music_volume");
|
||||
|
@ -132,6 +132,7 @@ bool AnimationState::init(const char *name) {
|
||||
|
||||
info = mpeg2_info(decoder);
|
||||
framenum = 0;
|
||||
ticks = _vm->_system->get_msecs();
|
||||
|
||||
/* Play audio - TODO: Sync with video?*/
|
||||
|
||||
@ -316,12 +317,18 @@ bool AnimationState::decodeFrame() {
|
||||
*/
|
||||
|
||||
#ifdef BACKEND_8BIT
|
||||
if (checkPaletteSwitch() ||
|
||||
(bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < (framenum+3)){
|
||||
if (checkPaletteSwitch() || (bgSoundStream == NULL) ||
|
||||
(bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < (framenum+3)){
|
||||
|
||||
_vm->_graphics->plotYUV(lut, sequence_i->width, sequence_i->height, info->display_fbuf->buf);
|
||||
|
||||
while ((bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < framenum+1);
|
||||
_vm->_system->delay_msecs(10);
|
||||
if (bgSoundStream) {
|
||||
while ((bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < framenum+1);
|
||||
_vm->_system->delay_msecs(10);
|
||||
} else {
|
||||
ticks += 83;
|
||||
_vm->sleepUntil(ticks);
|
||||
}
|
||||
|
||||
_vm->_graphics->setNeedFullRedraw();
|
||||
|
||||
@ -332,11 +339,18 @@ bool AnimationState::decodeFrame() {
|
||||
|
||||
#else
|
||||
|
||||
if ((bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < (framenum+3)){
|
||||
if ((bgSoundStream == NULL) ||
|
||||
(bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < (framenum+3)){
|
||||
|
||||
plotYUV(lookup2, sequence_i->width, sequence_i->height, info->display_fbuf->buf);
|
||||
|
||||
while ((bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < framenum+1);
|
||||
_vm->_system->delay_msecs(10);
|
||||
if (bgSoundStream) {
|
||||
while ((bgSoundStream->getSamplesPlayed()*12/bgSoundStream->getRate()) < framenum+1);
|
||||
_vm->_system->delay_msecs(10);
|
||||
} else {
|
||||
ticks += 83;
|
||||
_vm->sleepUntil(ticks);
|
||||
}
|
||||
|
||||
} else
|
||||
printf("dropped frame %i\n", framenum);
|
||||
|
@ -70,6 +70,7 @@ private:
|
||||
Sword2Engine *_vm;
|
||||
|
||||
int framenum;
|
||||
int ticks;
|
||||
|
||||
#ifdef USE_MPEG2
|
||||
mpeg2dec_t *decoder;
|
||||
|
Loading…
Reference in New Issue
Block a user