diff options
author | Ludvig Strigeus | 2001-10-09 14:30:12 +0000 |
---|---|---|
committer | Ludvig Strigeus | 2001-10-09 14:30:12 +0000 |
commit | c30932afbe1af874e3a2aeb95fa4ee5de4d6e38e (patch) | |
tree | 192b56f3908880c5a513a366f616341bcb47056e /costume.cpp | |
download | scummvm-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.cpp | 701 |
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; +} + |