aboutsummaryrefslogtreecommitdiff
path: root/scumm/costume.cpp
diff options
context:
space:
mode:
authorMax Horn2002-08-21 16:07:07 +0000
committerMax Horn2002-08-21 16:07:07 +0000
commitce46866403fdcc479cf9d67e4d430409b15dadc3 (patch)
tree75ebfaa1ed13f549959d76d3ce101c3e66f5451b /scumm/costume.cpp
parent662256f25dbe43abf67077a804e225738765f009 (diff)
downloadscummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.tar.gz
scummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.tar.bz2
scummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.zip
Initial revision
svn-id: r4785
Diffstat (limited to 'scumm/costume.cpp')
-rw-r--r--scumm/costume.cpp1447
1 files changed, 1447 insertions, 0 deletions
diff --git a/scumm/costume.cpp b/scumm/costume.cpp
new file mode 100644
index 0000000000..1996613929
--- /dev/null
+++ b/scumm/costume.cpp
@@ -0,0 +1,1447 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "stdafx.h"
+#include "scumm.h"
+#include "actor.h"
+#include "costume.h"
+
+const byte revBitMask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+void CostumeRenderer::ignorePakCols(int a)
+{
+ int n;
+
+ n = _height;
+ if (a > 1)
+ n *= a;
+
+ do {
+ _repcolor = *_srcptr++;
+ _replen = _repcolor & _maskval;
+ if (_replen == 0) {
+ _replen = *_srcptr++;
+ }
+ do {
+ if (!--n) {
+ _repcolor >>= _shrval;
+ return;
+ }
+ } while (--_replen);
+ } while (1);
+}
+
+const byte cost_scaleTable[256] = {
+ 255, 253, 125, 189, 61, 221, 93, 157, 29, 237,
+ 109, 173, 45, 205, 77, 141, 13, 245, 117, 181,
+ 53, 213, 85, 149, 21, 229, 101, 165, 37, 197, 69,
+ 133, 5, 249, 121, 185, 57, 217, 89, 153, 25, 233,
+ 105, 169, 41, 201, 73, 137, 9, 241, 113, 177, 49,
+ 209, 81, 145, 17, 225, 97, 161, 33, 193, 65, 129,
+ 1, 251, 123, 187, 59, 219, 91, 155, 27, 235, 107,
+ 171, 43, 203, 75, 139, 11, 243, 115, 179, 51, 211,
+ 83, 147, 19, 227, 99, 163, 35, 195, 67, 131, 3,
+ 247, 119, 183, 55, 215, 87, 151, 23, 231, 103,
+ 167, 39, 199, 71, 135, 7, 239, 111, 175, 47, 207,
+ 79, 143, 15, 223, 95, 159, 31, 191, 63, 127, 0,
+ 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208,
+ 48, 176, 112, 240, 8, 136, 72, 200, 40, 168, 104,
+ 232, 24, 152, 88, 216, 56, 184, 120, 248, 4, 132,
+ 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52,
+ 180, 116, 244, 12, 140, 76, 204, 44, 172, 108,
+ 236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130,
+ 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50,
+ 178, 114, 242, 10, 138, 74, 202, 42, 170, 106,
+ 234, 26, 154, 90, 218, 58, 186, 122, 250, 6, 134,
+ 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54,
+ 182, 118, 246, 14, 142, 78, 206, 46, 174, 110,
+ 238, 30, 158, 94, 222, 62, 190, 126, 254
+};
+
+byte CostumeRenderer::mainRoutine(Actor *a, int slot, int frame)
+{
+ int xmove, ymove, i, b, s;
+ uint scal;
+ byte scaling;
+ byte charsetmask, masking;
+ byte unk19;
+ byte newAmiCost;
+ int ex1, ex2;
+
+ newAmiCost = (_vm->_gameId == GID_MONKEY2 || _vm->_gameId == GID_INDY4) && (_vm->_features & GF_AMIGA);
+
+ CHECK_HEAP _maskval = 0xF;
+ _shrval = 4;
+ if (_loaded._numColors == 32) {
+ _maskval = 7;
+ _shrval = 3;
+ }
+
+ _width2 = _srcptr[0];
+ _width = _width2;
+ _height2 = _srcptr[2];
+ _height = _height2;
+ xmove = (int16)READ_LE_UINT16(_srcptr + 4) + _xmove;
+ ymove = (int16)READ_LE_UINT16(_srcptr + 6) + _ymove;
+ _xmove += (int16)READ_LE_UINT16(_srcptr + 8);
+ _ymove -= (int16)READ_LE_UINT16(_srcptr + 10);
+ _srcptr += 12;
+
+ switch (_loaded._ptr[7] & 0x7F) {
+ case 0x60:
+ case 0x61:
+ ex1 = _srcptr[0];
+ ex2 = _srcptr[1];
+ _srcptr += 2;
+ if (ex1 != 0xFF || ex2 != 0xFF) {
+ ex1 = READ_LE_UINT16(_loaded._ptr + _loaded._numColors + 10 + ex1 * 2);
+ _srcptr = _loaded._ptr + READ_LE_UINT16(_loaded._ptr + ex1 + ex2 * 2) + 14;
+ }
+ }
+
+ _xpos = _actorX;
+ _ypos = _actorY;
+
+ scaling = _scaleX == 255 && _scaleY == 255 ? 0 : 1;
+ s = 0;
+
+ if (scaling) {
+ _scaleIndexXStep = -1;
+ if (xmove < 0) {
+ xmove = -xmove;
+ _scaleIndexXStep = 1;
+ }
+
+ if (_mirror) {
+ unk19 = _scaleIndexX = 128 - xmove;
+ for (i = 0; i < xmove; i++) {
+ scal = cost_scaleTable[_scaleIndexX++];
+ if (scal < _scaleX)
+ _xpos -= _scaleIndexXStep;
+ }
+ _right = _left = _xpos;
+ _scaleIndexX = unk19;
+ for (i = 0; i < _width; i++) {
+ if (_right < 0) {
+ s++;
+ unk19 = _scaleIndexX;
+ }
+ scal = cost_scaleTable[_scaleIndexX++];
+ if (scal < _scaleX)
+ _right++;
+ }
+ } else {
+ unk19 = _scaleIndexX = xmove + 128;
+ for (i = 0; i < xmove; i++) {
+ scal = cost_scaleTable[_scaleIndexX--];
+ if (scal < _scaleX)
+ _xpos += _scaleIndexXStep;
+ }
+ _right = _left = _xpos;
+ _scaleIndexX = unk19;
+ for (i = 0; i < _width; i++) {
+ if (_left > 319) {
+ s++;
+ unk19 = _scaleIndexX;
+ }
+ scal = cost_scaleTable[_scaleIndexX--];
+ if (scal < _scaleX)
+ _left--;
+ }
+ }
+ _scaleIndexX = unk19;
+ if (s)
+ s--;
+ _scaleIndexYStep = -1;
+ if (ymove < 0) {
+ ymove = -ymove;
+ _scaleIndexYStep = 1;
+ }
+ _scaleIndexY = 128 - ymove;
+ for (i = 0; i < ymove; i++) {
+ scal = cost_scaleTable[_scaleIndexY++];
+ if (scal < _scaleY)
+ _ypos -= _scaleIndexYStep;
+ }
+ _top = _bottom = _ypos;
+ _scaleIndexY = 128 - ymove;
+ for (i = 0; i < _height; i++) {
+ scal = cost_scaleTable[_scaleIndexY++];
+ if (scal < _scaleY)
+ _bottom++;
+ }
+ _scaleIndexY = _scaleIndexYTop = 128 - ymove;
+ } else {
+ if (_mirror == 0)
+ xmove = -xmove;
+ _xpos += xmove;
+ _ypos += ymove;
+ if (_mirror) {
+ _left = _xpos;
+ _right = _xpos + _width;
+ } else {
+ _left = _xpos - _width;
+ _right = _xpos;
+ }
+ _top = _ypos;
+ _bottom = _top + _height;
+ }
+
+ _scaleIndexXStep = -1;
+ if (_mirror)
+ _scaleIndexXStep = 1;
+ _ypostop = _ypos;
+
+ _vm->updateDirtyRect(0, _left, _right + 1, _top, _bottom, 1 << a->number);
+
+ if (_top >= (int)_outheight || _bottom <= 0)
+ return 0;
+
+ _ypitch = _height * 320;
+ _docontinue = 0;
+ b = 1;
+ if (_left > 319 || _right <= 0)
+ return 1;
+ if (_mirror) {
+ _ypitch--;
+ if (scaling == 0) {
+ s = -_xpos;
+ }
+ if (s > 0) {
+ if (!newAmiCost) {
+ _width2 -= s;
+ ignorePakCols(s);
+ _xpos = 0;
+ _docontinue = 1;
+ }
+ } else {
+ s = _right - 320;
+ if (s <= 0) {
+ b = 2;
+ } else {
+ _width2 -= s;
+ }
+ }
+ } else {
+ _ypitch++;
+ if (scaling == 0)
+ s = _right - 320;
+ if (s > 0) {
+ if (!newAmiCost) {
+ _width2 -= s;
+ ignorePakCols(s);
+ _xpos = 319;
+ _docontinue = 1;
+ }
+ } else {
+ s = -1 - _left;
+ if (s <= 0)
+ b = 2;
+ else
+ _width2 -= s;
+ }
+ }
+
+ if (_width2 == 0)
+ return 0;
+
+ if ((uint) _top > (uint) _outheight)
+ _top = 0;
+
+ if (_left < 0)
+ _left = 0;
+
+ if ((uint) _bottom > _outheight)
+ _bottom = _outheight;
+
+ if (a->top > _top)
+ a->top = _top;
+
+ if (a->bottom < _bottom)
+ a->bottom = _bottom;
+
+ if (_height2 + _top >= 256) {
+ CHECK_HEAP return 2;
+ }
+
+ _bgbak_ptr = _vm->getResourceAddress(rtBuffer, 5) + _vm->virtscr[0].xstart + _ypos * 320 + _xpos;
+ _backbuff_ptr = _vm->virtscr[0].screenPtr + _vm->virtscr[0].xstart + _ypos * 320 + _xpos;
+ charsetmask =
+ _vm->hasCharsetMask(_left, _top + _vm->virtscr[0].topline, _right,
+ _vm->virtscr[0].topline + _bottom);
+ masking = 0;
+
+ if (_vm->_features & GF_SMALL_HEADER)
+ masking = (_zbuf != 0);
+ else
+ masking =
+ _vm->isMaskActiveAt(_left, _top, _right, _bottom,
+ _vm->getResourceAddress(rtBuffer, 9) +
+ _vm->gdi._imgBufOffs[_zbuf] +
+ _vm->_screenStartStrip);
+
+ if (masking || charsetmask) {
+ _mask_ptr = _vm->getResourceAddress(rtBuffer, 9) + _ypos * 40 + _vm->_screenStartStrip;
+ _imgbufoffs = _vm->gdi._imgBufOffs[_zbuf];
+ if (!charsetmask && _zbuf != 0)
+ _mask_ptr += _imgbufoffs;
+ _mask_ptr_dest = _mask_ptr + _xpos / 8;
+ }
+
+ CHECK_HEAP if (a->shadow_mode) {
+ proc_special(a, (masking << 1) + charsetmask);
+ return b;
+ }
+
+ switch ((newAmiCost << 3) | (scaling << 2) | (masking << 1) | charsetmask) {
+ case 0:
+ proc6(); // no scaling, no masking, no charsetmask
+ break;
+ case 1:
+ case 2:
+ proc5(); // no scaling, masking or charsetmask
+ break;
+ case 3:
+ proc4(); // no scaling, masking and charsetmask
+ break;
+ case 4:
+ proc1(); // scaling, no masking, no charsetmask
+ break;
+ case 5:
+ case 6:
+ proc2(); // scaling, masking or charsetmask
+ break;
+ case 7:
+ proc3(); // scaling, masking and charsetmask
+ break;
+ case 8:
+ proc6_ami(); // no scaling, no masking, no charsetmask (Amiga)
+ break;
+ case 9:
+ case 10:
+ proc5_ami(); // no scaling, masking or charsetmask (Amiga)
+ break;
+ case 11:
+ proc4_ami(); // no scaling, masking and charsetmask (Amiga)
+ break;
+ case 12:
+ proc1_ami(); // scaling, no masking, no charsetmask (Amiga)
+ break;
+ case 13:
+ case 14:
+ proc2_ami(); // scaling, masking or charsetmask (Amiga)
+ break;
+ case 15:
+ proc3_ami(); // scaling, masking and charsetmask (Amiga)
+ break;
+ }
+
+ CHECK_HEAP return b;
+}
+
+void CostumeRenderer::proc6()
+{
+ byte *src, *dst;
+ byte len, height, pcolor, width;
+ uint y;
+ int color;
+ uint scrheight;
+
+ y = _ypos;
+ src = _srcptr;
+ dst = _backbuff_ptr;
+ len = _replen;
+ color = _repcolor;
+ height = _height2;
+ scrheight = _outheight;
+ width = _width2;
+
+ if (_docontinue)
+ goto StartPos;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (color && y < scrheight) {
+ pcolor = _palette[color];
+ if (pcolor == 13) {
+ pcolor = _shadow_table[*dst];
+ }
+ *dst = pcolor;
+ }
+
+ dst += 320;
+ y++;
+ if (!--height) {
+ if (!--width)
+ return;
+ height = _height;
+ dst -= _ypitch;
+ y = _ypostop;
+ }
+ StartPos:;
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc5()
+{
+ byte *mask, *src, *dst;
+ byte maskbit, len, height, pcolor;
+ uint y, scrheight;
+ int color;
+
+ mask = _mask_ptr = _mask_ptr_dest;
+ maskbit = revBitMask[_xpos & 7];
+ y = _ypos;
+ src = _srcptr;
+ dst = _backbuff_ptr;
+ len = _replen;
+ color = _repcolor;
+ height = _height2;
+ scrheight = _outheight;
+
+ if (_docontinue)
+ goto StartPos;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (color && y < scrheight && !(*mask & maskbit)) {
+ pcolor = _palette[color];
+ if (pcolor == 13)
+ pcolor = _shadow_table[*dst];
+ *dst = pcolor;
+ }
+ dst += 320;
+ y++;
+ mask += 40;
+ if (!--height) {
+ if (!--_width2)
+ return;
+ height = _height;
+ dst -= _ypitch;
+ y = _ypostop;
+ if (_scaleIndexXStep != 1) {
+ maskbit <<= 1;
+ if (!maskbit) {
+ maskbit = 1;
+ _mask_ptr--;
+ }
+ } else {
+ maskbit >>= 1;
+ if (!maskbit) {
+ maskbit = 0x80;
+ _mask_ptr++;
+ }
+ }
+ mask = _mask_ptr;
+ }
+ StartPos:;
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc4()
+{
+ byte *mask, *src, *dst;
+ byte maskbit, len, height, pcolor;
+ uint y, scrheight;
+ int color;
+
+ mask = _mask_ptr = _mask_ptr_dest;
+ maskbit = revBitMask[_xpos & 7];
+ y = _ypos;
+ src = _srcptr;
+ dst = _backbuff_ptr;
+ len = _replen;
+ color = _repcolor;
+ height = _height2;
+ scrheight = _outheight;
+
+ if (_docontinue)
+ goto StartPos;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (color && y < scrheight && !((*mask | mask[_imgbufoffs]) & maskbit)) {
+ pcolor = _palette[color];
+ if (pcolor == 13)
+ pcolor = _shadow_table[*dst];
+ *dst = pcolor;
+ }
+ dst += 320;
+ y++;
+ mask += 40;
+ if (!--height) {
+ if (!--_width2)
+ return;
+ height = _height;
+ dst -= _ypitch;
+ y = _ypostop;
+ if (_scaleIndexXStep != 1) {
+ maskbit <<= 1;
+ if (!maskbit) {
+ maskbit = 1;
+ _mask_ptr--;
+ }
+ } else {
+ maskbit >>= 1;
+ if (!maskbit) {
+ maskbit = 0x80;
+ _mask_ptr++;
+ }
+ }
+ mask = _mask_ptr;
+ }
+ StartPos:;
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc3()
+{
+ byte *mask, *src, *dst;
+ byte maskbit, len, height, pcolor, width;
+ int color, t;
+ uint y;
+
+ mask = _mask_ptr_dest;
+ maskbit = revBitMask[_xpos & 7];
+ y = _ypos;
+ src = _srcptr;
+ dst = _backbuff_ptr;
+ len = _replen;
+ color = _repcolor;
+ height = _height2;
+ width = _width2;
+
+ if (_docontinue)
+ goto StartPos;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (cost_scaleTable[_scaleIndexY++] < _scaleY) {
+ if (color && y < _outheight && !((*mask | mask[_imgbufoffs]) & maskbit)) {
+ pcolor = _palette[color];
+ if (pcolor == 13)
+ pcolor = _shadow_table[*dst];
+ *dst = pcolor;
+ }
+ dst += 320;
+ mask += 40;
+ y++;
+ }
+ if (!--height) {
+ if (!--width)
+ return;
+ height = _height;
+ y = _ypostop;
+ _scaleIndexY = _scaleIndexYTop;
+ t = _scaleIndexX;
+ _scaleIndexX = t + _scaleIndexXStep;
+ if (cost_scaleTable[t] < _scaleX) {
+ _xpos += _scaleIndexXStep;
+ if (_xpos >= 320)
+ return;
+ maskbit = revBitMask[_xpos & 7];
+ _backbuff_ptr += _scaleIndexXStep;
+ }
+ dst = _backbuff_ptr;
+ mask = _mask_ptr + (_xpos >> 3);
+ }
+ StartPos:;
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc2()
+{
+ byte *mask, *src, *dst;
+ byte maskbit, len, height, pcolor, width;
+ int color, t;
+ uint y;
+
+ mask = _mask_ptr_dest;
+ maskbit = revBitMask[_xpos & 7];
+ y = _ypos;
+ src = _srcptr;
+ dst = _backbuff_ptr;
+ len = _replen;
+ color = _repcolor;
+ height = _height2;
+ width = _width2;
+
+ if (_docontinue)
+ goto StartPos;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (cost_scaleTable[_scaleIndexY++] < _scaleY) {
+ if (color && y < _outheight && !(*mask & maskbit)) {
+ pcolor = _palette[color];
+ if (pcolor == 13)
+ pcolor = _shadow_table[*dst];
+ *dst = pcolor;
+ }
+ dst += 320;
+ mask += 40;
+ y++;
+ }
+ if (!--height) {
+ if (!--width)
+ return;
+ height = _height;
+ y = _ypostop;
+ _scaleIndexY = _scaleIndexYTop;
+ t = _scaleIndexX;
+ _scaleIndexX = t + _scaleIndexXStep;
+ if (cost_scaleTable[t] < _scaleX) {
+ _xpos += _scaleIndexXStep;
+ if (_xpos >= 320)
+ return;
+ maskbit = revBitMask[_xpos & 7];
+ _backbuff_ptr += _scaleIndexXStep;
+ }
+ dst = _backbuff_ptr;
+ mask = _mask_ptr + (_xpos >> 3);
+ }
+ StartPos:;
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc1()
+{
+ byte *mask, *src, *dst, *dstorg;
+ byte maskbit, len, height, pcolor, width;
+ int color, t;
+ uint y;
+
+ mask = _mask_ptr = _mask_ptr_dest;
+ maskbit = revBitMask[_xpos & 7];
+ y = _ypos;
+ src = _srcptr;
+ dstorg = dst = _backbuff_ptr;
+ len = _replen;
+ color = _repcolor;
+ height = _height2;
+ width = _width2;
+
+ if (_docontinue)
+ goto StartPos;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (cost_scaleTable[_scaleIndexY++] < _scaleY) {
+ if (color && y < _outheight) {
+ pcolor = _palette[color];
+ if (pcolor == 13)
+ pcolor = _shadow_table[*dst];
+ *dst = pcolor;
+ }
+ dst += 320;
+ y++;
+ }
+ if (!--height) {
+ if (!--width)
+ return;
+ height = _height;
+ y = _ypostop;
+ _scaleIndexY = _scaleIndexYTop;
+ t = _scaleIndexX;
+ _scaleIndexX = t + _scaleIndexXStep;
+ if (cost_scaleTable[t] < _scaleX) {
+ _xpos += _scaleIndexXStep;
+ if (_xpos >= 320)
+ return;
+ _backbuff_ptr += _scaleIndexXStep;
+ }
+ dst = _backbuff_ptr;
+ }
+ StartPos:;
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc6_ami()
+{
+ byte len;
+ byte *src, *dst;
+ byte width, height, pcolor;
+ int color;
+ int step = _scaleIndexXStep;
+ uint x;
+ uint y;
+ uint scrheight;
+
+ x = _xpos;
+ y = _ypos;
+ src = _srcptr;
+ dst = _backbuff_ptr;
+ scrheight = _outheight;
+ width = _width;
+ height = _height2;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (color && x >= 0 && x < 320) {
+ pcolor = _palette[color];
+/* if (pcolor == 13) {
+ pcolor = _shadow_table[*dst];
+ }*/
+ *dst = pcolor;
+ }
+
+ dst += step;
+ x += step;
+ if (!--width) {
+ if (!--height)
+ return;
+ width = _width;
+ dst += 320-step*_width;
+ x = _xpos;
+ y++;
+ if (y >= scrheight)
+ return;
+ }
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc5_ami()
+{
+ byte *mask, *src, *dst;
+ byte maskbit, len, width, height, pcolor;
+ uint y, scrheight;
+ int color, x;
+ int step = _scaleIndexXStep;
+
+ mask = _mask_ptr = _mask_ptr_dest;
+ maskbit = revBitMask[_xpos & 7];
+ x = _xpos;
+ y = _ypos;
+ src = _srcptr;
+ dst = _backbuff_ptr;
+ scrheight = _outheight;
+ width = _width;
+ height = _height2;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (color && x >=0 && x < 320 && !(*mask & maskbit)) {
+ pcolor = _palette[color];
+/* if (pcolor == 13)
+ pcolor = _shadow_table[*dst];*/
+ *dst = pcolor;
+ }
+ dst += step;
+ x += step;
+ if (step != 1) {
+ maskbit <<= 1;
+ if (!maskbit)
+ {
+ maskbit = 1;
+ mask--;
+ }
+ } else {
+ maskbit >>= 1;
+ if (!maskbit)
+ {
+ maskbit = 0x80;
+ mask++;
+ }
+ }
+ if (!--width) {
+ if (!--height)
+ return;
+ width = _width;
+ x = _xpos;
+ y++;
+ dst += 320-step*_width;
+ _mask_ptr+=40;
+ mask = _mask_ptr;
+ maskbit = revBitMask[_xpos & 7];
+ if (y >= scrheight)
+ return;
+ }
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc4_ami()
+{
+ byte *mask, *src, *dst;
+ byte maskbit, len, width, height, pcolor;
+ uint y, scrheight;
+ int color, x;
+ int step = _scaleIndexXStep;
+
+ mask = _mask_ptr = _mask_ptr_dest;
+ maskbit = revBitMask[_xpos & 7];
+ x = _xpos;
+ y = _ypos;
+ src = _srcptr;
+ dst = _backbuff_ptr;
+ scrheight = _outheight;
+ height = _height2;
+ width = _width;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (color && x >= 0 && x < 320 && !((*mask | mask[_imgbufoffs]) & maskbit)) {
+ pcolor = _palette[color];
+/* if (pcolor == 13)
+ pcolor = _shadow_table[*dst];*/
+ *dst = pcolor;
+ }
+ dst += step;
+ x += step;
+ if (step != 1) {
+ maskbit <<= 1;
+ if (!maskbit) {
+ maskbit = 1;
+ mask--;
+ }
+ } else {
+ maskbit >>= 1;
+ if (!maskbit) {
+ maskbit = 0x80;
+ mask++;
+ }
+ }
+ if (!--width) {
+ if (!--height)
+ return;
+ width = _width;
+ y++;
+ x = _xpos;
+ dst += 320-step*_width;
+ _mask_ptr+= 40;
+ mask = _mask_ptr;
+ maskbit = revBitMask[_xpos & 7];
+ if (y >= scrheight)
+ return;
+ }
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc3_ami()
+{
+ byte *mask, *src, *dst;
+ byte maskbit, len, height, pcolor, width;
+ int color, t;
+ uint y;
+ uint oldXpos, oldScaleIndexX;
+
+ mask = _mask_ptr_dest;
+ dst = _backbuff_ptr;
+ height = _height2;
+ width = _width;
+ src = _srcptr;
+ maskbit = revBitMask[_xpos & 7];
+ y = _ypos;
+ oldXpos = _xpos;
+ oldScaleIndexX = _scaleIndexX;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+ do {
+ if (cost_scaleTable[_scaleIndexY] < _scaleY) {
+ if (color && _xpos >= 0 && _xpos < 320 && !((*mask | mask[_imgbufoffs]) & maskbit)) {
+ pcolor = _palette[color];
+/* if (pcolor == 13)
+ pcolor = _shadow_table[*dst];*/
+ *dst = pcolor;
+ }
+
+ t = _scaleIndexX;
+ _scaleIndexX = t + _scaleIndexXStep;
+ if (cost_scaleTable[t] < _scaleX) {
+ _xpos += _scaleIndexXStep;
+ dst += _scaleIndexXStep;
+ maskbit = revBitMask[_xpos & 7];
+ }
+ mask = _mask_ptr + (_xpos >> 3);
+ }
+ if (!--width) {
+ if (!--height)
+ return;
+
+ if (y >= _outheight)
+ return;
+
+ if (_xpos != oldXpos) {
+ dst += 320-(_xpos-oldXpos);
+ _mask_ptr += 40;
+ mask = _mask_ptr;
+ y++;
+ }
+ width = _width;
+ _xpos = oldXpos;
+ _scaleIndexX = oldScaleIndexX;
+ _scaleIndexY++;
+ }
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc2_ami()
+{
+ byte *mask, *src, *dst;
+ byte maskbit, len, height, pcolor, width;
+ int color, t;
+ uint y;
+ uint oldXpos, oldScaleIndexX;
+
+ mask = _mask_ptr_dest;
+ dst = _backbuff_ptr;
+ height = _height2;
+ width = _width;
+ src = _srcptr;
+ maskbit = revBitMask[_xpos & 7];
+ y = _ypos;
+
+ oldXpos = _xpos;
+ oldScaleIndexX = _scaleIndexX;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+ do {
+ if (cost_scaleTable[_scaleIndexY] < _scaleY) {
+ if (color && _xpos >= 0 && _xpos < 320 && !(*mask & maskbit)) {
+ pcolor = _palette[color];
+/* if (pcolor == 13)
+ pcolor = _shadow_table[*dst];*/
+ *dst = pcolor;
+ }
+ t = _scaleIndexX;
+ _scaleIndexX = t + _scaleIndexXStep;
+ if (cost_scaleTable[t] < _scaleX) {
+ _xpos += _scaleIndexXStep;
+ dst += _scaleIndexXStep;
+ maskbit = revBitMask[_xpos & 7];
+ _backbuff_ptr += _scaleIndexXStep;
+ }
+ mask = _mask_ptr + (_xpos >> 3);
+ }
+ if (!--width) {
+ if (!--height)
+ return;
+
+ if (y >= _outheight)
+ return;
+
+ if (_xpos != oldXpos) {
+ dst += 320-(_xpos-oldXpos);
+ _mask_ptr += 40;
+ mask = _mask_ptr;
+ y++;
+ }
+ width = _width;
+ _xpos = oldXpos;
+ _scaleIndexX = oldScaleIndexX;
+ _scaleIndexY++;
+ }
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc1_ami()
+{
+ byte *mask, *src, *dst;
+ byte maskbit, len, height, pcolor, width;
+ uint y;
+ int color;
+ int t, x;
+ uint oldXpos, oldScaleIndexX;
+
+ mask = _mask_ptr = _mask_ptr_dest;
+ maskbit = revBitMask[_xpos & 7];
+ x = _xpos;
+ y = _ypos;
+
+ dst = _backbuff_ptr;
+ height = _height2;
+ width = _width;
+ src = _srcptr;
+
+ oldXpos = _xpos;
+ oldScaleIndexX = _scaleIndexX;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do {
+ if (cost_scaleTable[_scaleIndexY] < _scaleY) {
+ if (color && _xpos >= 0 && _xpos < 320) {
+ pcolor = _palette[color];
+/* if (pcolor == 13)
+ pcolor = _shadow_table[*dst];*/
+ *dst = pcolor;
+ }
+
+ t = _scaleIndexX;
+ _scaleIndexX = t + _scaleIndexXStep;
+ if (cost_scaleTable[t] < _scaleX) {
+ _xpos += _scaleIndexXStep;
+ dst += _scaleIndexXStep;
+ }
+ }
+ if (!--width) {
+ if (!--height)
+ return;
+
+ if (y >= _outheight)
+ return;
+
+ if (_xpos != oldXpos) {
+ dst += 320-(_xpos-oldXpos);
+ y++;
+ }
+ width = _width;
+ _xpos = oldXpos;
+ _scaleIndexX = oldScaleIndexX;
+ _scaleIndexY++;
+ }
+ } while (--len);
+ } while (1);
+}
+
+void CostumeRenderer::proc_special(Actor *a, byte mask2)
+{
+ byte *mask, *src, *dst, *dstorg;
+ byte maskbit, len, height, pcolor, width;
+ uint y;
+ int color;
+ int t;
+
+ byte shadow1;
+ byte shadow2;
+ byte shadow3;
+ byte shadow4;
+ byte shadow5;
+
+ shadow1 = a->shadow_mode & 0x80;
+ shadow2 = a->shadow_mode & 0x40;
+ shadow3 = a->shadow_mode & 0x20;
+ shadow4 = a->shadow_mode & 0x10;
+ shadow5 = a->shadow_mode & 0x0F;
+
+ mask = _mask_ptr = _mask_ptr_dest;
+ maskbit = revBitMask[_xpos & 7];
+ y = _ypos;
+
+ mask = _mask_ptr_dest;
+ dstorg = dst = _backbuff_ptr;
+ height = _height2;
+ width = _width2;
+ len = _replen;
+ color = _repcolor;
+ src = _srcptr;
+
+ if (_mirror == 0)
+ shadow5 = -shadow5;
+
+ maskbit = revBitMask[_xpos & 7];
+
+ dst = _backbuff_ptr;
+
+ if (mask2 != 0 && mask2 < 3)
+ _imgbufoffs = 0;
+
+ if (_docontinue)
+ goto StartPos;
+
+ do {
+ len = *src++;
+ color = len >> _shrval;
+ len &= _maskval;
+ if (!len)
+ len = *src++;
+
+ do { // ok
+ if (cost_scaleTable[_scaleIndexY++] < _scaleY) {
+ if (color && y < _outheight) {
+ if (!mask2 || (mask2 && !((*mask | mask[_imgbufoffs]) & maskbit))) {
+ if (shadow3 == 0) {
+ pcolor = _palette[color];
+ if (pcolor != 13)
+ goto proc_special_end;
+
+ }
+ if (shadow2 != 0) {
+ warning("proc_special: shadow2 unimplemented");
+ pcolor = 0;
+ } else // we don't need all the random stuff, just the background copy
+ {
+ pcolor = _vm->_proc_special_palette[*dst];
+ }
+ proc_special_end:;
+ *dst = pcolor;
+ }
+ }
+ dst += 320;
+ mask += 40;
+ y++;
+ }
+ if (!--height) {
+ if (!--width)
+ return;
+ height = _height;
+ y = _ypostop;
+ _scaleIndexY = _scaleIndexYTop;
+ t = _scaleIndexX;
+ _scaleIndexX = t + _scaleIndexXStep;
+ if (cost_scaleTable[t] < _scaleX) {
+ _xpos += _scaleIndexXStep;
+ if (_xpos >= 320)
+ return;
+ maskbit = revBitMask[_xpos & 7];
+ _backbuff_ptr += _scaleIndexXStep;
+ }
+ dst = _backbuff_ptr;
+ mask = _mask_ptr + (_xpos >> 3);
+ }
+ StartPos:;
+ } while (--len);
+ } while (1);
+
+}
+
+void LoadedCostume::loadCostume(int id)
+{
+ _ptr = _vm->getResourceAddress(rtCostume, id);
+
+ if (_vm->_features & GF_AFTER_V6) {
+ _ptr += 8;
+ } else if (!(_vm->_features & GF_SMALL_HEADER)) {
+ _ptr += 2;
+ }
+
+ switch (_ptr[7] & 0x7F) {
+ case 0x58:
+ _numColors = 16;
+ break;
+ case 0x59:
+ _numColors = 32;
+ break;
+ case 0x60: /* New since version 6 */
+ _numColors = 16;
+ break;
+ case 0x61: /* New since version 6 */
+ _numColors = 32;
+ break;
+ default:
+ error("Costume %d is invalid", id);
+ }
+
+ _dataptr = _ptr + READ_LE_UINT16(_ptr + _numColors + 8);
+}
+
+byte CostumeRenderer::drawOneSlot(Actor *a, int slot)
+{
+
+ if (!(_vm->_features & GF_AFTER_V7)) {
+ int i;
+ int code;
+ CostumeData *cd = &a->cost;
+
+ if (cd->curpos[slot] == 0xFFFF || cd->stopped & (1 << slot))
+ return 0;
+
+ i = cd->curpos[slot] & 0x7FFF;
+
+ _frameptr = _loaded._ptr + READ_LE_UINT16(_loaded._ptr + _loaded._numColors + slot * 2 + 10);
+
+ code = _loaded._dataptr[i] & 0x7F;
+
+ _srcptr = _loaded._ptr + READ_LE_UINT16(_frameptr + code * 2);
+
+ if (code != 0x7B) {
+ if (!(_vm->_features & GF_OLD256) || code < 0x79)
+ return mainRoutine(a, slot, code);
+ }
+ }
+
+ return 0;
+
+}
+
+byte CostumeRenderer::drawCostume(Actor *a)
+{
+ int i;
+ byte r = 0;
+
+ _xmove = _ymove = 0;
+ for (i = 0; i != 16; i++)
+ r |= drawOneSlot(a, i);
+ return r;
+}
+
+int Scumm::cost_frameToAnim(Actor *a, int frame)
+{
+ return newDirToOldDir(a->facing) + frame * 4;
+}
+
+void Scumm::cost_decodeData(Actor *a, int frame, uint usemask)
+{
+ byte *p, *r;
+ uint mask, j;
+ int i;
+ byte extra, cmd;
+ byte *dataptr;
+ int anim;
+ LoadedCostume lc(this);
+
+ lc.loadCostume(a->costume);
+
+ anim = cost_frameToAnim(a, frame);
+
+ p = lc._ptr;
+ if (anim > p[6]) {
+ return;
+ }
+
+ r = p + READ_LE_UINT16(p + anim * 2 + lc._numColors + 42);
+ if (r == p) {
+ return;
+ }
+
+ if (_features & GF_OLD256)
+ dataptr = p + *(p + lc._numColors + 8);
+ else
+ dataptr = p + READ_LE_UINT16(p + lc._numColors + 8);
+
+ mask = READ_LE_UINT16(r);
+ r += 2;
+ i = 0;
+ do {
+ if (mask & 0x8000) {
+ if (_features & GF_OLD256) {
+ j = 0;
+ j = *(r);
+ r++;
+ if (j == 0xFF)
+ j = 0xFFFF;
+ } else {
+ j = READ_LE_UINT16(r);
+ r += 2;
+ }
+ if (usemask & 0x8000) {
+ if (j == 0xFFFF) {
+ a->cost.curpos[i] = 0xFFFF;
+ a->cost.start[i] = 0;
+ a->cost.frame[i] = frame;
+ } else {
+ extra = *r++;
+ cmd = dataptr[j];
+ if (cmd == 0x7A) {
+ a->cost.stopped &= ~(1 << i);
+ } else if (cmd == 0x79) {
+ a->cost.stopped |= (1 << i);
+ } else {
+ a->cost.curpos[i] = a->cost.start[i] = j;
+ a->cost.end[i] = j + (extra & 0x7F);
+ if (extra & 0x80)
+ a->cost.curpos[i] |= 0x8000;
+ a->cost.frame[i] = frame;
+ }
+ }
+ } else {
+ if (j != 0xFFFF)
+ r++;
+ }
+ }
+ i++;
+ usemask <<= 1;
+ mask <<= 1;
+ } while ((uint16)mask);
+}
+
+void CostumeRenderer::setPalette(byte *palette)
+{
+ int i;
+ byte color;
+
+ for (i = 0; i < _loaded._numColors; i++) {
+ if ((_vm->_vars[_vm->VAR_CURRENT_LIGHTS] & LIGHTMODE_actor_color) || (_vm->_features & GF_AFTER_V6)) {
+ color = palette[i];
+ if (color == 255)
+ color = _loaded._ptr[8 + i];
+ } else {
+ color = (i == 12) ? 0 : 8;
+ }
+ _palette[i] = color;
+ }
+}
+
+void CostumeRenderer::setFacing(uint16 facing)
+{
+ _mirror = newDirToOldDir(facing) != 0 || (_loaded._ptr[7] & 0x80);
+}
+
+void CostumeRenderer::setCostume(int costume)
+{
+ _loaded.loadCostume(costume);
+}
+
+byte LoadedCostume::increaseAnims(Actor *a)
+{
+ int i;
+ byte r = 0;
+
+ for (i = 0; i != 16; i++) {
+ if (a->cost.curpos[i] != 0xFFFF)
+ r += increaseAnim(a, i);
+ }
+ return r;
+}
+
+byte LoadedCostume::increaseAnim(Actor *a, int slot)
+{
+ int highflag;
+ int i, end;
+ byte code, nc;
+
+ if (a->cost.curpos[slot] == 0xFFFF)
+ return 0;
+
+ highflag = a->cost.curpos[slot] & 0x8000;
+ i = a->cost.curpos[slot] & 0x7FFF;
+ end = a->cost.end[slot];
+ code = _dataptr[i] & 0x7F;
+
+ do {
+ if (!highflag) {
+ if (i++ >= end)
+ i = a->cost.start[slot];
+ } else {
+ if (i != end)
+ i++;
+ }
+ nc = _dataptr[i];
+
+ if (nc == 0x7C) {
+ a->cost.animCounter1++;
+ if (a->cost.start[slot] != end)
+ continue;
+ } else {
+ if (_vm->_features & GF_AFTER_V6) {
+ if (nc >= 0x71 && nc <= 0x78) {
+ _vm->_sound->addSoundToQueue2(a->sound[nc - 0x71]);
+ if (a->cost.start[slot] != end)
+ continue;
+ }
+ } else {
+ if (nc == 0x78) {
+ a->cost.animCounter2++;
+ if (a->cost.start[slot] != end)
+ continue;
+ }
+ }
+ }
+
+ a->cost.curpos[slot] = i | highflag;
+ return (_dataptr[i] & 0x7F) != code;
+ } while (1);
+}
+
+bool Scumm::isCostumeInUse(int cost)
+{
+ int i;
+ Actor *a;
+
+ if (_roomResource != 0)
+ for (i = 1; i < NUM_ACTORS; i++) {
+ a = derefActor(i);
+ if (a->isInCurrentRoom() && a->costume == cost)
+ return true;
+ }
+
+ return false;
+}