diff options
Diffstat (limited to 'engines/cge/vga13h.cpp')
-rw-r--r-- | engines/cge/vga13h.cpp | 1034 |
1 files changed, 1034 insertions, 0 deletions
diff --git a/engines/cge/vga13h.cpp b/engines/cge/vga13h.cpp new file mode 100644 index 0000000000..8213a1bcf3 --- /dev/null +++ b/engines/cge/vga13h.cpp @@ -0,0 +1,1034 @@ +/* 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 Soltys source code + * Copyright (c) 1994-1995 Janus B. Wisniewski and L.K. Avalon + */ + +#include "common/array.h" +#include "common/rect.h" +#include "graphics/palette.h" +#include "cge/general.h" +#include "cge/vga13h.h" +#include "cge/bitmap.h" +#include "cge/vol.h" +#include "cge/text.h" +#include "cge/cge_main.h" +#include "cge/cge.h" + +namespace CGE { + +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; +} + +extern "C" void SNDMIDIPlay(); + +Dac mkDac(uint8 r, uint8 g, uint8 b) { + static Dac x; + x._r = r; + x._g = g; + x._b = b; + return x; +} + +Sprite *locate(int ref) { + Sprite *spr = _vga->_showQ->locate(ref); + return (spr) ? spr : _vga->_spareQ->locate(ref); +} + +Sprite::Sprite(CGEEngine *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), _cave(0), _vm(vm) { + memset(_file, 0, sizeof(_file)); + *((uint16 *)&_flags) = 0; + _ref = 0; + _x = _y = 0; + _w = _h = 0; + _time = 0; + _seqPtr = 0; + _shpCnt = 0; + _prev = _next = NULL; + + setShapeList(shpP); +} + +Sprite::~Sprite() { + if (_sprite == this) + _sprite = NULL; + + contract(); +} + +BitmapPtr Sprite::shp() { + SprExt *e = _ext; + if (!e || !e->_seq) + return NULL; + + int i = e->_seq[_seqPtr]._now; + if (i >= _shpCnt) { + //char s[256]; + //sprintf(s, "Seq=%p ShpCnt=%d SeqPtr=%d Now=%d Next=%d", + // Seq, ShpCnt, SeqPtr, Seq[SeqPtr].Now, Seq[SeqPtr].Next); + //VGA::Exit(s, File); + 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; +} + +void Sprite::moveShapes(uint8 *buf) { + BitmapPtr *p; + for (p = _ext->_shpList; *p; p++) { + buf += (*p)->moveVmap(buf); + } +} + +bool Sprite::works(Sprite *spr) { + if (!spr || !spr->_ext) + return false; + + Snail::Com *c = spr->_ext->_take; + if (c != NULL) { + c += spr->_takePtr; + if (c->_ref == _ref) + if (c->_com != kSnLabel || (c->_val == 0 || c->_val == _vm->_now)) + return true; + } + + return false; +} + +Seq *Sprite::setSeq(Seq *seq) { + if (_ext) { + free(_ext->_seq); + _ext->_seq = NULL; + } + + expand(); + + 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; +} + +Snail::Com *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 line[kLineMax], fname[kPathMax]; + + Common::Array<BitmapPtr> shplist; + for (int i = 0; i < _shpCnt + 1; ++i) + shplist.push_back(NULL); + + Seq *seq = NULL; + int shpcnt = 0, + seqcnt = 0, + neacnt = 0, + takcnt = 0, + maxnow = 0, + maxnxt = 0; + + Snail::Com *nea = NULL; + Snail::Com *tak = NULL; + mergeExt(fname, _file, kSprExt); + if (INI_FILE::exist(fname)) { // sprite description file exist + INI_FILE sprf(fname); + if (!(sprf._error==0)) + error("Bad SPR [%s]", fname); + int len = 0, lcnt = 0; + while ((len = sprf.read((uint8 *)line)) != 0) { + lcnt++; + if (len && line[len - 1] == '\n') + line[--len] = '\0'; + if (len == 0 || *line == '.') + continue; + + Snail::Com *c; + switch (takeEnum(Comd, strtok(line, " =\t"))) { + case 0: + // Name + setName(strtok(NULL, "")); + break; + case 1: + // Phase + // In case the shape index gets too high, increase the array size + while ((shpcnt + 1) >= (int)shplist.size()) { + shplist.push_back(NULL); + ++_shpCnt; + } + shplist[shpcnt++] = new Bitmap(strtok(NULL, " \t,;/")); + break; + case 2: + // Seq + seq = (Seq *) realloc(seq, (seqcnt + 1) * sizeof(*seq)); + assert(seq != NULL); + Seq *s; + s = &seq[seqcnt++]; + 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 = seqcnt; + break; + case 0xFE: + s->_next = seqcnt - 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; + nea = (Snail::Com *) realloc(nea, (neacnt + 1) * sizeof(*nea)); + assert(nea != NULL); + c = &nea[neacnt++]; + if ((c->_com = (SnCom)takeEnum(Snail::_comText, 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->_ptr = NULL; + break; + case 4: + // Take + if (_takePtr == kNoPtr) + break; + tak = (Snail::Com *) realloc(tak, (takcnt + 1) * sizeof(*tak)); + assert(tak != NULL); + c = &tak[takcnt++]; + if ((c->_com = (SnCom)takeEnum(Snail::_comText, 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->_ptr = NULL; + break; + } + } + } else { + // no sprite description: try to read immediately from .BMP + shplist[shpcnt++] = new Bitmap(_file); + } + + shplist[shpcnt] = NULL; + if (seq) { + if (maxnow >= shpcnt) + error("Bad PHASE in SEQ [%s]", fname); + if (maxnxt >= seqcnt) + 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 (nea) + nea[neacnt - 1]._ptr = _ext->_near = nea; + else + _nearPtr = kNoPtr; + if (tak) + tak[takcnt - 1]._ptr = _ext->_take = tak; + 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; + + 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; +// asm cli // critic section... + e = _ext; + e->_x0 = e->_x1; + e->_y0 = e->_y1; + e->_b0 = e->_b1; + e->_x1 = _x; + e->_y1 = _y; + e->_b1 = shp(); +// asm sti // ...done! + 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 = Vga::_page[1]; + Vga::_page[1] = Vga::_page[pg & 3]; + shp()->show(_x, _y); + 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(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(_cave); + + // 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._____ = 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._____; + 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 +} + +Sprite *spriteAt(int x, int y) { + Sprite *spr = NULL, * tail = _vga->_showQ->last(); + if (tail) { + for (spr = tail->_prev; spr; spr = spr->_prev) { + if (! spr->_flags._hide && ! spr->_flags._tran) { + if (spr->shp()->solidAt(x - spr->_x, y - spr->_y)) + break; + } + } + } + return spr; +} + +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::forAll(void (*fun)(Sprite *)) { + Sprite *s = _head; + while (s) { + Sprite *n = s->_next; + fun(s); + s = n; + } +} + +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; +} + +//extern const char Copr[]; +Graphics::Surface *Vga::_page[4]; +Dac *Vga::_sysPal; + +void Vga::init() { + for (int idx = 0; idx < 4; idx++) { + _page[idx] = new Graphics::Surface(); + _page[idx]->create(320, 200, Graphics::PixelFormat::createFormatCLUT8()); + } + + _sysPal = new Dac[kPalCount]; +} + +void Vga::deinit() { + for (int idx = 0; idx < 4; idx++) { + _page[idx]->free(); + delete _page[idx]; + } + delete[] _sysPal; +} + +Vga::Vga() + : _frmCnt(0), _msg(NULL), _name(NULL), _setPal(false), _mono(0) { + _oldColors = NULL; + _newColors = NULL; + _showQ = new Queue(true); + _spareQ = new Queue(false); + + bool std = true; + for (int i = 10; i < 20; i++) { + char *text = _text->getText(i); + if (text) { + debugN(1, "%s\n", text); + std = false; + } + } + if (std) +// warning(Copr); + warning("TODO: Fix Copr"); + + _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); +*/ + free(_oldColors); + free(_newColors); + if (_msg) + buffer = Common::String(_msg); + if (_name) + buffer = buffer + " [" + _name + "]"; + + debugN("%s", buffer.c_str()); + + delete _showQ; + delete _spareQ; +} + +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); +} + +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 colour 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; + } + + g_system->copyRectToScreen((const byte *)Vga::_page[0]->getBasePtr(0, 0), 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) { + debugC(4, kCGEDebugBitmap, "Bitmap::xShow(%d, %d)", x, y); + + const byte *srcP = (const byte *)_v; + byte *destEndP = (byte *)Vga::_page[1]->pixels + (kScrWidth * 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 *)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) { + debugC(5, kCGEDebugBitmap, "Bitmap::show(%d, %d)", x, y); + + const byte *srcP = (const byte *)_v; + byte *destEndP = (byte *)Vga::_page[1]->pixels + (kScrWidth * 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 *)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++; + } + } +/* + DEBUG code to display image immediately + // Temporary + g_system->copyRectToScreen((const byte *)VGA::Page[1]->getBasePtr(0, 0), SCR_WID, 0, 0, SCR_WID, SCR_HIG); + byte palData[PAL_SIZ]; + VGA::DAC2pal(VGA::SysPal, palData); + g_system->getPaletteManager()->setPalette(palData, 0, PAL_CNT); + + g_system->updateScreen(); + g_system->delayMillis(5000); +*/ +} + + +void Bitmap::hide(int16 x, int16 y) { + debugC(5, kCGEDebugBitmap, "Bitmap::hide(%d, %d)", x, y); + + for (int yp = y; yp < y + _h; yp++) { + const byte *srcP = (const byte *)Vga::_page[2]->getBasePtr(x, yp); + byte *destP = (byte *)Vga::_page[1]->getBasePtr(x, yp); + + Common::copy(srcP, srcP + _w, destP); + } +} + +/*--------------------------------------------------------------------------*/ + +HorizLine::HorizLine(CGEEngine *vm): Sprite(vm, NULL) { + // Set the sprite list + BitmapPtr *HL = new BitmapPtr[2]; + HL[0] = new Bitmap("HLINE"); + HL[1] = NULL; + + setShapeList(HL); +} + +CavLight::CavLight(CGEEngine *vm): Sprite(vm, NULL) { + // Set the sprite list + BitmapPtr *PR = new BitmapPtr[2]; + PR[0] = new Bitmap("PRESS"); + PR[1] = NULL; + + setShapeList(PR); +} + +Spike::Spike(CGEEngine *vm): Sprite(vm, NULL) { + // Set the sprite list + BitmapPtr *SP = new BitmapPtr[3]; + SP[0] = new Bitmap("SPK_L"); + SP[1] = new Bitmap("SPK_R"); + SP[2] = NULL; + + setShapeList(SP); +} + +PocLight::PocLight(CGEEngine *vm): Sprite(vm, NULL) { + // Set the sprite list + BitmapPtr *LI = new BitmapPtr[5]; + LI[0] = new Bitmap("LITE0"); + LI[1] = new Bitmap("LITE1"); + LI[2] = new Bitmap("LITE2"); + LI[3] = new Bitmap("LITE3"); + LI[4] = NULL; + + setShapeList(LI); + + _flags._kill = false; +} + +} // End of namespace CGE |