From ec71f936280496d349310ea0091dbe26b90ae540 Mon Sep 17 00:00:00 2001 From: uruk Date: Tue, 29 Apr 2014 09:50:40 +0200 Subject: [PATCH] CGE2: Add parts of the graphics code. --- engines/cge2/bitmap.cpp | 369 ++++++++++++++ engines/cge2/bitmap.h | 87 ++++ engines/cge2/cge2.cpp | 44 ++ engines/cge2/cge2.h | 18 + engines/cge2/general.h | 43 ++ engines/cge2/module.mk | 4 +- engines/cge2/vga13h.cpp | 1016 +++++++++++++++++++++++++++++++++++++++ engines/cge2/vga13h.h | 243 ++++++++++ 8 files changed, 1823 insertions(+), 1 deletion(-) create mode 100644 engines/cge2/bitmap.cpp create mode 100644 engines/cge2/bitmap.h create mode 100644 engines/cge2/general.h create mode 100644 engines/cge2/vga13h.cpp create mode 100644 engines/cge2/vga13h.h diff --git a/engines/cge2/bitmap.cpp b/engines/cge2/bitmap.cpp new file mode 100644 index 000000000000..77c7eb9c4173 --- /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(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 000000000000..3d3c27f97ea4 --- /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 56393d20db0f..955c5eb0ea96 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 f84c9a8212b0..814c607a93da 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 @@ class CGE2Engine : public Engine { 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 000000000000..7d5c60f19142 --- /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 fc710b663ac5..493488f7459d 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 000000000000..26fba8bfd8ae --- /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 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 +inline bool contains(const Common::List &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 000000000000..e761c5c35c38 --- /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