diff options
author | Max Horn | 2002-08-21 16:07:07 +0000 |
---|---|---|
committer | Max Horn | 2002-08-21 16:07:07 +0000 |
commit | ce46866403fdcc479cf9d67e4d430409b15dadc3 (patch) | |
tree | 75ebfaa1ed13f549959d76d3ce101c3e66f5451b /scumm/akos.cpp | |
parent | 662256f25dbe43abf67077a804e225738765f009 (diff) | |
download | scummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.tar.gz scummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.tar.bz2 scummvm-rg350-ce46866403fdcc479cf9d67e4d430409b15dadc3.zip |
Initial revision
svn-id: r4785
Diffstat (limited to 'scumm/akos.cpp')
-rw-r--r-- | scumm/akos.cpp | 1199 |
1 files changed, 1199 insertions, 0 deletions
diff --git a/scumm/akos.cpp b/scumm/akos.cpp new file mode 100644 index 0000000000..78eabfeb14 --- /dev/null +++ b/scumm/akos.cpp @@ -0,0 +1,1199 @@ +/* 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 "akos.h" + +bool Scumm::akos_hasManyDirections(Actor *a) +{ + if (_features & GF_NEW_COSTUMES) { + byte *akos; + AkosHeader *akhd; + + akos = getResourceAddress(rtCostume, a->costume); + assert(akos); + + akhd = (AkosHeader *) findResourceData(MKID('AKHD'), akos); + return (akhd->flags & 2) != 0; + } + return 0; +} + +int Scumm::akos_frameToAnim(Actor *a, int frame) +{ + if (akos_hasManyDirections(a)) + return toSimpleDir(1, a->facing) + frame * 8; + 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; + uint16 start, len; + uint16 mask; + + if (a->costume == 0) + return; + + anim = akos_frameToAnim(a, frame); + + akos = getResourceAddress(rtCostume, a->costume); + assert(akos); + + akhd = (AkosHeader *) findResourceData(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 AkosRenderer::setPalette(byte *new_palette) +{ + byte *the_akpl; + uint size, i; + + the_akpl = _vm->findResourceData(MKID('AKPL'), akos); + size = _vm->getResourceDataSize(akpl); + + if (size > 256) + error("akos_setPalette: %d is too many colors", size); + + for (i = 0; i < size; i++) { + palette[i] = new_palette[i] != 0xFF ? new_palette[i] : the_akpl[i]; + } +} + +void AkosRenderer::setCostume(int costume) +{ + akos = _vm->getResourceAddress(rtCostume, costume); + assert(akos); + + akhd = (AkosHeader *) _vm->findResourceData(MKID('AKHD'), akos); + akof = (AkosOffset *) _vm->findResourceData(MKID('AKOF'), akos); + akci = _vm->findResourceData(MKID('AKCI'), akos); + aksq = _vm->findResourceData(MKID('AKSQ'), akos); + akcd = _vm->findResourceData(MKID('AKCD'), akos); + akpl = _vm->findResourceData(MKID('AKPL'), akos); + codec = READ_LE_UINT16(&akhd->codec); +} + +void AkosRenderer::setFacing(Actor *a) +{ + mirror = (newDirToOldDir(a->facing) != 0 || akhd->flags & 1); + if (a->flip) + mirror ^= 1; +} + +bool AkosRenderer::drawCostume() +{ + int i; + bool result = false; + + move_x = move_y = 0; + for (i = 0; i < 16; i++) + result |= drawCostumeChannel(i); + return result; +} + +bool AkosRenderer::drawCostumeChannel(int chan) +{ + uint code; + byte *p; + AkosOffset *off; + AkosCI *the_akci; + uint i, extra; + + if (!cd->active[chan] || cd->stopped & (1 << chan)) + return false; + + p = aksq + 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 = akof + (code & 0xFFF); + + assert((code & 0xFFF) * 6 < READ_BE_UINT32_UNALIGNED((byte *)akof - 4) - 8); + assert((code & 0x7000) == 0); + + srcptr = akcd + READ_LE_UINT32(&off->akcd); + the_akci = (AkosCI *) (akci + READ_LE_UINT16(&off->akci)); + + move_x_cur = move_x + (int16)READ_LE_UINT16(&the_akci->rel_x); + move_y_cur = move_y + (int16)READ_LE_UINT16(&the_akci->rel_y); + width = READ_LE_UINT16(&the_akci->width); + height = READ_LE_UINT16(&the_akci->height); + move_x += (int16)READ_LE_UINT16(&the_akci->move_x); + move_y -= (int16)READ_LE_UINT16(&the_akci->move_y); + + switch (codec) { + case 1: + codec1(); + break; + case 5: + codec5(); + break; + case 16: + codec16(); + break; + default: + error("akos_drawCostumeChannel: invalid codec %d", 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 = akof + code; + + srcptr = akcd + READ_LE_UINT32(&off->akcd); + the_akci = (AkosCI *) (akci + READ_LE_UINT16(&off->akci)); + + move_x_cur = move_x + (int16)READ_LE_UINT16(p + 0); + move_y_cur = move_y + (int16)READ_LE_UINT16(p + 2); + + p += (p[4] & 0x80) ? 6 : 5; + + width = READ_LE_UINT16(&the_akci->width); + height = READ_LE_UINT16(&the_akci->height); + + switch (codec) { + case 1: + codec1(); + break; + case 5: + codec5(); + break; + case 16: + codec16(); + break; + default: + error("akos_drawCostumeChannel: invalid codec %d", 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 (len) + 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); +} + +void akos_generic_decode(AkosRenderer * ar) +{ + byte *src, *dst; + byte len, height, maskbit; + uint y, color; + const byte *scaleytab, *mask; + + + y = ar->v1.y; + + len = ar->v1.replen; + src = ar->srcptr; + dst = ar->v1.destptr; + color = ar->v1.repcolor; + height = ar->height; + + scaleytab = &ar->v1.scaletable[ar->v1.tmp_y]; + maskbit = revBitMask[ar->v1.x & 7]; + mask = ar->v1.mask_ptr + (ar->v1.x >> 3); + + if (len) + goto StartPos; + + do { + len = *src++; + color = len >> ar->v1.shl; + len &= ar->v1.mask; + if (!len) + len = *src++; + + do { + if (*scaleytab++ < ar->scale_y) { + if (color && y < ar->outheight + && (!ar->v1.mask_ptr || !((mask[0] | mask[ar->v1.imgbufoffs]) & maskbit))) { + *dst = ar->palette[color]; + } + mask += 40; + dst += ar->outwidth; + y++; + } + if (!--height) { + if (!--ar->v1.skip_width) + return; + height = ar->height; + y = ar->v1.y; + + scaleytab = &ar->v1.scaletable[ar->v1.tmp_y]; + + if (ar->v1.scaletable[ar->v1.tmp_x] < ar->scale_x) { + ar->v1.x += ar->v1.scaleXstep; + if ((uint) ar->v1.x >= 320) + return; + maskbit = revBitMask[ar->v1.x & 7]; + ar->v1.destptr += ar->v1.scaleXstep; + } + mask = ar->v1.mask_ptr + (ar->v1.x >> 3); + ar->v1.tmp_x += ar->v1.scaleXstep; + dst = ar->v1.destptr; + } + StartPos:; + } while (--len); + } while (1); +} + + +void akos_c1_spec1(AkosRenderer * ar) +{ + byte *src, *dst; + byte len, height, pcolor, maskbit; + uint y, color; + const byte *scaleytab, *mask; + + + y = ar->v1.y; + + len = ar->v1.replen; + src = ar->srcptr; + dst = ar->v1.destptr; + color = ar->v1.repcolor; + height = ar->height; + + scaleytab = &ar->v1.scaletable[ar->v1.tmp_y]; + maskbit = revBitMask[ar->v1.x & 7]; + mask = ar->v1.mask_ptr + (ar->v1.x >> 3); + + if (len) + goto StartPos; + + do { + len = *src++; + color = len >> ar->v1.shl; + len &= ar->v1.mask; + if (!len) + len = *src++; + + do { + if (*scaleytab++ < ar->scale_y) { + if (color && y < ar->outheight + && (!ar->v1.mask_ptr || !((mask[0] | mask[ar->v1.imgbufoffs]) & maskbit))) { + pcolor = ar->palette[color]; + if (pcolor == 13) + pcolor = ar->shadow_table[*dst]; + *dst = pcolor; + } + mask += 40; + dst += ar->outwidth; + y++; + } + if (!--height) { + if (!--ar->v1.skip_width) + return; + height = ar->height; + y = ar->v1.y; + + scaleytab = &ar->v1.scaletable[ar->v1.tmp_y]; + + if (ar->v1.scaletable[ar->v1.tmp_x] < ar->scale_x) { + ar->v1.x += ar->v1.scaleXstep; + if ((uint) ar->v1.x >= 320) + return; + maskbit = revBitMask[ar->v1.x & 7]; + ar->v1.destptr += ar->v1.scaleXstep; + } + mask = ar->v1.mask_ptr + (ar->v1.x >> 3); + ar->v1.tmp_x += ar->v1.scaleXstep; + dst = ar->v1.destptr; + } + StartPos:; + } while (--len); + } while (1); +} + +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 AkosRenderer::codec1() +{ + int num_colors; + bool use_scaling; + int i, j; + int cur_x, x_right, x_left, skip = 0, tmp_x, tmp_y; + int cur_y, y_top, y_bottom; + bool y_clipping; + bool masking; + int step; + + + /* implement custom scale table */ + + + + if (_vm->isGlobInMemory(rtString, _vm->_vars[_vm->VAR_CUSTOMSCALETABLE])) { + v1.scaletable = _vm->getStringAddressVar(_vm->VAR_CUSTOMSCALETABLE); + } else { + v1.scaletable = default_scale_table; + } + + /* Setup color decoding variables */ + num_colors = _vm->getResourceDataSize(akpl); + if (num_colors == 32) { + v1.mask = (1 << 3) - 1; + v1.shl = 3; + } else if (num_colors == 64) { + v1.mask = (1 << 2) - 1; + v1.shl = 2; + } else { + v1.mask = (1 << 4) - 1; + v1.shl = 4; + } + + use_scaling = (scale_x != 0xFF) || (scale_y != 0xFF); + + cur_x = x; + cur_y = y; + + if (use_scaling) { + + /* Scale direction */ + v1.scaleXstep = -1; + if (move_x_cur < 0) { + move_x_cur = -move_x_cur; + v1.scaleXstep = 1; + } + + if (mirror) { + /* Adjust X position */ + tmp_x = 0x180 - move_x_cur; + j = tmp_x; + for (i = 0; i < move_x_cur; i++) { + if (v1.scaletable[j++] < scale_x) + cur_x -= v1.scaleXstep; + } + + x_left = x_right = cur_x; + + j = tmp_x; + for (i = 0, skip = 0; i < width; i++) { + if (x_right < 0) { + skip++; + tmp_x = j; + } + if (v1.scaletable[j++] < scale_x) + x_right++; + } + } else { + /* No mirror */ + /* Adjust X position */ + tmp_x = 0x180 + move_x_cur; + j = tmp_x; + for (i = 0; i < move_x_cur; i++) { + if (v1.scaletable[j++] < scale_x) + cur_x += v1.scaleXstep; + } + + x_left = x_right = cur_x; + + j = tmp_x; + for (i = 0, skip = 0; i < width; i++) { + if (x_left >= (int)outwidth) { + tmp_x = j; + skip++; + } + if (v1.scaletable[j--] < scale_x) + x_left--; + } + } + + if (skip) + skip--; + + step = -1; + if (move_y_cur < 0) { + move_y_cur = -move_y_cur; + step = -step; + } + + tmp_y = 0x180 - move_y_cur; + for (i = 0; i < move_y_cur; i++) { + if (v1.scaletable[tmp_y++] < scale_y) + cur_y -= step; + } + + y_top = y_bottom = cur_y; + tmp_y = 0x180 - move_y_cur; + for (i = 0; i < height; i++) { + if (v1.scaletable[tmp_y++] < scale_y) + y_bottom++; + } + + tmp_y = 0x180 - move_y_cur; + } else { + if (!mirror) + move_x_cur = -move_x_cur; + + cur_x += move_x_cur; + cur_y += move_y_cur; + + if (mirror) { + x_left = cur_x; + x_right = cur_x + width; + } else { + x_right = cur_x; + x_left = cur_x - width; + } + + y_top = cur_y; + y_bottom = cur_y + height; + + tmp_x = 0x180; + tmp_y = 0x180; + } + + v1.tmp_x = tmp_x; + v1.tmp_y = tmp_y; + v1.skip_width = width; + + v1.scaleXstep = -1; + if (mirror) + v1.scaleXstep = -v1.scaleXstep; + + if ((uint) y_top >= (uint) outheight || y_bottom <= 0) + return; + + if ((int)x_left >= (int)outwidth || x_right <= 0) + return; + + v1.replen = 0; + v1.y_pitch = height * outwidth; + + if (mirror) { + v1.y_pitch--; + if (!use_scaling) + skip = -cur_x; + if (skip > 0) { + v1.skip_width -= skip; + codec1_ignorePakCols(skip); + cur_x = 0; + } else { + skip = x_right - outwidth; + if (skip > 0) + v1.skip_width -= skip; + } + } else { + v1.y_pitch++; + if (!use_scaling) { + skip = x_right - outwidth + 1; + } + if (skip > 0) { + v1.skip_width -= skip; + codec1_ignorePakCols(skip); + cur_x = outwidth - 1; + } else { + skip = -1 - x_left; + if (skip > 0) + v1.skip_width -= skip; + } + } + + v1.x = cur_x; + v1.y = cur_y; + + if (v1.skip_width <= 0 || height <= 0) + return; + + _vm->updateDirtyRect(0, x_left, x_right, y_top, y_bottom, 1 << dirty_id); + + y_clipping = ((uint) y_bottom > outheight || y_top < 0); + + if ((uint) y_top > (uint) outheight) + y_top = 0; + + if ((uint) y_bottom > (uint) outheight) + y_bottom = outheight; + + if (y_top < draw_top) + draw_top = y_top; + if (y_bottom > draw_bottom) + draw_bottom = y_bottom; + + if (cur_x == -1) + cur_x = 0; /* ?? */ + + v1.destptr = outptr + cur_x + cur_y * outwidth; + + masking = false; + if (clipping) { + masking = _vm->isMaskActiveAt(x_left, y_top, x_right, y_bottom, + _vm->getResourceAddress(rtBuffer, 9) + + _vm->gdi._imgBufOffs[clipping] + _vm->_screenStartStrip) != 0; + } + + v1.mask_ptr = NULL; + + if (masking || charsetmask || shadow_mode) { + v1.mask_ptr = _vm->getResourceAddress(rtBuffer, 9) + cur_y * 40 + _vm->_screenStartStrip; + v1.imgbufoffs = _vm->gdi._imgBufOffs[clipping]; + if (!charsetmask && masking) { + v1.mask_ptr += v1.imgbufoffs; + v1.imgbufoffs = 0; + } + } + + switch (shadow_mode) { + case 1: + akos_c1_spec1(this); + return; + case 2: +// akos_c1_spec2(this); + warning("akos_c1_spec2"); + return; + case 3: +// akos_c1_spec3(this); + warning("akos_c1_spec3"); + return; + } + + akos_generic_decode(this); + +// akos_c1_0y_decode(this); + +#if 0 + + switch (((byte)y_clipping << 3) | ((byte)use_scaling << 2) | ((byte)masking << 1) | (byte)charsetmask) { + case 0: + akos_c1_0_decode(this); + break; + case 0 + 8: + akos_c1_0y_decode(this); + break; + case 2: + case 1: + akos_c1_12_decode(this); + break; + case 2 + 8: + case 1 + 8: + akos_c1_12y_decode(this); + break; + case 3 + 8: + case 3: + akos_c1_3_decode(this); + break; + case 4: + akos_c1_4_decode(this); + break; + case 4 + 8: + akos_c1_4y_decode(this); + break; + case 6: + case 5: + akos_c1_56_decode(this); + break; + case 6 + 8: + case 5 + 8: + akos_c1_56y_decode(this); + break; + case 7: + case 7 + 8: + akos_c1_7_decode(this); + break; + } +#endif +} + + +void AkosRenderer::codec1_ignorePakCols(int num) +{ + int n; + byte repcolor; + byte replen; + byte *src; + + n = height; + if (num > 1) + n *= num; + src = srcptr; + do { + repcolor = *src++; + replen = repcolor & v1.mask; + if (replen == 0) { + replen = *src++; + } + do { + if (!--n) { + v1.repcolor = repcolor >> v1.shl; + v1.replen = replen; + srcptr = src; + return; + } + } while (--replen); + } while (1); +} + + +void AkosRenderer::codec5() +{ + VirtScreen *vs; + BompDrawData bdd; + + int moveX; + int moveY; + int left; + int var_20; + int max_width; + + int right; + int top; + int bottom; + + vs = &_vm->virtscr[0]; + //setBlastObjectMode(shadow_mode); // not implemented yet + moveX = move_x_cur; + moveY = move_y_cur; + + if (!mirror) { + left = (x - moveX - width) + 1; + } else { + left = x + moveX - 1; + } + + var_20 = 0; + max_width = outwidth; + + right = left + width - 1; + top = y + moveY; + bottom = top + height; + + if (left < 0) + left = 0; + if (left > max_width) + left -= left - max_width; + + // Yazoo: this is not correct, but fix a lots of bugs for the momment + + draw_top = 0; + draw_bottom = vs->height; + + _vm->updateDirtyRect(0, left, right + 1, top, bottom + 1, 1 << dirty_id); + + bdd.dataptr = srcptr; + bdd.out = outptr; + bdd.outheight = outheight; + bdd.outwidth = outwidth; + bdd.scale_x = 0xFF; + bdd.scale_y = 0xFF; + bdd.srcheight = height; + bdd.srcwidth = width; + bdd.x = left + 1; + bdd.y = top; + + _vm->drawBomp(&bdd, 0, bdd.dataptr, 0, 0); +} + +void AkosRenderer::codec16() +{ + warning("akos_codec16: not implemented"); +} + + +bool Scumm::akos_increaseAnims(byte *akos, Actor *a) +{ + byte *aksq, *akfo; + int i; + uint size; + bool result; + + aksq = findResourceData(MKID('AKSQ'), akos); + akfo = findResourceData(MKID('AKFO'), akos); + + size = getResourceDataSize(akfo) >> 1; + + 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(a->getAnimVar(GB(2)), + "akos_increaseAnim:29"), a->getAnimVar(GB(3)), 0); + continue; + + case AKC_Random: + a->setAnimVar(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(a->getAnimVar(GB(4)), GW(2), code - AKC_SkipStart)) + flag_value = true; + continue; + case AKC_IncVar: + a->setAnimVar(0, a->getAnimVar(0) + 1); + continue; + case AKC_SetVar: + a->setAnimVar(GB(4), GW(2)); + continue; + case AKC_AddVar: + a->setAnimVar(GB(4), a->getAnimVar(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, a->getAnimVar(GB(2)), 0); + continue; + case AKC_SetVarInActor: + derefActorSafe(a->getAnimVar(GB(2)), "akos_increaseAnim:9")->setAnimVar(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 = a->getAnimVar(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 (!a->getAnimVar(GB(4))) + continue; + a->setAnimVar(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(a->getAnimVar(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; + } +} |