aboutsummaryrefslogtreecommitdiff
path: root/costume.cpp
diff options
context:
space:
mode:
authorLudvig Strigeus2001-10-09 14:30:12 +0000
committerLudvig Strigeus2001-10-09 14:30:12 +0000
commitc30932afbe1af874e3a2aeb95fa4ee5de4d6e38e (patch)
tree192b56f3908880c5a513a366f616341bcb47056e /costume.cpp
downloadscummvm-rg350-c30932afbe1af874e3a2aeb95fa4ee5de4d6e38e.tar.gz
scummvm-rg350-c30932afbe1af874e3a2aeb95fa4ee5de4d6e38e.tar.bz2
scummvm-rg350-c30932afbe1af874e3a2aeb95fa4ee5de4d6e38e.zip
Initial revision
svn-id: r3408
Diffstat (limited to 'costume.cpp')
-rw-r--r--costume.cpp701
1 files changed, 701 insertions, 0 deletions
diff --git a/costume.cpp b/costume.cpp
new file mode 100644
index 0000000000..6fa98e8165
--- /dev/null
+++ b/costume.cpp
@@ -0,0 +1,701 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ *
+ * 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.
+ *
+ * Change Log:
+ * $Log$
+ * Revision 1.1 2001/10/09 14:30:14 strigeus
+ * Initial revision
+ *
+ *
+ */
+
+#include "stdafx.h"
+#include "scumm.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;
+
+ checkHeap();
+
+ _maskval = 0xF;
+ _shrval = 4;
+ if (_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;
+
+ _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;
+ _vscreenheight = _vm->virtscr[0].height;
+ _vm->updateDirtyRect(0, _left, _right+1,_top,_bottom,1<<a->number);
+
+ if ((int)_top >= (int)_vscreenheight || _bottom <= 0) {
+ checkHeap();
+ return 0;
+ }
+
+ _ypitch = _height * 320;
+ _docontinue = 0;
+ b = 1;
+ if (_left > 319 || _right <= 0)
+ return 0;
+ if (_mirror) {
+ _ypitch--;
+ if (scaling==0) {
+ s = -_xpos;
+ }
+ if (s > 0) {
+ _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) {
+ _width2 -= s;
+ ignorePakCols(s);
+ _xpos = 319;
+ _docontinue = 1;
+ } else {
+ s = -1 - _left;
+ if (s <= 0)
+ b = 2;
+ else
+ _width2 -= s;
+ }
+ }
+
+ if (_top > _vscreenheight || _top < 0)
+ _top = 0;
+
+ if (_bottom > _vscreenheight)
+ _bottom = _vscreenheight;
+
+ if (a->top > _top)
+ a->top = _top;
+
+ if (a->bottom < _bottom)
+ a->bottom = _bottom;
+
+ if (_height2 + _top >= 256) {
+ checkHeap();
+ return 2;
+ }
+
+ _where_to_draw_ptr = _vm->getResourceAddress(0xA, 5) + _vm->virtscr[0].xstart + _ypos*320 + _xpos;
+ _bg_ptr = _vm->getResourceAddress(0xA, 1) + _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 (_zbuf) {
+ masking = _vm->isMaskActiveAt(_left, _top, _right, _bottom,
+ _vm->getResourceAddress(0xA, 9) + _vm->_imgBufOffs[_zbuf] + _vm->_screenStartStrip
+ );
+ }
+
+ if (_zbuf || charsetmask) {
+ _mask_ptr = _vm->getResourceAddress(0xA, 9) + _ypos*40 + _vm->_screenStartStrip;
+
+ _imgbufoffs = _vm->_imgBufOffs[_zbuf];
+ if (!charsetmask && _zbuf!=0)
+ _mask_ptr += _imgbufoffs;
+ _mask_ptr_dest = _mask_ptr + _xpos / 8;
+ }
+
+ checkHeap();
+
+ switch ((scaling<<2)|(masking<<1)|charsetmask) {
+ case 0:
+ proc6();
+ break;
+ case 1: case 2:
+ proc5();
+ break;
+ case 3:
+ proc4();
+ break;
+ case 4:
+ proc1();
+ break;
+ case 5:case 6:
+ proc2();
+ break;
+ case 7:
+ proc3();
+ break;
+ }
+
+ checkHeap();
+ return b;
+}
+
+void CostumeRenderer::proc6() {
+ byte len;
+ byte *src, *dst;
+ byte width,height,pcolor;
+ int color;
+ uint y;
+ uint scrheight;
+
+ y = _ypos;
+ len = _replen;
+ src = _srcptr;
+ dst = _bg_ptr;
+ color = _repcolor;
+ scrheight = _vscreenheight;
+ width = _width2;
+ height = _height2;
+
+ 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 = _transEffect[*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 = _bg_ptr;
+ len = _replen;
+ color = _repcolor;
+ scrheight = _vscreenheight;
+ height = _height2;
+
+ 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 = _transEffect[*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 = _bg_ptr;
+ len = _replen;
+ color = _repcolor;
+ scrheight = _vscreenheight;
+ height = _height2;
+
+ 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 = _transEffect[*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() {
+ warning("COST_Proc3: not implemented");
+}
+
+void CostumeRenderer::proc2() {
+ byte *mask,*src,*dst;
+ byte maskbit,len,height,pcolor,width;
+ int color,t;
+ uint y;
+
+ mask = _mask_ptr_dest;
+ dst = _bg_ptr;
+ height = _height2;
+ width = _width2;
+ len = _replen;
+ color = _repcolor;
+ src = _srcptr;
+ maskbit = revBitMask[_xpos&7];
+ y = _ypos;
+
+ 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 < _vscreenheight && !(*mask&maskbit)) {
+ pcolor = _palette[color];
+ if (pcolor==13)
+ pcolor = _transEffect[*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];
+ _bg_ptr += _scaleIndexXStep;
+ }
+ dst = _bg_ptr;
+ mask = _mask_ptr + (_xpos>>3);
+ }
+StartPos:;
+ } while (--len);
+ } while(1);
+
+}
+
+void CostumeRenderer::proc1() {
+ byte *mask,*src,*dst;
+ byte maskbit,len,height,pcolor,width;
+ uint y;
+ int color;
+ int t;
+
+#if 0
+ debug(1, "proc1(): (%d %d),(%d %d %d),(%d %d %d),(%d %d,%d %d,%d %d),(%d %d)",
+ _xpos, _ypos,
+ _width2, _height2, _height,
+ _replen,_repcolor,_docontinue,
+ _scaleX, _scaleY, _scaleIndexX, _scaleIndexY,
+ _scaleIndexXStep, _scaleIndexYStep,
+ _scaleIndexYTop,_vscreenheight
+ );
+#endif
+
+ mask = _mask_ptr = _mask_ptr_dest;
+ maskbit = revBitMask[_xpos&7];
+ y = _ypos;
+
+ dst = _bg_ptr;
+ height = _height2;
+ width = _width2;
+ len = _replen;
+ color = _repcolor;
+ src = _srcptr;
+
+ 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 < _vscreenheight) {
+ pcolor = _palette[color];
+ if (pcolor==13)
+ pcolor = _transEffect[*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;
+ _bg_ptr += _scaleIndexXStep;
+ }
+ dst = _bg_ptr;
+ }
+StartPos:;
+ } while (--len);
+ } while(1);
+}
+
+void CostumeRenderer::loadCostume(int id) {
+ _ptr = _vm->getResourceAddress(3, id) + 2;
+ switch(_ptr[7]&0x7F) {
+ case 0x58:
+ _numColors = 16;
+ break;
+ case 0x59:
+ _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) {
+ int i;
+ int code;
+ CostumeData *cd = &a->cost;
+
+ if (cd->a[slot]==0xFFFF || cd->hdr & (1<<slot))
+ return 0;
+
+ i = cd->a[slot]&0x7FFF;
+ _frameptr = _ptr + READ_LE_UINT16(_ptr + _numColors + slot*2 + 10);
+ code = _dataptr[i]&0x7F;
+ _srcptr = _ptr + READ_LE_UINT16(_frameptr + code*2);
+
+ if (code != 0x7B) {
+ 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;
+}
+
+byte CostumeRenderer::animateOneSlot(CostumeData *cd, int slot) {
+ int highflag;
+ int i,end,code;
+
+ if (cd->a[slot]==0xFFFF)
+ return 0;
+
+ highflag = cd->a[slot]&0x8000;
+ i = cd->a[slot]&0x7FFF;
+ end = cd->c[slot];
+ code=_dataptr[i]&0x7F;
+
+ do {
+ if (!highflag) {
+ if (i++ >= end)
+ i = cd->b[slot];
+ } else {
+ if (i != end)
+ i++;
+ }
+
+ if (_dataptr[i]==0x7C) {
+ cd->animCounter1++;
+ if(cd->b[slot] != end)
+ continue;
+ }
+
+ if (_dataptr[i]==0x78) {
+ cd->animCounter2++;
+ if(cd->b[slot] != end)
+ continue;
+ }
+
+ cd->a[slot] = i|highflag;
+ return (_dataptr[i]&0x7F) != code;
+ } while(1);
+}
+
+byte CostumeRenderer::animate(CostumeData *cd) {
+ int i;
+ byte r = 0;
+
+ for (i=0; i<16; i++) {
+ if(cd->a[i]!=0xFFFF)
+ r+=animateOneSlot(cd, i);
+ }
+ return r;
+}
+