aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoruruk2014-04-29 09:50:40 +0200
committeruruk2014-04-29 09:50:40 +0200
commitec71f936280496d349310ea0091dbe26b90ae540 (patch)
treec82e841ab69dcec31fd74ba87f5bc88b7f25ae32
parent258d7ea535c2891bed4132e649c66fb86967a2a0 (diff)
downloadscummvm-rg350-ec71f936280496d349310ea0091dbe26b90ae540.tar.gz
scummvm-rg350-ec71f936280496d349310ea0091dbe26b90ae540.tar.bz2
scummvm-rg350-ec71f936280496d349310ea0091dbe26b90ae540.zip
CGE2: Add parts of the graphics code.
-rw-r--r--engines/cge2/bitmap.cpp369
-rw-r--r--engines/cge2/bitmap.h87
-rw-r--r--engines/cge2/cge2.cpp44
-rw-r--r--engines/cge2/cge2.h18
-rw-r--r--engines/cge2/general.h43
-rw-r--r--engines/cge2/module.mk4
-rw-r--r--engines/cge2/vga13h.cpp1016
-rw-r--r--engines/cge2/vga13h.h243
8 files changed, 1823 insertions, 1 deletions
diff --git a/engines/cge2/bitmap.cpp b/engines/cge2/bitmap.cpp
new file mode 100644
index 0000000000..77c7eb9c41
--- /dev/null
+++ b/engines/cge2/bitmap.cpp
@@ -0,0 +1,369 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "cge2/bitmap.h"
+#include "cge2/cge2.h"
+#include "cge2/vga13h.h"
+//#include "cge/cge_main.h"
+#include "common/system.h"
+#include "common/debug.h"
+#include "common/debug-channels.h"
+
+namespace CGE2 {
+
+Bitmap::Bitmap(CGE2Engine *vm, const char *fname) : _m(NULL), _v(NULL), _map(0), _vm(vm) {
+ char pat[kMaxPath];
+ forceExt(pat, fname, ".VBM");
+
+ if (_vm->_resman->exist(pat)) {
+ EncryptedStream file(_vm, pat);
+ if (file.err())
+ error("Unable to find VBM [%s]", fname);
+ if (!loadVBM(&file))
+ error("Bad VBM [%s]", fname);
+ } else {
+ error("Bad VBM [%s]", fname);
+ }
+}
+
+Bitmap::Bitmap(CGE2Engine *vm, uint16 w, uint16 h, uint8 *map) : _w(w), _h(h), _m(map), _v(NULL), _map(0), _b(NULL), _vm(vm) {
+ if (map)
+ code();
+}
+
+// following routine creates filled rectangle
+// immediately as VGA video chunks, in near memory as fast as possible,
+// especially for text line real time display
+Bitmap::Bitmap(CGE2Engine *vm, uint16 w, uint16 h, uint8 fill)
+ : _w((w + 3) & ~3), // only full uint32 allowed!
+ _h(h), _m(NULL), _map(0), _b(NULL), _vm(vm) {
+
+ uint16 dsiz = _w >> 2; // data size (1 plane line size)
+ uint16 lsiz = 2 + dsiz + 2; // uint16 for line header, uint16 for gap
+ uint16 psiz = _h * lsiz; // - last gape, but + plane trailer
+ uint8 *v = new uint8[4 * psiz + _h * sizeof(*_b)];// the same for 4 planes
+ // + room for wash table
+ assert(v != NULL);
+
+ WRITE_LE_UINT16(v, (kBmpCPY | dsiz)); // data chunk hader
+ memset(v + 2, fill, dsiz); // data bytes
+ WRITE_LE_UINT16(v + lsiz - 2, (kBmpSKP | ((kScrWidth / 4) - dsiz))); // gap
+
+ // Replicate lines
+ byte *destP;
+ for (destP = v + lsiz; destP < (v + psiz); destP += lsiz)
+ Common::copy(v, v + lsiz, destP);
+
+ WRITE_LE_UINT16(v + psiz - 2, kBmpEOI); // plane trailer uint16
+
+ // Replicate planes
+ for (destP = v + psiz; destP < (v + 4 * psiz); destP += psiz)
+ Common::copy(v, v + psiz, destP);
+
+ HideDesc *b = (HideDesc *)(v + 4 * psiz);
+ b->_skip = (kScrWidth - _w) >> 2;
+ b->_hide = _w >> 2;
+
+ // Replicate across the entire table
+ for (HideDesc *hdP = b + 1; hdP < (b + _h); hdP++)
+ *hdP = *b;
+
+ b->_skip = 0; // fix the first entry
+ _v = v;
+ _b = b;
+}
+
+Bitmap::Bitmap(CGE2Engine *vm, const Bitmap &bmp) : _w(bmp._w), _h(bmp._h), _m(NULL), _v(NULL), _map(0), _b(NULL), _vm(vm) {
+ uint8 *v0 = bmp._v;
+ if (!v0)
+ return;
+
+ uint16 vsiz = (uint8 *)(bmp._b) - (uint8 *)(v0);
+ uint16 siz = vsiz + _h * sizeof(HideDesc);
+ uint8 *v1 = new uint8[siz];
+ assert(v1 != NULL);
+ memcpy(v1, v0, siz);
+ _b = (HideDesc *)((_v = v1) + vsiz);
+}
+
+Bitmap::~Bitmap() {
+ free(_m);
+ delete[] _v;
+}
+
+Bitmap &Bitmap::operator=(const Bitmap &bmp) {
+ if (this == &bmp)
+ return *this;
+
+ uint8 *v0 = bmp._v;
+ _w = bmp._w;
+ _h = bmp._h;
+ _m = NULL;
+ _map = 0;
+ _vm = bmp._vm;
+ delete[] _v;
+
+ if (v0 == NULL) {
+ _v = NULL;
+ } else {
+ uint16 vsiz = (uint8 *)bmp._b - (uint8 *)v0;
+ uint16 siz = vsiz + _h * sizeof(HideDesc);
+ uint8 *v1 = new uint8[siz];
+ assert(v1 != NULL);
+ memcpy(v1, v0, siz);
+ _b = (HideDesc *)((_v = v1) + vsiz);
+ }
+ return *this;
+}
+
+char *Bitmap::forceExt(char *buf, const char *name, const char *ext) {
+ strcpy(buf, name);
+ char *dot = strrchr(buf, '.');
+ if (dot)
+ *dot = '\0';
+ strcat(buf, ext);
+
+ return buf;
+}
+
+BitmapPtr Bitmap::code() {
+ if (!_m)
+ return NULL;
+
+ uint16 cnt;
+
+ if (_v) { // old X-map exists, so remove it
+ delete[] _v;
+ _v = NULL;
+ }
+
+ while (true) { // at most 2 times: for (V == NULL) & for allocated block;
+ uint8 *im = _v + 2;
+ uint16 *cp = (uint16 *) _v;
+ int bpl;
+
+ if (_v) { // 2nd pass - fill the hide table
+ for (uint16 i = 0; i < _h; i++) {
+ _b[i]._skip = 0xFFFF;
+ _b[i]._hide = 0x0000;
+ }
+ }
+ for (bpl = 0; bpl < 4; bpl++) { // once per each bitplane
+ uint8 *bm = _m;
+ bool skip = (bm[bpl] == kPixelTransp);
+ uint16 j;
+
+ cnt = 0;
+ for (uint16 i = 0; i < _h; i++) { // once per each line
+ uint8 pix;
+ for (j = bpl; j < _w; j += 4) {
+ pix = bm[j];
+ if (_v && pix != kPixelTransp) {
+ if (j < _b[i]._skip)
+ _b[i]._skip = j;
+
+ if (j >= _b[i]._hide)
+ _b[i]._hide = j + 1;
+ }
+ if ((pix == kPixelTransp) != skip || cnt >= 0x3FF0) { // end of block
+ cnt |= (skip) ? kBmpSKP : kBmpCPY;
+ if (_v)
+ WRITE_LE_UINT16(cp, cnt); // store block description uint16
+
+ cp = (uint16 *) im;
+ im += 2;
+ skip = (pix == kPixelTransp);
+ cnt = 0;
+ }
+ if (!skip) {
+ if (_v)
+ *im = pix;
+ im++;
+ }
+ cnt++;
+ }
+
+ bm += _w;
+ if (_w < kScrWidth) {
+ if (skip) {
+ cnt += (kScrWidth - j + 3) / 4;
+ } else {
+ cnt |= kBmpCPY;
+ if (_v)
+ WRITE_LE_UINT16(cp, cnt);
+
+ cp = (uint16 *) im;
+ im += 2;
+ skip = true;
+ cnt = (kScrWidth - j + 3) / 4;
+ }
+ }
+ }
+ if (cnt && ! skip) {
+ cnt |= kBmpCPY;
+ if (_v)
+ WRITE_LE_UINT16(cp, cnt);
+
+ cp = (uint16 *) im;
+ im += 2;
+ }
+ if (_v)
+ WRITE_LE_UINT16(cp, kBmpEOI);
+ cp = (uint16 *) im;
+ im += 2;
+ }
+ if (_v)
+ break;
+
+ uint16 sizV = (uint16)(im - 2 - _v);
+ _v = new uint8[sizV + _h * sizeof(*_b)];
+ assert(_v != NULL);
+
+ _b = (HideDesc *)(_v + sizV);
+ }
+ cnt = 0;
+ for (uint16 i = 0; i < _h; i++) {
+ if (_b[i]._skip == 0xFFFF) { // whole line is skipped
+ _b[i]._skip = (cnt + kScrWidth) >> 2;
+ cnt = 0;
+ } else {
+ uint16 s = _b[i]._skip & ~3;
+ uint16 h = (_b[i]._hide + 3) & ~3;
+ _b[i]._skip = (cnt + s) >> 2;
+ _b[i]._hide = (h - s) >> 2;
+ cnt = kScrWidth - h;
+ }
+ }
+
+ return this;
+}
+
+bool Bitmap::solidAt(int16 x, int16 y) {
+ if ((x >= _w) || (y >= _h))
+ return false;
+
+ uint8 *m = _v;
+ uint16 r = static_cast<uint16>(x) % 4;
+ uint16 n0 = (kScrWidth * y + x) / 4;
+ uint16 n = 0;
+
+ while (r) {
+ uint16 w, t;
+
+ w = READ_LE_UINT16(m);
+ m += 2;
+ t = w & 0xC000;
+ w &= 0x3FFF;
+
+ switch (t) {
+ case kBmpEOI:
+ r--;
+ // No break on purpose
+ case kBmpSKP:
+ w = 0;
+ break;
+ case kBmpREP:
+ w = 1;
+ break;
+ }
+ m += w;
+ }
+
+ while (true) {
+ uint16 w, t;
+
+ w = READ_LE_UINT16(m);
+ m += 2;
+ t = w & 0xC000;
+ w &= 0x3FFF;
+
+ if (n > n0)
+ return false;
+
+ n += w;
+ switch (t) {
+ case kBmpEOI:
+ return false;
+ case kBmpSKP:
+ w = 0;
+ break;
+ case kBmpREP:
+ case kBmpCPY:
+ if (n - w <= n0 && n > n0)
+ return true;
+ break;
+ }
+ m += ((t == kBmpREP) ? 1 : w);
+ }
+}
+
+bool Bitmap::loadVBM(EncryptedStream *f) {
+ uint16 p = 0, n = 0;
+ if (!f->err())
+ f->read((uint8 *)&p, sizeof(p));
+ p = FROM_LE_16(p);
+
+ if (!f->err())
+ f->read((uint8 *)&n, sizeof(n));
+ n = FROM_LE_16(n);
+
+ if (!f->err())
+ f->read((uint8 *)&_w, sizeof(_w));
+ _w = FROM_LE_16(_w);
+
+ if (!f->err())
+ f->read((uint8 *)&_h, sizeof(_h));
+ _h = FROM_LE_16(_h);
+
+ if (!f->err()) {
+ if (p) {
+ if (_vm->_bitmapPalette) {
+ // Read in the palette
+ byte palData[kPalSize];
+ f->read(palData, kPalSize);
+
+ const byte *srcP = palData;
+ for (int idx = 0; idx < kPalCount; idx++, srcP += 3) {
+ _vm->_bitmapPalette[idx]._r = *srcP;
+ _vm->_bitmapPalette[idx]._g = *(srcP + 1);
+ _vm->_bitmapPalette[idx]._b = *(srcP + 2);
+ }
+ } else
+ f->seek(f->pos() + kPalSize);
+ }
+ }
+ if ((_v = new uint8[n]) == NULL)
+ return false;
+
+ if (!f->err())
+ f->read(_v, n);
+
+ _b = (HideDesc *)(_v + n - _h * sizeof(HideDesc));
+ return (!f->err());
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/bitmap.h b/engines/cge2/bitmap.h
new file mode 100644
index 0000000000..3d3c27f97e
--- /dev/null
+++ b/engines/cge2/bitmap.h
@@ -0,0 +1,87 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_BITMAP_H
+#define CGE2_BITMAP_H
+
+#include "cge/general.h"
+#include "common/file.h"
+
+namespace CGE2 {
+
+class CGE2Engine;
+class EncryptedStream;
+
+#define kMaxPath 128
+enum {
+ kBmpEOI = 0x0000,
+ kBmpSKP = 0x4000,
+ kBmpREP = 0x8000,
+ kBmpCPY = 0xC000
+};
+
+#include "common/pack-start.h"
+
+struct HideDesc {
+ uint16 _skip;
+ uint16 _hide;
+} PACKED_STRUCT;
+
+#include "common/pack-end.h"
+
+class Bitmap {
+ CGE2Engine *_vm;
+ char *forceExt(char *buf, const char *name, const char *ext);
+ bool loadVBM(EncryptedStream *f);
+public:
+ uint16 _w;
+ uint16 _h;
+ uint8 *_m;
+ uint8 *_v;
+ int32 _map;
+ HideDesc *_b;
+
+ Bitmap(CGE2Engine *vm, const char *fname);
+ Bitmap(CGE2Engine *vm, uint16 w, uint16 h, uint8 *map);
+ Bitmap(CGE2Engine *vm, uint16 w, uint16 h, uint8 fill);
+ Bitmap(CGE2Engine *vm, const Bitmap &bmp);
+ ~Bitmap();
+
+ Bitmap *code();
+ Bitmap &operator=(const Bitmap &bmp);
+ void hide(int16 x, int16 y);
+ void show(int16 x, int16 y);
+ void xShow(int16 x, int16 y);
+ bool solidAt(int16 x, int16 y);
+};
+
+
+typedef Bitmap *BitmapPtr;
+
+} // End of namespace CGE2
+
+#endif // CGE2_BITMAP_H
diff --git a/engines/cge2/cge2.cpp b/engines/cge2/cge2.cpp
index 56393d20db..955c5eb0ea 100644
--- a/engines/cge2/cge2.cpp
+++ b/engines/cge2/cge2.cpp
@@ -25,21 +25,34 @@
* Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
*/
+#include "engines/util.h"
+
#include "cge2/cge2.h"
+#include "cge2/bitmap.h"
+#include "cge2/vga13h.h"
namespace CGE2 {
CGE2Engine::CGE2Engine(OSystem *syst, const ADGameDescription *gameDescription)
: Engine(syst), _gameDescription(gameDescription) {
_resman = nullptr;
+ _vga = nullptr;
+ _sprite = nullptr;
+
+ _quitFlag = false;
+ _bitmapPalette = nullptr;
+ _mode = 0;
}
void CGE2Engine::init() {
_resman = new ResourceManager();
+ _vga = new Vga(this);
}
void CGE2Engine::deinit() {
delete _resman;
+ delete _vga;
+ delete _sprite;
}
bool CGE2Engine::hasFeature(EngineFeature f) const {
@@ -64,10 +77,41 @@ Common::Error CGE2Engine::saveGameState(int slot, const Common::String &desc) {
}
Common::Error CGE2Engine::run() {
+ initGraphics(kScrWidth, kScrHeight, false);
+
init();
warning("STUB: CGE2Engine::run()");
+ showTitle("WELCOME");
deinit();
return Common::kNoError;
}
+bool CGE2Engine::showTitle(const char *name) {
+ if (_quitFlag)
+ return false;
+
+ _bitmapPalette = _vga->_sysPal;
+ BitmapPtr *LB = new BitmapPtr[2];
+ LB[0] = new Bitmap(this, name);
+ LB[1] = NULL;
+ _bitmapPalette = NULL;
+
+ Sprite D(this, LB);
+ D._flags._kill = true;
+ D._flags._bDel = true;
+ D.center();
+ D.show(2);
+
+ _vga->sunset();
+ _vga->copyPage(1, 2);
+ _vga->copyPage(0, 1);
+ _vga->sunrise(_vga->_sysPal);
+
+ _vga->update();
+
+ warning("STUB: CGE2Engine::showTitle()");
+
+ return true;
+}
+
} // End of namespace CGE2
diff --git a/engines/cge2/cge2.h b/engines/cge2/cge2.h
index f84c9a8212..814c607a93 100644
--- a/engines/cge2/cge2.h
+++ b/engines/cge2/cge2.h
@@ -30,10 +30,20 @@
#include "engines/engine.h"
#include "engines/advancedDetector.h"
+#include "common/system.h"
#include "cge2/fileio.h"
+#include "cge2/general.h"
namespace CGE2 {
+class Vga;
+class Sprite;
+
+#define kScrWidth 320
+#define kScrHeight 240
+#define kMaxFile 128
+#define kPathMax 128
+
class CGE2Engine : public Engine {
public:
CGE2Engine(OSystem *syst, const ADGameDescription *gameDescription);
@@ -44,9 +54,17 @@ public:
virtual Common::Error saveGameState(int slot, const Common::String &desc);
virtual Common::Error run();
+ bool showTitle(const char *name);
+
const ADGameDescription *_gameDescription;
+ bool _quitFlag;
+ Dac *_bitmapPalette;
+ int _mode;
+
ResourceManager *_resman;
+ Vga *_vga;
+ Sprite *_sprite;
private:
void init();
void deinit();
diff --git a/engines/cge2/general.h b/engines/cge2/general.h
new file mode 100644
index 0000000000..7d5c60f191
--- /dev/null
+++ b/engines/cge2/general.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_GENERAL_H
+#define CGE2_GENERAL_H
+
+#include "common/file.h"
+
+namespace CGE2 {
+
+struct Dac {
+ uint8 _r;
+ uint8 _g;
+ uint8 _b;
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_GENERAL_H
diff --git a/engines/cge2/module.mk b/engines/cge2/module.mk
index fc710b663a..493488f745 100644
--- a/engines/cge2/module.mk
+++ b/engines/cge2/module.mk
@@ -3,7 +3,9 @@ MODULE := engines/cge2
MODULE_OBJS = \
cge2.o \
detection.o \
- fileio.o
+ fileio.o \
+ vga13h.o \
+ bitmap.o
# This module can be built as a plugin
ifeq ($(ENABLE_CGE2), DYNAMIC_PLUGIN)
diff --git a/engines/cge2/vga13h.cpp b/engines/cge2/vga13h.cpp
new file mode 100644
index 0000000000..26fba8bfd8
--- /dev/null
+++ b/engines/cge2/vga13h.cpp
@@ -0,0 +1,1016 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#include "common/array.h"
+#include "common/config-manager.h"
+#include "common/rect.h"
+#include "graphics/palette.h"
+#include "cge2/general.h"
+#include "cge2/vga13h.h"
+#include "cge2/bitmap.h"
+//#include "cge/text.h"
+//#include "cge/cge_main.h"
+#include "cge2/cge2.h"
+#include "cge2/vga13h.h"
+
+namespace CGE2 {
+
+Seq *getConstantSeq(bool seqFlag) {
+ const Seq seq1[] = { { 0, 0, 0, 0, 0 } };
+ const Seq seq2[] = { { 0, 1, 0, 0, 0 }, { 1, 0, 0, 0, 0 } };
+
+ Seq *seq;
+ if (seqFlag) {
+ seq = (Seq *)malloc(1 * sizeof(Seq));
+ *seq = seq1[0];
+ } else {
+ seq = (Seq *)malloc(2 * sizeof(Seq));
+ seq[0] = seq2[0];
+ seq[1] = seq2[1];
+ }
+
+ return seq;
+}
+
+Sprite::Sprite(CGE2Engine *vm, BitmapPtr *shpP)
+ : _x(0), _y(0), _z(0), _nearPtr(0), _takePtr(0),
+ _next(NULL), _prev(NULL), _seqPtr(kNoSeq), _time(0),
+ _ext(NULL), _ref(-1), _scene(0), _vm(vm) {
+ memset(_file, 0, sizeof(_file));
+ memset(&_flags, 0, sizeof(_flags));
+ _ref = 0;
+ _x = _y = 0;
+ _w = _h = 0;
+ _time = 0;
+ _seqPtr = 0;
+ _shpCnt = 0;
+ _prev = _next = NULL;
+
+ setShapeList(shpP);
+}
+
+Sprite::~Sprite() {
+ if (_vm->_sprite == this)
+ _vm->_sprite = NULL;
+
+ contract();
+}
+
+BitmapPtr Sprite::shp() {
+ SprExt *e = _ext;
+ if (!e || !e->_seq)
+ return NULL;
+
+ int i = e->_seq[_seqPtr]._now;
+ if (i >= _shpCnt)
+ error("Invalid PHASE in SPRITE::Shp() %s", _file);
+ return e->_shpList[i];
+}
+
+BitmapPtr *Sprite::setShapeList(BitmapPtr *shpP) {
+ BitmapPtr *r = (_ext) ? _ext->_shpList : NULL;
+
+ _shpCnt = 0;
+ _w = 0;
+ _h = 0;
+
+ if (shpP) {
+ BitmapPtr *p;
+ for (p = shpP; *p; p++) {
+ BitmapPtr b = (*p); // ->Code();
+ if (b->_w > _w)
+ _w = b->_w;
+ if (b->_h > _h)
+ _h = b->_h;
+ _shpCnt++;
+ }
+ expand();
+ _ext->_shpList = shpP;
+ _flags._bDel = true;
+ if (!_ext->_seq)
+ setSeq(getConstantSeq(_shpCnt < 2));
+ }
+ return r;
+}
+
+bool Sprite::works(Sprite *spr) {
+ //if (!spr || !spr->_ext)
+ // return false;
+
+ //CommandHandler::Command *c = spr->_ext->_take;
+ //if (c != NULL) {
+ // c += spr->_takePtr;
+ // if (c->_ref == _ref)
+ // if (c->_commandType != kCmdLabel || (c->_val == 0 || c->_val == _vm->_now))
+ // return true;
+ //}
+
+ warning("STUB: Sprite::works()");
+
+ return false;
+}
+
+Seq *Sprite::setSeq(Seq *seq) {
+ if (_ext) {
+ free(_ext->_seq);
+ _ext->_seq = NULL;
+ }
+
+// expand();
+ warning("STUB: Sprite::setSeq()");
+
+ Seq *s = _ext->_seq;
+ _ext->_seq = seq;
+ if (_seqPtr == kNoSeq)
+ step(0);
+ else if (_time == 0)
+ step(_seqPtr);
+ return s;
+}
+
+bool Sprite::seqTest(int n) {
+ if (n >= 0)
+ return (_seqPtr == n);
+ if (_ext)
+ return (_ext->_seq[_seqPtr]._next == _seqPtr);
+ return true;
+}
+
+//CommandHandler::Command *Sprite::snList(SnList type) {
+// SprExt *e = _ext;
+// if (e)
+// return (type == kNear) ? e->_near : e->_take;
+// return NULL;
+//}
+
+void Sprite::setName(char *newName) {
+ if (!_ext)
+ return;
+
+ if (_ext->_name) {
+ delete[] _ext->_name;
+ _ext->_name = NULL;
+ }
+ if (newName) {
+ _ext->_name = new char[strlen(newName) + 1];
+ assert(_ext->_name != NULL);
+ strcpy(_ext->_name, newName);
+ }
+}
+
+Sprite *Sprite::expand() {
+ if (_ext)
+ return this;
+
+ _ext = new SprExt;
+ assert(_ext != NULL);
+ if (!*_file)
+ return this;
+
+ static const char *Comd[] = { "Name", "Phase", "Seq", "Near", "Take", NULL };
+ char fname[kPathMax];
+
+ Common::Array<BitmapPtr> shplist;
+ for (int i = 0; i < _shpCnt + 1; ++i)
+ shplist.push_back(NULL);
+
+ Seq *seq = NULL;
+ int shapeCount = 0,
+ seqCount = 0,
+ nearCount = 0,
+ takeCount = 0,
+ maxnow = 0,
+ maxnxt = 0;
+
+ warning("STUB: Sprite::expand()");
+
+ //CommandHandler::Command *nearList = NULL;
+ //CommandHandler::Command *takeList = NULL;
+ //_vm->mergeExt(fname, _file, kSprExt);
+ //if (_vm->_resman->exist(fname)) { // sprite description file exist
+ // EncryptedStream sprf(_vm, fname);
+ // if (sprf.err())
+ // error("Bad SPR [%s]", fname);
+ // Common::String line;
+ // char tmpStr[kLineMax + 1];
+ // int lcnt = 0;
+
+ // for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) {
+ // int len = line.size();
+ // Common::strlcpy(tmpStr, line.c_str(), sizeof(tmpStr));
+ // lcnt++;
+ // if (len == 0 || *tmpStr == '.')
+ // continue;
+
+ // CommandHandler::Command *c;
+ // switch (_vm->takeEnum(Comd, strtok(tmpStr, " =\t"))) {
+ // case 0:
+ // // Name
+ // setName(strtok(NULL, ""));
+ // break;
+ // case 1:
+ // // Phase
+ // // In case the shape index gets too high, increase the array size
+ // while ((shapeCount + 1) >= (int)shplist.size()) {
+ // shplist.push_back(NULL);
+ // ++_shpCnt;
+ // }
+ // shplist[shapeCount++] = new Bitmap(_vm, strtok(NULL, " \t,;/"));
+ // break;
+ // case 2:
+ // // Seq
+ // seq = (Seq *)realloc(seq, (seqCount + 1) * sizeof(*seq));
+ // assert(seq != NULL);
+ // Seq *s;
+ // s = &seq[seqCount++];
+ // s->_now = atoi(strtok(NULL, " \t,;/"));
+ // if (s->_now > maxnow)
+ // maxnow = s->_now;
+ // s->_next = atoi(strtok(NULL, " \t,;/"));
+ // switch (s->_next) {
+ // case 0xFF:
+ // s->_next = seqCount;
+ // break;
+ // case 0xFE:
+ // s->_next = seqCount - 1;
+ // break;
+ // }
+ // if (s->_next > maxnxt)
+ // maxnxt = s->_next;
+ // s->_dx = atoi(strtok(NULL, " \t,;/"));
+ // s->_dy = atoi(strtok(NULL, " \t,;/"));
+ // s->_dly = atoi(strtok(NULL, " \t,;/"));
+ // break;
+ // case 3:
+ // // Near
+ // if (_nearPtr == kNoPtr)
+ // break;
+ // nearList = (CommandHandler::Command *)realloc(nearList, (nearCount + 1) * sizeof(*nearList));
+ // assert(nearList != NULL);
+ // c = &nearList[nearCount++];
+ // if ((c->_commandType = (CommandType)_vm->takeEnum(CommandHandler::_commandText, strtok(NULL, " \t,;/"))) < 0)
+ // error("Bad NEAR in %d [%s]", lcnt, fname);
+ // c->_ref = atoi(strtok(NULL, " \t,;/"));
+ // c->_val = atoi(strtok(NULL, " \t,;/"));
+ // c->_spritePtr = NULL;
+ // break;
+ // case 4:
+ // // Take
+ // if (_takePtr == kNoPtr)
+ // break;
+ // takeList = (CommandHandler::Command *)realloc(takeList, (takeCount + 1) * sizeof(*takeList));
+ // assert(takeList != NULL);
+ // c = &takeList[takeCount++];
+ // if ((c->_commandType = (CommandType)_vm->takeEnum(CommandHandler::_commandText, strtok(NULL, " \t,;/"))) < 0)
+ // error("Bad NEAR in %d [%s]", lcnt, fname);
+ // c->_ref = atoi(strtok(NULL, " \t,;/"));
+ // c->_val = atoi(strtok(NULL, " \t,;/"));
+ // c->_spritePtr = NULL;
+ // break;
+ // }
+ // }
+ //} else {
+ // // no sprite description: try to read immediately from .BMP
+ // shplist[shapeCount++] = new Bitmap(_vm, _file);
+ //}
+
+ //shplist[shapeCount] = NULL;
+ //if (seq) {
+ // if (maxnow >= shapeCount)
+ // error("Bad PHASE in SEQ [%s]", fname);
+ // if (maxnxt >= seqCount)
+ // error("Bad JUMP in SEQ [%s]", fname);
+ // setSeq(seq);
+ //} else
+ // setSeq(getConstantSeq(_shpCnt == 1));
+
+ //// Set the shape list
+ //BitmapPtr *shapeList = new BitmapPtr[shplist.size()];
+ //for (uint i = 0; i < shplist.size(); ++i)
+ // shapeList[i] = shplist[i];
+
+ //setShapeList(shapeList);
+
+ //if (nearList)
+ // nearList[nearCount - 1]._spritePtr = _ext->_near = nearList;
+ //else
+ // _nearPtr = kNoPtr;
+ //if (takeList)
+ // takeList[takeCount - 1]._spritePtr = _ext->_take = takeList;
+ //else
+ // _takePtr = kNoPtr;
+
+ return this;
+}
+
+Sprite *Sprite::contract() {
+ //SprExt *e = _ext;
+ //if (!e)
+ // return this;
+
+ //if (e->_name)
+ // delete[] e->_name;
+ //if (_flags._bDel && e->_shpList) {
+ // for (int i = 0; e->_shpList[i]; i++)
+ // delete e->_shpList[i];
+ // delete[] e->_shpList;
+ //}
+
+ //free(e->_seq);
+ //free(e->_near);
+ //free(e->_take);
+
+ //delete e;
+ //_ext = NULL;
+
+ warning("STUB: Sprite::contract()");
+
+ return this;
+}
+
+Sprite *Sprite::backShow(bool fast) {
+ expand();
+ show(2);
+ show(1);
+ if (fast)
+ show(0);
+ contract();
+ return this;
+}
+
+void Sprite::step(int nr) {
+ if (nr >= 0)
+ _seqPtr = nr;
+ if (_ext) {
+ Seq *seq;
+ if (nr < 0)
+ _seqPtr = _ext->_seq[_seqPtr]._next;
+ seq = _ext->_seq + _seqPtr;
+ if (seq->_dly >= 0) {
+ gotoxy(_x + (seq->_dx), _y + (seq->_dy));
+ _time = seq->_dly;
+ }
+ }
+}
+
+//void Sprite::tick() {
+// step();
+//}
+
+void Sprite::makeXlat(uint8 *x) {
+ if (!_ext)
+ return;
+
+ if (_flags._xlat)
+ killXlat();
+ for (BitmapPtr *b = _ext->_shpList; *b; b++)
+ (*b)->_m = x;
+ _flags._xlat = true;
+}
+
+void Sprite::killXlat() {
+ if (!_flags._xlat || !_ext)
+ return;
+
+ uint8 *m = (*_ext->_shpList)->_m;
+ free(m);
+
+ for (BitmapPtr *b = _ext->_shpList; *b; b++)
+ (*b)->_m = NULL;
+ _flags._xlat = false;
+}
+
+void Sprite::gotoxy(int x, int y) {
+ int xo = _x, yo = _y;
+ if (_x < kScrWidth) {
+ if (x < 0)
+ x = 0;
+ if (x + _w > kScrWidth)
+ x = (kScrWidth - _w);
+ _x = x;
+ }
+ if (_h < kScrHeight) {
+ if (y < 0)
+ y = 0;
+ if (y + _h > kScrHeight)
+ y = (kScrHeight - _h);
+ _y = y;
+ }
+ if (_next)
+ if (_next->_flags._slav)
+ _next->gotoxy(_next->_x - xo + _x, _next->_y - yo + _y);
+ if (_flags._shad)
+ _prev->gotoxy(_prev->_x - xo + _x, _prev->_y - yo + _y);
+}
+
+void Sprite::center() {
+ gotoxy((kScrWidth - _w) / 2, (kScrHeight - _h) / 2);
+}
+
+void Sprite::show() {
+ SprExt *e;
+ e = _ext;
+ e->_x0 = e->_x1;
+ e->_y0 = e->_y1;
+ e->_b0 = e->_b1;
+ e->_x1 = _x;
+ e->_y1 = _y;
+ e->_b1 = shp();
+ if (!_flags._hide) {
+ if (_flags._xlat)
+ e->_b1->xShow(e->_x1, e->_y1);
+ else
+ e->_b1->show(e->_x1, e->_y1);
+ }
+}
+
+void Sprite::show(uint16 pg) {
+ Graphics::Surface *a = _vm->_vga->_page[1];
+ _vm->_vga->_page[1] = _vm->_vga->_page[pg & 3];
+ shp()->show(_x, _y);
+ _vm->_vga->_page[1] = a;
+}
+
+void Sprite::hide() {
+ SprExt *e = _ext;
+ if (e->_b0)
+ e->_b0->hide(e->_x0, e->_y0);
+}
+
+BitmapPtr Sprite::ghost() {
+ SprExt *e = _ext;
+ if (!e->_b1)
+ return NULL;
+
+ BitmapPtr bmp = new Bitmap(_vm, 0, 0, (uint8 *)NULL);
+ assert(bmp != NULL);
+ bmp->_w = e->_b1->_w;
+ bmp->_h = e->_b1->_h;
+ bmp->_b = new HideDesc[bmp->_h];
+ assert(bmp->_b != NULL);
+ bmp->_v = (uint8 *) memcpy(bmp->_b, e->_b1->_b, sizeof(HideDesc) * bmp->_h);
+ bmp->_map = (e->_y1 << 16) + e->_x1;
+ return bmp;
+}
+
+void Sprite::sync(Common::Serializer &s) {
+ uint16 unused = 0;
+
+ s.syncAsUint16LE(unused);
+ s.syncAsUint16LE(unused); // _ext
+ s.syncAsUint16LE(_ref);
+ s.syncAsByte(_scene);
+
+ // bitfield in-memory storage is unpredictable, so to avoid
+ // any issues, pack/unpack everything manually
+ uint16 flags = 0;
+ if (s.isLoading()) {
+ s.syncAsUint16LE(flags);
+ _flags._hide = flags & 0x0001 ? true : false;
+ _flags._near = flags & 0x0002 ? true : false;
+ _flags._drag = flags & 0x0004 ? true : false;
+ _flags._hold = flags & 0x0008 ? true : false;
+ _flags._dummy = flags & 0x0010 ? true : false;
+ _flags._slav = flags & 0x0020 ? true : false;
+ _flags._syst = flags & 0x0040 ? true : false;
+ _flags._kill = flags & 0x0080 ? true : false;
+ _flags._xlat = flags & 0x0100 ? true : false;
+ _flags._port = flags & 0x0200 ? true : false;
+ _flags._kept = flags & 0x0400 ? true : false;
+ _flags._east = flags & 0x0800 ? true : false;
+ _flags._shad = flags & 0x1000 ? true : false;
+ _flags._back = flags & 0x2000 ? true : false;
+ _flags._bDel = flags & 0x4000 ? true : false;
+ _flags._tran = flags & 0x8000 ? true : false;
+ } else {
+ flags = (flags << 1) | _flags._tran;
+ flags = (flags << 1) | _flags._bDel;
+ flags = (flags << 1) | _flags._back;
+ flags = (flags << 1) | _flags._shad;
+ flags = (flags << 1) | _flags._east;
+ flags = (flags << 1) | _flags._kept;
+ flags = (flags << 1) | _flags._port;
+ flags = (flags << 1) | _flags._xlat;
+ flags = (flags << 1) | _flags._kill;
+ flags = (flags << 1) | _flags._syst;
+ flags = (flags << 1) | _flags._slav;
+ flags = (flags << 1) | _flags._dummy;
+ flags = (flags << 1) | _flags._hold;
+ flags = (flags << 1) | _flags._drag;
+ flags = (flags << 1) | _flags._near;
+ flags = (flags << 1) | _flags._hide;
+ s.syncAsUint16LE(flags);
+ }
+
+ s.syncAsUint16LE(_x);
+ s.syncAsUint16LE(_y);
+ s.syncAsByte(_z);
+ s.syncAsUint16LE(_w);
+ s.syncAsUint16LE(_h);
+ s.syncAsUint16LE(_time);
+ s.syncAsByte(_nearPtr);
+ s.syncAsByte(_takePtr);
+ s.syncAsSint16LE(_seqPtr);
+ s.syncAsUint16LE(_shpCnt);
+ s.syncBytes((byte *)&_file[0], 9);
+ _file[8] = '\0';
+
+ s.syncAsUint16LE(unused); // _prev
+ s.syncAsUint16LE(unused); // _next
+}
+
+Queue::Queue(bool show) : _head(NULL), _tail(NULL), _show(show) {
+}
+
+Queue::~Queue() {
+ clear();
+}
+
+void Queue::clear() {
+ while (_head) {
+ Sprite *s = remove(_head);
+ if (s->_flags._kill)
+ delete s;
+ }
+}
+
+void Queue::append(Sprite *spr) {
+ if (_tail) {
+ spr->_prev = _tail;
+ _tail->_next = spr;
+ } else
+ _head = spr;
+ _tail = spr;
+ if (_show)
+ spr->expand();
+ else
+ spr->contract();
+}
+
+void Queue::insert(Sprite *spr, Sprite *nxt) {
+ if (nxt == _head) {
+ spr->_next = _head;
+ _head = spr;
+ if (!_tail)
+ _tail = spr;
+ } else {
+ assert(nxt);
+ spr->_next = nxt;
+ spr->_prev = nxt->_prev;
+ if (spr->_prev)
+ spr->_prev->_next = spr;
+ }
+ if (spr->_next)
+ spr->_next->_prev = spr;
+ if (_show)
+ spr->expand();
+ else
+ spr->contract();
+}
+
+void Queue::insert(Sprite *spr) {
+ Sprite *s;
+ for (s = _head; s; s = s->_next)
+ if (s->_z > spr->_z)
+ break;
+ if (s)
+ insert(spr, s);
+ else
+ append(spr);
+ if (_show)
+ spr->expand();
+ else
+ spr->contract();
+}
+
+template<typename T>
+inline bool contains(const Common::List<T> &l, const T &v) {
+ return (Common::find(l.begin(), l.end(), v) != l.end());
+}
+
+Sprite *Queue::remove(Sprite *spr) {
+ if (spr == _head)
+ _head = spr->_next;
+ if (spr == _tail)
+ _tail = spr->_prev;
+ if (spr->_next)
+ spr->_next->_prev = spr->_prev;
+ if (spr->_prev)
+ spr->_prev->_next = spr->_next;
+ spr->_prev = NULL;
+ spr->_next = NULL;
+ return spr;
+}
+
+Sprite *Queue::locate(int ref) {
+ for (Sprite *spr = _head; spr; spr = spr->_next) {
+ if (spr->_ref == ref)
+ return spr;
+ }
+ return NULL;
+}
+
+Vga::Vga(CGE2Engine *vm) : _frmCnt(0), _msg(NULL), _name(NULL), _setPal(false), _mono(0), _vm(vm) {
+ _oldColors = NULL;
+ _newColors = NULL;
+ _showQ = new Queue(true);
+ _spareQ = new Queue(false);
+ _sysPal = new Dac[kPalCount];
+
+ for (int idx = 0; idx < 4; idx++) {
+ _page[idx] = new Graphics::Surface();
+ _page[idx]->create(kScrWidth, kScrHeight, Graphics::PixelFormat::createFormatCLUT8());
+ }
+
+ /*if (ConfMan.getBool("enable_color_blind"))
+ _mono = 1;*/
+
+ warning("STUB: Vga::Vga()");
+
+ _oldColors = (Dac *)malloc(sizeof(Dac) * kPalCount);
+ _newColors = (Dac *)malloc(sizeof(Dac) * kPalCount);
+ getColors(_oldColors);
+ sunset();
+ setColors();
+ clear(0);
+}
+
+Vga::~Vga() {
+ _mono = 0;
+
+ Common::String buffer = "";
+/*
+ clear(0);
+ setMode(_oldMode);
+ setColors();
+ restoreScreen(_oldScreen);
+ sunrise(_oldColors);
+*/
+ warning("STUB: Vga::~Vga()");
+
+ free(_oldColors);
+ free(_newColors);
+ if (_msg)
+ buffer = Common::String(_msg);
+ if (_name)
+ buffer = buffer + " [" + _name + "]";
+
+ debugN("%s", buffer.c_str());
+
+ delete _showQ;
+ delete _spareQ;
+ delete[] _sysPal;
+
+ for (int idx = 0; idx < 4; idx++) {
+ _page[idx]->free();
+ delete _page[idx];
+ }
+}
+
+void Vga::waitVR() {
+ // Since some of the game parts rely on using vertical sync as a delay mechanism,
+ // we're introducing a short delay to simulate it
+ g_system->delayMillis(5);
+}
+
+void Vga::getColors(Dac *tab) {
+ byte palData[kPalSize];
+ g_system->getPaletteManager()->grabPalette(palData, 0, kPalCount);
+ palToDac(palData, tab);
+}
+
+uint8 Vga::closest(Dac *pal, const uint8 colR, const uint8 colG, const uint8 colB) {
+#define f(col, lum) ((((uint16)(col)) << 8) / lum)
+ uint16 i, dif = 0xFFFF, found = 0;
+ uint16 L = colR + colG + colB;
+ if (!L)
+ L++;
+ uint16 R = f(colR, L), G = f(colG, L), B = f(colB, L);
+ for (i = 0; i < 256; i++) {
+ uint16 l = pal[i]._r + pal[i]._g + pal[i]._b;
+ if (!l)
+ l++;
+ int r = f(pal[i]._r, l), g = f(pal[i]._g, l), b = f(pal[i]._b, l);
+ uint16 D = ((r > R) ? (r - R) : (R - r)) +
+ ((g > G) ? (g - G) : (G - g)) +
+ ((b > B) ? (b - B) : (B - b)) +
+ ((l > L) ? (l - L) : (L - l)) * 10 ;
+
+ if (D < dif) {
+ found = i;
+ dif = D;
+ if (D == 0)
+ break; // exact!
+ }
+ }
+ return found;
+#undef f
+}
+
+uint8 *Vga::glass(Dac *pal, const uint8 colR, const uint8 colG, const uint8 colB) {
+ uint8 *x = (uint8 *)malloc(256);
+ if (x) {
+ uint16 i;
+ for (i = 0; i < 256; i++) {
+ x[i] = closest(pal, ((uint16)(pal[i]._r) * colR) / 255,
+ ((uint16)(pal[i]._g) * colG) / 255,
+ ((uint16)(pal[i]._b) * colB) / 255);
+ }
+ }
+ return x;
+}
+
+void Vga::palToDac(const byte *palData, Dac *tab) {
+ const byte *colP = palData;
+ for (int idx = 0; idx < kPalCount; idx++, colP += 3) {
+ tab[idx]._r = *colP >> 2;
+ tab[idx]._g = *(colP + 1) >> 2;
+ tab[idx]._b = *(colP + 2) >> 2;
+ }
+}
+
+void Vga::dacToPal(const Dac *tab, byte *palData) {
+ for (int idx = 0; idx < kPalCount; idx++, palData += 3) {
+ *palData = tab[idx]._r << 2;
+ *(palData + 1) = tab[idx]._g << 2;
+ *(palData + 2) = tab[idx]._b << 2;
+ }
+}
+
+void Vga::setColors(Dac *tab, int lum) {
+ Dac *palP = tab, *destP = _newColors;
+ for (int idx = 0; idx < kPalCount; idx++, palP++, destP++) {
+ destP->_r = (palP->_r * lum) >> 6;
+ destP->_g = (palP->_g * lum) >> 6;
+ destP->_b = (palP->_b * lum) >> 6;
+ }
+
+ if (_mono) {
+ destP = _newColors;
+ for (int idx = 0; idx < kPalCount; idx++, destP++) {
+ // Form a greyscalce color from 30% R, 59% G, 11% B
+ uint8 intensity = (((int)destP->_r * 77) + ((int)destP->_g * 151) + ((int)destP->_b * 28)) >> 8;
+ destP->_r = intensity;
+ destP->_g = intensity;
+ destP->_b = intensity;
+ }
+ }
+
+ _setPal = true;
+}
+
+void Vga::setColors() {
+ memset(_newColors, 0, kPalSize);
+ updateColors();
+}
+
+void Vga::sunrise(Dac *tab) {
+ for (int i = 0; i <= 64; i += kFadeStep) {
+ setColors(tab, i);
+ waitVR();
+ updateColors();
+ }
+}
+
+void Vga::sunset() {
+ Dac tab[256];
+ getColors(tab);
+ for (int i = 64; i >= 0; i -= kFadeStep) {
+ setColors(tab, i);
+ waitVR();
+ updateColors();
+ }
+}
+
+void Vga::show() {
+ for (Sprite *spr = _showQ->first(); spr; spr = spr->_next)
+ spr->show();
+ update();
+ for (Sprite *spr = _showQ->first(); spr; spr = spr->_next)
+ spr->hide();
+
+ _frmCnt++;
+}
+
+void Vga::updateColors() {
+ byte palData[kPalSize];
+ dacToPal(_newColors, palData);
+ g_system->getPaletteManager()->setPalette(palData, 0, 256);
+}
+
+void Vga::update() {
+ SWAP(Vga::_page[0], Vga::_page[1]);
+
+ if (_setPal) {
+ updateColors();
+ _setPal = false;
+ }
+ /*if (_vm->_showBoundariesFl) {
+ Vga::_page[0]->hLine(0, 200 - kPanHeight, 320, 0xee);
+ if (_vm->_barriers[_vm->_now]._horz != 255) {
+ for (int i = 0; i < 8; i++)
+ Vga::_page[0]->vLine((_vm->_barriers[_vm->_now]._horz * 8) + i, 0, 200, 0xff);
+ }
+ if (_vm->_barriers[_vm->_now]._vert != 255) {
+ for (int i = 0; i < 4; i++)
+ Vga::_page[0]->hLine(0, 80 + (_vm->_barriers[_vm->_now]._vert * 4) + i, 320, 0xff);
+ }
+ }*/
+
+ warning("STUB: Vga::update()");
+
+ g_system->copyRectToScreen(Vga::_page[0]->getPixels(), kScrWidth, 0, 0, kScrWidth, kScrHeight);
+ g_system->updateScreen();
+}
+
+void Vga::clear(uint8 color) {
+ for (int paneNum = 0; paneNum < 4; paneNum++)
+ _page[paneNum]->fillRect(Common::Rect(0, 0, kScrWidth, kScrHeight), color);
+}
+
+void Vga::copyPage(uint16 d, uint16 s) {
+ _page[d]->copyFrom(*_page[s]);
+}
+
+//--------------------------------------------------------------------------
+
+void Bitmap::xShow(int16 x, int16 y) {
+ const byte *srcP = (const byte *)_v;
+ byte *destEndP = (byte *)_vm->_vga->_page[1]->getBasePtr(0, kScrHeight);
+ byte *lookupTable = _m;
+
+ // Loop through processing data for each plane. The game originally ran in plane mapped mode, where a
+ // given plane holds each fourth pixel sequentially. So to handle an entire picture, each plane's data
+ // must be decompressed and inserted into the surface
+ for (int planeCtr = 0; planeCtr < 4; planeCtr++) {
+ byte *destP = (byte *)_vm->_vga->_page[1]->getBasePtr(x + planeCtr, y);
+
+ for (;;) {
+ uint16 v = READ_LE_UINT16(srcP);
+ srcP += 2;
+ int cmd = v >> 14;
+ int count = v & 0x3FFF;
+
+ if (cmd == 0) {
+ // End of image
+ break;
+ }
+
+ assert(destP < destEndP);
+
+ if (cmd == 2)
+ srcP++;
+ else if (cmd == 3)
+ srcP += count;
+
+ // Handle a set of pixels
+ while (count-- > 0) {
+ // Transfer operation
+ switch (cmd) {
+ case 1:
+ // SKIP
+ break;
+ case 2:
+ case 3:
+ // TINT
+ *destP = lookupTable[*destP];
+ break;
+ }
+
+ // Move to next dest position
+ destP += 4;
+ }
+ }
+ }
+}
+
+
+void Bitmap::show(int16 x, int16 y) {
+ const byte *srcP = (const byte *)_v;
+ byte *destEndP = (byte *)_vm->_vga->_page[1]->getBasePtr(0, kScrHeight);
+
+ // Loop through processing data for each plane. The game originally ran in plane mapped mode, where a
+ // given plane holds each fourth pixel sequentially. So to handle an entire picture, each plane's data
+ // must be decompressed and inserted into the surface
+ for (int planeCtr = 0; planeCtr < 4; planeCtr++) {
+ byte *destP = (byte *)_vm->_vga->_page[1]->getBasePtr(x + planeCtr, y);
+
+ for (;;) {
+ uint16 v = READ_LE_UINT16(srcP);
+ srcP += 2;
+ int cmd = v >> 14;
+ int count = v & 0x3FFF;
+
+ if (cmd == 0) {
+ // End of image
+ break;
+ }
+
+ assert(destP < destEndP);
+
+ // Handle a set of pixels
+ while (count-- > 0) {
+ // Transfer operation
+ switch (cmd) {
+ case 1:
+ // SKIP
+ break;
+ case 2:
+ // REPEAT
+ *destP = *srcP;
+ break;
+ case 3:
+ // COPY
+ *destP = *srcP++;
+ break;
+ }
+
+ // Move to next dest position
+ destP += 4;
+ }
+
+ if (cmd == 2)
+ srcP++;
+ }
+ }
+}
+
+
+void Bitmap::hide(int16 x, int16 y) {
+ for (int yp = y; yp < y + _h; yp++) {
+ const byte *srcP = (const byte *)_vm->_vga->_page[2]->getBasePtr(x, yp);
+ byte *destP = (byte *)_vm->_vga->_page[1]->getBasePtr(x, yp);
+
+ Common::copy(srcP, srcP + _w, destP);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+HorizLine::HorizLine(CGE2Engine *vm) : Sprite(vm, NULL), _vm(vm) {
+ // Set the sprite list
+ BitmapPtr *HL = new BitmapPtr[2];
+ HL[0] = new Bitmap(_vm, "HLINE");
+ HL[1] = NULL;
+
+ setShapeList(HL);
+}
+
+SceneLight::SceneLight(CGE2Engine *vm) : Sprite(vm, NULL), _vm(vm) {
+ // Set the sprite list
+ BitmapPtr *PR = new BitmapPtr[2];
+ PR[0] = new Bitmap(_vm, "PRESS");
+ PR[1] = NULL;
+
+ setShapeList(PR);
+}
+
+Speaker::Speaker(CGE2Engine *vm): Sprite(vm, NULL), _vm(vm) {
+ // Set the sprite list
+ BitmapPtr *SP = new BitmapPtr[3];
+ SP[0] = new Bitmap(_vm, "SPK_L");
+ SP[1] = new Bitmap(_vm, "SPK_R");
+ SP[2] = NULL;
+
+ setShapeList(SP);
+}
+
+PocLight::PocLight(CGE2Engine *vm): Sprite(vm, NULL), _vm(vm) {
+ // Set the sprite list
+ BitmapPtr *LI = new BitmapPtr[5];
+ LI[0] = new Bitmap(_vm, "LITE0");
+ LI[1] = new Bitmap(_vm, "LITE1");
+ LI[2] = new Bitmap(_vm, "LITE2");
+ LI[3] = new Bitmap(_vm, "LITE3");
+ LI[4] = NULL;
+
+ setShapeList(LI);
+
+ _flags._kill = false;
+}
+
+} // End of namespace CGE2
diff --git a/engines/cge2/vga13h.h b/engines/cge2/vga13h.h
new file mode 100644
index 0000000000..e761c5c35c
--- /dev/null
+++ b/engines/cge2/vga13h.h
@@ -0,0 +1,243 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Sfinx source code
+ * Copyright (c) 1994-1997 Janus B. Wisniewski and L.K. Avalon
+ */
+
+#ifndef CGE2_VGA13H_H
+#define CGE2_VGA13H_H
+
+#include "common/serializer.h"
+#include "common/events.h"
+#include "graphics/surface.h"
+#include "cge2/general.h"
+#include "cge2/bitmap.h"
+//#include "cge/snail.h"
+#include "cge2/cge2.h"
+
+namespace CGE2 {
+
+#define kFadeStep 2
+#define kVgaColDark 207
+#define kVgaColDarkGray 225 /*219*/
+#define kVgaColGray 231
+#define kVgaColLightGray 237
+#define kPixelTransp 0xFE
+#define kNoSeq (-1)
+#define kNoPtr ((uint8)-1)
+#define kSprExt ".SPR"
+#define kPalCount 256
+#define kPalSize (kPalCount * 3)
+
+struct Seq {
+ uint8 _now;
+ uint8 _next;
+ int8 _dx;
+ int8 _dy;
+ int _dly;
+};
+
+class SprExt {
+public:
+ int _x0;
+ int _y0;
+ int _x1;
+ int _y1;
+ BitmapPtr _b0;
+ BitmapPtr _b1;
+ BitmapPtr *_shpList;
+ Seq *_seq;
+ char *_name;
+ /*CommandHandler::Command *_near;
+ CommandHandler::Command *_take;*/
+ SprExt() :
+ _x0(0), _y0(0),
+ _x1(0), _y1(0),
+ _b0(NULL), _b1(NULL),
+ _shpList(NULL), _seq(NULL),
+ _name(NULL)/*, _near(NULL), _take(NULL)*/
+ {}
+};
+
+class Sprite {
+protected:
+ SprExt *_ext;
+public:
+ int _ref;
+ signed char _scene;
+ struct Flags {
+ uint16 _hide : 1; // general visibility switch
+ uint16 _near : 1; // Near action lock
+ uint16 _drag : 1; // sprite is moveable
+ uint16 _hold : 1; // sprite is held with mouse
+ uint16 _dummy : 1; // intrrupt driven animation
+ uint16 _slav : 1; // slave object
+ uint16 _syst : 1; // system object
+ uint16 _kill : 1; // dispose memory after remove
+ uint16 _xlat : 1; // 2nd way display: xlat table
+ uint16 _port : 1; // portable
+ uint16 _kept : 1; // kept in pocket
+ uint16 _east : 1; // talk to east (in opposite to west)
+ uint16 _shad : 1; // shadow
+ uint16 _back : 1; // 'send to background' request
+ uint16 _bDel : 1; // delete bitmaps in ~SPRITE
+ uint16 _tran : 1; // transparent (untouchable)
+ } _flags;
+ int _x;
+ int _y;
+ signed char _z;
+ uint16 _w;
+ uint16 _h;
+ uint16 _time;
+ uint8 _nearPtr;
+ uint8 _takePtr;
+ int _seqPtr;
+ int _shpCnt;
+ char _file[kMaxFile];
+ Sprite *_prev;
+ Sprite *_next;
+
+ bool works(Sprite *spr);
+ bool seqTest(int n);
+ inline bool active() {
+ return _ext != NULL;
+ }
+
+ Sprite(CGE2Engine *vm, BitmapPtr *shp);
+ virtual ~Sprite();
+ BitmapPtr shp();
+ BitmapPtr *setShapeList(BitmapPtr *shp);
+ Sprite *expand();
+ Sprite *contract();
+ Sprite *backShow(bool fast = false);
+ void setName(char *newName);
+ inline char *name() {
+ return (_ext) ? _ext->_name : NULL;
+ }
+ void gotoxy(int x, int y);
+ void center();
+ void show();
+ void hide();
+ BitmapPtr ghost();
+ void show(uint16 pg);
+ void makeXlat(uint8 *x);
+ void killXlat();
+ void step(int nr = -1);
+ Seq *setSeq(Seq *seq);
+ //CommandHandler::Command *snList(SnList type);
+ /*virtual void touch(uint16 mask, int x, int y, Common::KeyCode keyCode);
+ virtual void tick();*/
+ void sync(Common::Serializer &s);
+private:
+ CGE2Engine *_vm;
+};
+
+class Queue {
+ Sprite *_head;
+ Sprite *_tail;
+public:
+ Queue(bool show);
+ ~Queue();
+
+ bool _show;
+
+ void append(Sprite *spr);
+ void insert(Sprite *spr, Sprite *nxt);
+ void insert(Sprite *spr);
+ Sprite *remove(Sprite *spr);
+ Sprite *first() {
+ return _head;
+ }
+ Sprite *last() {
+ return _tail;
+ }
+ Sprite *locate(int ref);
+ void clear();
+};
+
+class Vga {
+ CGE2Engine *_vm;
+ bool _setPal;
+ Dac *_oldColors;
+ Dac *_newColors;
+ const char *_msg;
+ const char *_name;
+
+ void updateColors();
+ void setColors();
+ void waitVR();
+ uint8 closest(Dac *pal, const uint8 colR, const uint8 colG, const uint8 colB);
+
+public:
+ uint32 _frmCnt;
+ Queue *_showQ;
+ Queue *_spareQ;
+ int _mono;
+ Graphics::Surface *_page[4];
+ Dac *_sysPal;
+
+ Vga(CGE2Engine *vm);
+ ~Vga();
+
+ uint8 *glass(Dac *pal, const uint8 colR, const uint8 colG, const uint8 colB);
+ void getColors(Dac *tab);
+ void setColors(Dac *tab, int lum);
+ void clear(uint8 color);
+ void copyPage(uint16 d, uint16 s);
+ void sunrise(Dac *tab);
+ void sunset();
+ void show();
+ void update();
+
+ void palToDac(const byte *palData, Dac *tab);
+ void dacToPal(const Dac *tab, byte *palData);
+};
+
+class HorizLine: public Sprite {
+ CGE2Engine *_vm;
+public:
+ HorizLine(CGE2Engine *vm);
+};
+
+class SceneLight: public Sprite {
+ CGE2Engine *_vm;
+public:
+ SceneLight(CGE2Engine *vm);
+};
+
+class Speaker: public Sprite {
+ CGE2Engine *_vm;
+public:
+ Speaker(CGE2Engine *vm);
+};
+
+class PocLight: public Sprite {
+ CGE2Engine *_vm;
+public:
+ PocLight(CGE2Engine *vm);
+};
+
+} // End of namespace CGE2
+
+#endif // CGE2_VGA13H_H