aboutsummaryrefslogtreecommitdiff
path: root/sword1
diff options
context:
space:
mode:
authorJames Brown2004-01-18 05:52:04 +0000
committerJames Brown2004-01-18 05:52:04 +0000
commitad46828d1c8fb68c3c44c5c38c5ac9b2031a2fc9 (patch)
tree4253ac14e5934508d7a455cafdf1fec88d0af866 /sword1
parenta95818d29a706095517ada079f316ad74f20a86d (diff)
downloadscummvm-rg350-ad46828d1c8fb68c3c44c5c38c5ac9b2031a2fc9.tar.gz
scummvm-rg350-ad46828d1c8fb68c3c44c5c38c5ac9b2031a2fc9.tar.bz2
scummvm-rg350-ad46828d1c8fb68c3c44c5c38c5ac9b2031a2fc9.zip
BS1 cutscene support. Also bugfixes (don't crash if cutscene ogg unavailable)
svn-id: r12465
Diffstat (limited to 'sword1')
-rw-r--r--sword1/animation.cpp389
-rw-r--r--sword1/animation.h144
-rw-r--r--sword1/logic.cpp36
-rw-r--r--sword1/logic.h5
-rw-r--r--sword1/module.mk1
-rw-r--r--sword1/screen.cpp36
-rw-r--r--sword1/screen.h6
-rw-r--r--sword1/sword1.cpp2
8 files changed, 615 insertions, 4 deletions
diff --git a/sword1/animation.cpp b/sword1/animation.cpp
new file mode 100644
index 0000000000..1533dd5e74
--- /dev/null
+++ b/sword1/animation.cpp
@@ -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
diff --git a/sword1/animation.h b/sword1/animation.h
new file mode 100644
index 0000000000..bfbbd11e13
--- /dev/null
+++ b/sword1/animation.h
@@ -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
diff --git a/sword1/logic.cpp b/sword1/logic.cpp
index 177e4e63c8..8e1c24edbe 100644
--- a/sword1/logic.cpp
+++ b/sword1/logic.cpp
@@ -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 */
diff --git a/sword1/logic.h b/sword1/logic.h
index c49d12092b..3d3fc47288 100644
--- a/sword1/logic.h
+++ b/sword1/logic.h
@@ -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;
diff --git a/sword1/module.mk b/sword1/module.mk
index f67dd6fac2..686ed9008f 100644
--- a/sword1/module.mk
+++ b/sword1/module.mk
@@ -1,6 +1,7 @@
MODULE := sword1
MODULE_OBJS := \
+ sword1/animation.o \
sword1/control.o \
sword1/debug.o \
sword1/eventman.o \
diff --git a/sword1/screen.cpp b/sword1/screen.cpp
index 400aa6a9c6..c5c1dd80ac 100644
--- a/sword1/screen.cpp
+++ b/sword1/screen.cpp
@@ -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
diff --git a/sword1/screen.h b/sword1/screen.h
index 3c7326e8f4..569b1fccb2 100644
--- a/sword1/screen.h
+++ b/sword1/screen.h
@@ -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);
diff --git a/sword1/sword1.cpp b/sword1/sword1.cpp
index 1d16a746ad..a59025521c 100644
--- a/sword1/sword1.cpp
+++ b/sword1/sword1.cpp
@@ -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");