aboutsummaryrefslogtreecommitdiff
path: root/akos.cpp
diff options
context:
space:
mode:
authorLudvig Strigeus2001-11-26 19:57:57 +0000
committerLudvig Strigeus2001-11-26 19:57:57 +0000
commit38e2a886ce152ed2b0cfe9777a0514a10c56de04 (patch)
treeb208fd89d2050005c2e79851f6101c6a94860a7a /akos.cpp
parent7b959f62677cf18f52d53123a4d8eb819d01a828 (diff)
downloadscummvm-rg350-38e2a886ce152ed2b0cfe9777a0514a10c56de04.tar.gz
scummvm-rg350-38e2a886ce152ed2b0cfe9777a0514a10c56de04.tar.bz2
scummvm-rg350-38e2a886ce152ed2b0cfe9777a0514a10c56de04.zip
very simple full throttle support, use the FULL_THROTTLE define. (will fix later)
modified some actor parts to work better with full throttle (most likely new bugs because of that). directions are now stored as angles instead of left/right/up/down implemented loadFlObject (flobjects are currently saved in the savestate, will fix that also) svn-id: r3505
Diffstat (limited to 'akos.cpp')
-rw-r--r--akos.cpp1040
1 files changed, 1040 insertions, 0 deletions
diff --git a/akos.cpp b/akos.cpp
new file mode 100644
index 0000000000..8d429f143a
--- /dev/null
+++ b/akos.cpp
@@ -0,0 +1,1040 @@
+/* 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.
+ *
+ * $Header$
+ *
+ */
+#include "stdafx.h"
+#include "scumm.h"
+
+#if defined(FULL_THROTTLE)
+
+bool Scumm::akos_hasManyDirections(Actor *a) {
+ byte *akos;
+ AkosHeader *akhd;
+
+ akos = getResourceAddress(rtCostume, a->costume);
+ assert(akos);
+ akhd = (AkosHeader*)findResource(MKID('AKHD'), akos);
+ return (akhd->flags&2) != 0;
+}
+
+
+int Scumm::akos_frameToAnim(Actor *a, int frame) {
+ if (akos_hasManyDirections(a)) {
+ error("akos_frameToAnim: hasManyDirections not supported");
+ } else {
+ return newDirToOldDir(a->facing) + frame * 4;
+ }
+}
+
+void Scumm::akos_decodeData(Actor *a, int frame, uint usemask) {
+ uint anim;
+ byte *akos,*r;
+ AkosHeader *akhd;
+ uint offs;
+ int i;
+ byte code;
+ uint32 start,len;
+ uint16 mask;
+
+ if (a->costume==0)
+ return;
+
+ anim = akos_frameToAnim(a, frame);
+
+ akos = getResourceAddress(rtCostume, a->costume);
+ assert(akos);
+
+ akhd = (AkosHeader*)findResource(MKID('AKHD'), akos);
+
+ if (anim>=READ_LE_UINT16(&akhd->num_anims))
+ return;
+
+ r = findResourceData(MKID('AKCH'), akos);
+ assert(r);
+
+ offs = READ_LE_UINT16(r + anim * sizeof(uint16));
+ if (offs==0)
+ return;
+ r += offs;
+
+ i = 0;
+ mask = READ_LE_UINT16(r);
+ r+=sizeof(uint16);
+ do {
+ if (mask&0x8000) {
+ code = *r++;
+ if (usemask&0x8000) {
+ switch(code) {
+ case 1:
+ a->cost.active[i] = 0;
+ a->cost.frame[i] = frame;
+ a->cost.end[i] = 0;
+ a->cost.start[i] = 0;
+ a->cost.curpos[i] = 0;
+ break;
+ case 4:
+ a->cost.stopped |= 1<<i;
+ break;
+ case 5:
+ a->cost.stopped &= ~(1<<i);
+ break;
+ default:
+ start = READ_LE_UINT16(r);
+ len = READ_LE_UINT16(r+sizeof(uint16));
+ r+=sizeof(uint16)*2;
+
+ a->cost.active[i] = code;
+ a->cost.frame[i] = frame;
+ a->cost.end[i] = start + len;
+ a->cost.start[i] = start;
+ a->cost.curpos[i] = start;
+ break;
+ }
+ } else {
+ if (code!=1 && code!=4 && code!=5)
+ r+=sizeof(uint16)*2;
+ }
+ }
+ i++;
+ mask<<=1;
+ usemask<<=1;
+ } while ((uint16)mask);
+}
+
+void Scumm::akos_setPalette(AkosRenderer *ar, byte *palette) {
+ byte *akos, *akpl;
+ uint size, i;
+
+ akpl = findResource(MKID('AKPL'), ar->akos);
+ size = READ_BE_UINT32(akpl+4) - 8;
+ akpl += 8;
+
+ if (size > 256)
+ error("akos_setPalette: %d is too many colors", size);
+
+ for(i=0; i<size; i++) {
+ ar->palette[i] = palette[i]!=0xFF ? palette[i] : akpl[i];
+ }
+}
+
+void Scumm::akos_setCostume(AkosRenderer *ar, int costume) {
+ ar->akos = getResourceAddress(rtCostume, costume);
+ assert(ar->akos);
+
+ ar->akhd = (AkosHeader*)findResource(MKID('AKHD'), ar->akos);
+ ar->akof = (AkosOffset*)(findResource(MKID('AKOF'), ar->akos)+8);
+ ar->akci = (findResource(MKID('AKCI'), ar->akos)+8);
+ ar->aksq = (findResource(MKID('AKSQ'), ar->akos)+8);
+ ar->akcd = (findResource(MKID('AKCD'), ar->akos)+8);
+ ar->akpl = (findResource(MKID('AKPL'), ar->akos)+8);
+ ar->codec = READ_LE_UINT16(&ar->akhd->codec);
+}
+
+void Scumm::akos_setFacing(AkosRenderer *ar, Actor *a) {
+ ar->mirror = (newDirToOldDir(a->facing)!=0 || ar->akhd->flags&1);
+ if (a->flip)
+ ar->mirror ^= 1;
+}
+
+bool Scumm::akos_drawCostume(AkosRenderer *ar) {
+ int i;
+ bool result = false;
+
+ ar->move_x = ar->move_y = 0;
+ for(i=0; i<16; i++)
+ result |= akos_drawCostumeChannel(ar, i);
+ return result;
+}
+
+bool Scumm::akos_drawCostumeChannel(AkosRenderer *ar, int chan) {
+ uint code;
+ byte *p;
+ AkosOffset *off;
+ AkosCI *akci;
+ uint i,extra;
+
+ if (!ar->cd->active[chan] || ar->cd->stopped&(1<<chan))
+ return false;
+
+ p = ar->aksq + ar->cd->curpos[chan];
+
+ code = p[0];
+ if (code & 0x80) code = (code<<8)|p[1];
+
+ if (code==AKC_Return)
+ return false;
+
+ if (code!=AKC_ComplexChan) {
+ off = ar->akof + (code & 0xFFF);
+
+ assert( (code & 0xFFF)*6 < READ_BE_UINT32((byte*)ar->akof - 4)-8 );
+
+ assert( (code&0x7000) == 0);
+
+ ar->srcptr = ar->akcd + READ_LE_UINT32(&off->akcd);
+ akci = (AkosCI*)ar->akci + READ_LE_UINT16(&off->akci);
+
+ ar->move_x_cur = ar->move_x + (int16)READ_LE_UINT16(&akci->rel_x);
+ ar->move_y_cur = ar->move_y + (int16)READ_LE_UINT16(&akci->rel_y);
+ ar->width = READ_LE_UINT16(&akci->width);
+ ar->height = READ_LE_UINT16(&akci->height);
+ ar->move_x += (int16)READ_LE_UINT16(&akci->move_x);
+ ar->move_y -= (int16)READ_LE_UINT16(&akci->move_y);
+
+ switch(ar->codec) {
+ case 1:
+ akos_codec1(ar);
+ break;
+ case 5:
+ akos_codec5(ar);
+ break;
+ case 16:
+ akos_codec16(ar);
+ break;
+ default:
+ error("akos_drawCostumeChannel: invalid codec %d", ar->codec);
+ }
+ } else {
+ extra = p[2];
+ p+=3;
+
+ for(i=0; i!=extra; i++) {
+ code = p[4];
+ if (code&0x80) code = ((code&0xF)<<8)|p[5];
+ off = ar->akof + code;
+
+ ar->srcptr = ar->akcd + READ_LE_UINT32(&off->akcd);
+ akci = (AkosCI*)(ar->akci + READ_LE_UINT16(&off->akci));
+
+ ar->move_x_cur = ar->move_x + (int16)READ_LE_UINT16(p+0);
+ ar->move_y_cur = ar->move_y + (int16)READ_LE_UINT16(p+2);
+
+ p += (p[4]&0x80) ? 6 : 5;
+
+ ar->width = READ_LE_UINT16(&akci->width);
+ ar->height = READ_LE_UINT16(&akci->height);
+
+ switch(ar->codec) {
+ case 1:
+ akos_codec1(ar);
+ break;
+ case 5:
+ akos_codec5(ar);
+ break;
+ case 16:
+ akos_codec16(ar);
+ break;
+ default:
+ error("akos_drawCostumeChannel: invalid codec %d", ar->codec);
+ }
+ }
+ }
+
+ return true;
+}
+
+void akos_c1_0y_decode(AkosRenderer *ar) {
+ byte len,color;
+ byte *src, *dst;
+ int height;
+ uint y;
+ uint scrheight;
+
+ len = ar->v1.replen;
+ src = ar->srcptr;
+ dst = ar->v1.destptr;
+ color = ar->v1.repcolor;
+ scrheight = ar->outheight;
+ height = ar->height;
+ y = ar->v1.y;
+
+ if (ar->v1.doContinue) goto StartPos;
+
+ do {
+ len = *src++;
+ color = len>>ar->v1.shl;
+ len &= ar->v1.mask;
+ if (!len) len = *src++;
+
+ do {
+ if (color && y < scrheight) {
+ *dst = ar->palette[color];
+ }
+
+ dst += ar->outwidth;
+ y++;
+ if (!--height) {
+ if (!--ar->v1.skip_width)
+ return;
+ dst -= ar->v1.y_pitch;
+ height = ar->height;
+ y = ar->v1.y;
+ }
+StartPos:;
+ } while (--len);
+ } while (1);
+}
+
+#if 0
+void akos_c1_spec1(AkosRenderer *ar) {
+ byte *mask,*src,*dst,*dstorg;
+ byte maskbit,len,height,pcolor,width;
+ uint y;
+ int color;
+ int t;
+
+ mask = _mask_ptr = ar->v1.mask_ptr_dest;
+ maskbit = revBitMask[ar_xpos&7];
+ y = _ypos;
+
+ dstorg = dst = _backbuff_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;
+ _backbuff_ptr += _scaleIndexXStep;
+ }
+ dst = _backbuff_ptr;
+ }
+StartPos:;
+ } while (--len);
+ } while(1);
+}
+#endif
+
+const byte default_scale_table[768] = {
+0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFE,
+0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFE,
+0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF,
+};
+
+
+void Scumm::akos_codec1(AkosRenderer *ar) {
+ int num_colors;
+ bool use_scaling;
+ int i,j;
+ int x,x_right,x_left,skip,tmp_x,tmp_y;
+ int y,y_top,y_bottom;
+ byte *stab;
+ bool y_clipping;
+ bool charsetmask;
+ bool masking;
+ int step;
+
+ /* implement custom scale table */
+ ar->v1.scaletable = default_scale_table;
+
+ /* Setup color decoding variables */
+ num_colors = READ_BE_UINT32(ar->akpl-4)-8;
+ if (num_colors == 32) {
+ ar->v1.mask = (1<<3)-1;
+ ar->v1.shl = 3;
+ } else if (num_colors == 64) {
+ ar->v1.mask = (1<<2)-1;
+ ar->v1.shl = 2;
+ } else {
+ ar->v1.mask = (1<<4)-1;
+ ar->v1.shl = 4;
+ }
+
+ use_scaling = (ar->scale_x!=0xFF) || (ar->scale_y!=0xFF);
+
+ use_scaling = false;
+
+ x = ar->x;
+ y = ar->y;
+
+ if (use_scaling) {
+
+ /* Scale direction */
+ ar->v1.scaleXstep = -1;
+ if (ar->move_x_cur < 0) {
+ ar->move_x_cur = -ar->move_x_cur;
+ ar->v1.scaleXstep = 1;
+ }
+
+ if (ar->mirror) {
+ /* Adjust X position */
+ tmp_x = 0x180 - ar->move_x_cur;
+ j = tmp_x;
+ for(i=0; i<ar->move_x_cur; i++) {
+ if (ar->v1.scaletable[j++] < ar->scale_x)
+ x -= ar->v1.scaleXstep;
+ }
+
+ x_left = x_right = x;
+
+ j = tmp_x;
+ for(i=0,skip=0; i<ar->width; i++) {
+ if (x_right < 0) {
+ skip++;
+ tmp_x = j;
+ }
+ if (ar->v1.scaletable[j++] < ar->scale_x)
+ x_right++;
+ }
+ } else {
+ /* No mirror */
+ /* Adjust X position */
+ tmp_x = 0x180 + ar->move_x_cur;
+ j = tmp_x;
+ for(i=0; i<ar->move_x_cur; i++) {
+ if (ar->v1.scaletable[j++] < ar->scale_x)
+ x += ar->v1.scaleXstep;
+ }
+
+ x_left = x_right = x;
+
+ j = tmp_x;
+ for(i=0,skip=0; i<ar->width; i++) {
+ if (x_left >= ar->outwidth) {
+ tmp_x = j;
+ skip++;
+
+ }
+ if (ar->v1.scaletable[j--] < ar->scale_x)
+ x_left--;
+ }
+ }
+
+ if (skip) skip--;
+
+ step = -1;
+ if (ar->move_y_cur < 0) {
+ ar->move_y_cur = -ar->move_y_cur;
+ step = -step;
+ }
+
+ tmp_y = 0x180 - ar->move_y_cur;
+ for(i=0; i<ar->move_y_cur; i++) {
+ if (ar->v1.scaletable[tmp_y++] < ar->scale_y)
+ y -= step;
+ }
+
+ y_top = y_bottom = y;
+ tmp_y = 0x180 - ar->move_y_cur;
+ for(i=0; i<ar->height; i++) {
+ if (ar->v1.scaletable[tmp_y++] < ar->scale_y)
+ y_bottom++;
+ }
+
+ tmp_y = 0x180 - ar->move_y_cur;
+ } else {
+ if (!ar->mirror)
+ ar->move_x_cur = -ar->move_x_cur;
+
+ x += ar->move_x_cur;
+ y += ar->move_y_cur;
+
+ if (ar->mirror) {
+ x_left = x;
+ x_right = x + ar->width;
+ } else {
+ x_right = x;
+ x_left = x - ar->width;
+ }
+
+ y_top = y;
+ y_bottom = y + ar->height;
+
+ tmp_x = 0x180;
+ tmp_y = 0x180;
+ }
+
+ ar->v1.tmp_x = tmp_x;
+ ar->v1.tmp_y = tmp_y;
+ ar->v1.skip_width = ar->width;
+
+ ar->v1.scaleXstep = -1;
+ if (ar->mirror)
+ ar->v1.scaleXstep = -ar->v1.scaleXstep;
+
+ if ((uint)y_top >= (uint)ar->outheight || y_bottom <= 0)
+ return;
+
+ if ((uint)x_left >= (uint)ar->outwidth || x_right <= 0)
+ return;
+
+ updateDirtyRect(0, x_left, x_right, y_top, y_bottom, 1<<ar->dirty_id);
+
+ ar->v1.doContinue = false;
+
+ ar->v1.y_pitch = ar->height * ar->outwidth;
+
+ if (ar->mirror) {
+ ar->v1.y_pitch--;
+ if (!use_scaling)
+ skip = -x;
+ if (skip > 0) {
+ ar->v1.skip_width -= skip;
+ akos_codec1_ignorePakCols(ar, skip);
+ x = 0;
+ ar->v1.doContinue = true;
+ } else {
+ skip = x_right - ar->outwidth;
+ if (skip > 0)
+ ar->v1.skip_width -= skip;
+ }
+ } else {
+ ar->v1.y_pitch++;
+ if (!use_scaling) {
+ skip = x_right - ar->outwidth + 1;
+ }
+ if (skip > 0) {
+ ar->v1.skip_width -= skip;
+ akos_codec1_ignorePakCols(ar, skip);
+ x = ar->outwidth - 1;
+ ar->v1.doContinue = true;
+ } else {
+ skip = -1 - x_left;
+ if (skip > 0)
+ ar->v1.skip_width -= skip;
+ }
+ }
+
+ ar->v1.x = x;
+ ar->v1.y = y;
+
+ if (ar->v1.skip_width <= 0 || ar->height<=0)
+ return;
+
+
+ y_clipping = (y_bottom > ar->outheight || y_top < 0);
+
+ if ( (uint)y_top > (uint)ar->outheight)
+ y_top = 0;
+
+ if ( (uint) y_bottom > (uint)ar->outheight)
+ y_bottom = ar->outheight;
+
+ if (y_top < ar->draw_top)
+ ar->draw_top = y_top;
+ if (y_bottom > ar->draw_bottom)
+ ar->draw_bottom = y_bottom;
+
+ if (x==-1) x=0; /* ?? */
+
+ ar->v1.destptr = ar->outptr + x + y * ar->outwidth;
+
+ charsetmask = false;
+
+ masking = false;
+ if (ar->clipping) {
+ masking = isMaskActiveAt(x_left, y_top, x_right, y_bottom,
+ getResourceAddress(rtBuffer, 9) + gdi._imgBufOffs[ar->clipping] + _screenStartStrip
+ ) != 0;
+ }
+
+ if (masking || charsetmask || ar->actor_unk1) {
+ ar->v1.mask_ptr = getResourceAddress(rtBuffer, 9) + y*40 + _screenStartStrip;
+ ar->v1.imgbufoffs = gdi._imgBufOffs[ar->clipping];
+ if (!charsetmask && masking) {
+ ar->v1.mask_ptr += ar->v1.imgbufoffs;
+ ar->v1.imgbufoffs = 0;
+ }
+ ar->v1.mask_ptr_dest = ar->v1.mask_ptr + (x >> 3);
+ }
+
+ ar->actor_unk1 = 0;
+
+ if(ar->actor_unk1==0)
+ akos_c1_0y_decode(ar);
+
+#if 0
+
+ switch(ar->actor_unk1) {
+ case 1:
+ akos_c1_spec1(ar);
+ return;
+ case 2:
+ akos_c1_spec2(ar);
+ return;
+ case 3:
+ akos_c1_spec3(ar);
+ return;
+ }
+
+ switch(((byte)y_clipping<<3) | ((byte)use_scaling<<2) | ((byte)masking<<1) | (byte)charsetmask) {
+ case 0: akos_c1_0_decode(ar); break;
+ case 0+8: akos_c1_0y_decode(ar); break;
+ case 2:
+ case 1: akos_c1_12_decode(ar); break;
+ case 2+8:
+ case 1+8: akos_c1_12y_decode(ar); break;
+ case 3+8:
+ case 3: akos_c1_3_decode(ar); break;
+ case 4: akos_c1_4_decode(ar); break;
+ case 4+8: akos_c1_4y_decode(ar); break;
+ case 6:
+ case 5: akos_c1_56_decode(ar); break;
+ case 6+8:
+ case 5+8: akos_c1_56y_decode(ar); break;
+ case 7:
+ case 7+8: akos_c1_7_decode(ar); break;
+ }
+#endif
+}
+
+
+void Scumm::akos_codec1_ignorePakCols(AkosRenderer *ar, int num) {
+ int n;
+ byte repcolor;
+ byte replen;
+ byte *src;
+
+ n = ar->height;
+ if (num>1) n *= num;
+ src = ar->srcptr;
+ do {
+ repcolor = *src++;
+ replen = repcolor & ar->v1.mask;
+ if (replen==0) {
+ replen = *src++;
+ }
+ do {
+ if (!--n) {
+ ar->v1.repcolor = repcolor>>ar->v1.shl;
+ ar->v1.replen = replen;
+ ar->srcptr = src;
+ return;
+ }
+ } while (--replen);
+ } while (1);
+}
+
+
+void Scumm::akos_codec5(AkosRenderer *ar) {
+ warning("akos_codec5: not implemented");
+}
+
+void Scumm::akos_codec16(AkosRenderer *ar) {
+ warning("akos_codec16: not implemented");
+}
+
+
+bool Scumm::akos_increaseAnims(byte *akos, Actor *a) {
+ byte *aksq, *akfo;
+ int i;
+ uint size;
+ bool result;
+
+ aksq = findResource(MKID('AKSQ'), akos) + 8;
+ akfo = findResource(MKID('AKFO'), akos);
+
+ size = 0;
+ if (akfo) {
+ size = (READ_BE_UINT32(akfo)-8)>>1;
+ akfo += 8;
+ }
+
+ result = false;
+ for(i=0;i!=0x10;i++) {
+ if (a->cost.active[i]!=0)
+ result|=akos_increaseAnim(a, i, aksq, (uint16*)akfo, size);
+ }
+ return result;
+}
+
+
+#define GW(o) ((int16)READ_LE_UINT16(aksq+curpos+(o)))
+#define GUW(o) READ_LE_UINT16(aksq+curpos+(o))
+#define GB(o) aksq[curpos+(o)]
+
+bool Scumm::akos_increaseAnim(Actor *a, int chan, byte *aksq, uint16 *akfo, int numakfo) {
+ byte active;
+ uint old_curpos, curpos,end;
+ uint code;
+ bool flag_value;
+ int tmp,tmp2;
+
+ active = a->cost.active[chan];
+ end = a->cost.end[chan];
+ old_curpos = curpos = a->cost.curpos[chan];
+ flag_value = false;
+
+ do {
+
+ code = aksq[curpos];
+ if (code & 0x80) code = (code<<8)|aksq[curpos+1];
+
+ switch(active) {
+ case 6:
+ switch(code) {
+ case AKC_JumpIfSet:
+ case AKC_AddVar:
+ case AKC_SetVar:
+ case AKC_SkipGE:
+ case AKC_SkipG:
+ case AKC_SkipLE:
+ case AKC_SkipL:
+ case AKC_SkipNE:
+ case AKC_SkipE:
+ curpos += 5;
+ break;
+ case AKC_JumpTable:
+ case AKC_SetActorClip:
+ case AKC_Ignore3:
+ case AKC_Ignore2:
+ case AKC_Ignore:
+ case AKC_StartAnim:
+ case AKC_CmdQue3:
+ curpos += 3;
+ break;
+ case AKC_SoundStuff:
+ curpos += 8;
+ break;
+ case AKC_Cmd3:
+ case AKC_SetVarInActor:
+ case AKC_SetDrawOffs:
+ curpos += 6;
+ break;
+ case AKC_ClearFlag:
+ case AKC_HideActor:
+ case AKC_CmdQue3Quick:
+ case AKC_Return:
+ curpos += 2;
+ break;
+ case AKC_JumpGE:
+ case AKC_JumpG:
+ case AKC_JumpLE:
+ case AKC_JumpL:
+ case AKC_JumpNE:
+ case AKC_JumpE:
+ case AKC_Random:
+ curpos += 7;
+ break;
+ case AKC_Flip:
+ case AKC_Jump:
+ curpos += 4;
+ break;
+ case AKC_ComplexChan:
+ curpos += 3;
+ tmp = aksq[curpos-1];
+ while (--tmp >= 0) {
+ curpos += 4;
+ curpos += (aksq[curpos]&0x80) ? 2 : 1;
+ }
+ break;
+ default:
+ if (code&0xC000)
+ error("akos_increaseAnim: invalid code %x", code);
+ curpos += (code&0x8000) ? 2 : 1;
+ }
+ break;
+ case 2:
+ curpos += (code&0x8000) ? 2 : 1;
+ if (curpos > end)
+ curpos = a->cost.start[chan];
+ break;
+ case 3:
+ if (curpos != end)
+ curpos += (code&0x8000) ? 2 : 1;
+ break;
+ }
+
+ code = aksq[curpos];
+ if (code & 0x80) code = (code<<8)|aksq[curpos+1];
+
+ if (flag_value && code!=AKC_ClearFlag)
+ continue;
+
+ switch(code) {
+ case AKC_StartAnimInActor:
+ akos_queCommand(4,
+ derefActorSafe(getAnimVar(a, GB(2)), "akos_increaseAnim:29"),
+ getAnimVar(a, GB(3)),
+ 0
+ );
+ continue;
+
+ case AKC_Random:
+ setAnimVar(a, GB(6), getRandomNumberRng(GW(2),GW(4)));
+ continue;
+ case AKC_SkipGE:
+ case AKC_SkipG:
+ case AKC_SkipLE:
+ case AKC_SkipL:
+ case AKC_SkipNE:
+ case AKC_SkipE:
+ if ( !akos_compare(getAnimVar(a, GB(4)),GW(2), code-AKC_SkipStart) )
+ flag_value = true;
+ continue;
+ case AKC_IncVar:
+ setAnimVar(a, 0, getAnimVar(a, 0)+1);
+ continue;
+ case AKC_SetVar:
+ setAnimVar(a, GB(4), GW(2));
+ continue;
+ case AKC_AddVar:
+ setAnimVar(a, GB(4), getAnimVar(a, GB(4)) + GW(2) );
+ continue;
+ case AKC_Flip:
+ a->flip = GW(2) != 0;
+ continue;
+ case AKC_CmdQue3:
+ tmp = GB(2);
+ if ((uint)tmp < 8)
+ akos_queCommand(3, a, a->sound[tmp], 0);
+ continue;
+ case AKC_CmdQue3Quick:
+ akos_queCommand(3, a, a->sound[1], 0);
+ continue;
+ case AKC_StartAnim:
+ akos_queCommand(4, a, GB(2), 0);
+ continue;
+ case AKC_StartVarAnim:
+ akos_queCommand(4, a, getAnimVar(a, GB(2)), 0);
+ continue;
+ case AKC_SetVarInActor:
+ setAnimVar(
+ derefActorSafe(getAnimVar(a, GB(2)),"akos_increaseAnim:9"),
+ GB(3), GW(4)
+ );
+ continue;
+ case AKC_HideActor:
+ akos_queCommand(1, a, 0, 0);
+ continue;
+ case AKC_SetActorClip:
+ akos_queCommand(5, a, GB(2), 0);
+ continue;
+ case AKC_SoundStuff:
+ tmp = GB(2);
+ if (tmp >= 8)
+ continue;
+ tmp2 = GB(4);
+ if (tmp2<1 || tmp2>3)
+ error("akos_increaseAnim:8 invalid code %d", tmp2);
+ akos_queCommand(tmp2+6, a, a->sound[tmp], GB(6));
+ continue;
+ case AKC_SetDrawOffs:
+ akos_queCommand(6, a, GW(2), GW(4));
+ continue;
+ case AKC_JumpTable:
+ if (akfo==NULL)
+ error("akos_increaseAnim: no AKFO table");
+ tmp = getAnimVar(a, GB(2)) - 1;
+ if (tmp<0 || tmp >= numakfo-1)
+ error("akos_increaseAnim: invalid jump value %d",tmp);
+ curpos = READ_LE_UINT16(&akfo[tmp]);
+ break;
+ case AKC_JumpIfSet:
+ if (!getAnimVar(a, GB(4)))
+ continue;
+ setAnimVar(a, GB(4), 0);
+ curpos = GUW(2);
+ break;
+
+ case AKC_ClearFlag:
+ flag_value = false;
+ continue;
+
+ case AKC_Jump:
+ curpos = GUW(2);
+ break;
+
+ case AKC_Return:
+ case AKC_ComplexChan:
+ break;
+
+ case AKC_Ignore:
+ case AKC_Ignore2:
+ case AKC_Ignore3:
+ continue;
+
+ case AKC_JumpE:
+ case AKC_JumpNE:
+ case AKC_JumpL:
+ case AKC_JumpLE:
+ case AKC_JumpG:
+ case AKC_JumpGE:
+ if ( !akos_compare(getAnimVar(a, GB(4)), GW(2), code - AKC_JumpStart) )
+ continue;
+ curpos = GUW(2);
+ break;
+
+ default:
+ if ((code&0xC000)==0xC000)
+ error("Undefined uSweat token %X", code);
+ }
+ break;
+ } while(1);
+
+ int code2 = aksq[curpos];
+ if (code2 & 0x80) code2 = (code2<<8)|aksq[curpos+1];
+ assert((code2&0xC000)!=0xC000 || code2==AKC_ComplexChan || code2==AKC_Return);
+
+ a->cost.curpos[chan] = curpos;
+
+ return curpos != old_curpos;
+}
+
+void Scumm::akos_queCommand(byte cmd, Actor *a, int param_1, int param_2) {
+// warning("akos_queCommand(%d,%d,%d,%d)", cmd, a->number, param_1, param_2);
+}
+
+
+bool Scumm::akos_compare(int a, int b, byte cmd) {
+ switch(cmd) {
+ case 0: return a==b;
+ case 1: return a!=b;
+ case 2: return a<b;
+ case 3: return a<=b;
+ case 4: return a>b;
+ default: return a>=b;
+ }
+}
+
+int Scumm::getAnimVar(Actor *a, byte var) {
+ assert(var>=0 && var<=15);
+ return a->animVariable[var];
+}
+
+void Scumm::setAnimVar(Actor *a, byte var, int value) {
+ assert(var>=0 && var<=15);
+ a->animVariable[var] = value;
+}
+
+
+#endif \ No newline at end of file