diff --git a/actor.cpp b/actor.cpp index 6f6d75897e0..1306db5f43b 100644 --- a/actor.cpp +++ b/actor.cpp @@ -28,9 +28,9 @@ void Scumm::initActor(Actor *a, int mode) { a->room = 0; a->x = 0; a->y = 0; - a->facing = 2; + a->facing = 180; } else if (mode==2) { - a->facing = 2; + a->facing = 180; } a->elevation = 0; @@ -50,7 +50,7 @@ void Scumm::initActor(Actor *a, int mode) { a->sound[7] = 0; a->newDirection = 0; a->moving = 0; - a->data8 = 0; + a->unk1 = 0; setActorWalkSpeed(a, 8, 2); @@ -78,6 +78,18 @@ void Scumm::setActorWalkSpeed(Actor *a, uint speedx, uint speedy) { } } +int Scumm::getAngleFromPos(int x, int y) { + if (abs(y)*2 < abs(x)) { + if (x>0) + return 90; + return 270; + } else { + if (y>0) + return 180; + return 0; + } +} + int Scumm::calcMovementFactor(Actor *a, int newX, int newY) { int actorX, actorY; int diffX, diffY; @@ -96,10 +108,10 @@ int Scumm::calcMovementFactor(Actor *a, int newX, int newY) { if (diffY < 0) YXFactor = -YXFactor; + XYFactor = YXFactor * diffX; if (diffY != 0) { - XYFactor = YXFactor * diffX / diffY; + XYFactor /= diffY; } else { - XYFactor = YXFactor * diffX; YXFactor = 0; } @@ -108,10 +120,10 @@ int Scumm::calcMovementFactor(Actor *a, int newX, int newY) { if (diffX < 0) XYFactor = -XYFactor; + YXFactor = XYFactor * diffY; if (diffX != 0) { - YXFactor = XYFactor * diffY / diffX; + YXFactor /= diffX; } else { - YXFactor = XYFactor * diffY; XYFactor = 0; } } @@ -124,88 +136,142 @@ int Scumm::calcMovementFactor(Actor *a, int newX, int newY) { a->walkdata.YXFactor = YXFactor; a->walkdata.xfrac = 0; a->walkdata.yfrac = 0; + + a->newDirection = getAngleFromPos(XYFactor, YXFactor); return actorWalkStep(a); } +int Scumm::remapDirection(Actor *a, int dir) { + int specdir; + byte flags; + + if (!a->ignoreBoxes) { + specdir = _extraBoxFlags[a->walkbox]; + if (specdir) { + if (specdir & 0x8000) { + dir = specdir & 0x3FFF; + } else { + error("getProgrDirChange: special dir not implemented"); + } + } + + flags = getBoxFlags(a->walkbox); + + if ((flags&8) || getClass(a->number, 0x1E)) { + dir = 360 - dir; + } + + if ((flags&0x10) || getClass(a->number, 0x1D)) { + dir = 180 - dir; + } + + switch(flags & 7) { + case 1: + if (dir >= 180) + return 270; + return 90; + case 2: + if (dir <= 90 || dir>270) + return 0; + return 180; + case 3: return 270; + case 4: return 90; + case 5: return 0; + case 6: return 180; + } + } + return normalizeAngle(dir); +} + +int Scumm::updateActorDirection(Actor *a) { + int from,to; + int diff; + + from = toSimpleDir(a->facing); + to = toSimpleDir(remapDirection(a, a->newDirection)); + diff = to - from; + + if (abs(diff) > 2) + diff = -diff; + + if (diff==0) { + } else if (diff>0) { + from++; + } else { + from--; + } + + return fromSimpleDir(from&3); +} + +void Scumm::setActorBox(Actor *a, int box) { + a->walkbox = box; + a->mask = getMaskFromBox(box); + setupActorScale(a); +} + + int Scumm::actorWalkStep(Actor *a) { - int32 XYFactor, YXFactor; - int actorX, actorY, newx, newy; - int newXDist; - int32 tmp,tmp2; - - byte direction; - + int tmpX, tmpY; + int actorX, actorY; + int distX, distY; + int direction; + a->needRedraw = true; a->needBgReset = true; - XYFactor = a->walkdata.XYFactor; - YXFactor = a->walkdata.YXFactor; - - direction = XYFactor>0 ? 1 : 0; - if (abs(YXFactor) * 2 > abs(XYFactor)) - direction = YXFactor>0 ? 2 : 3; - a->newDirection = direction; - - direction = getProgrDirChange(a, 1); - - if (!(a->moving&2) || a->facing!=direction) { - if (a->walkFrame != a->animIndex || a->facing != direction) { - startAnimActor(a, a->walkFrame, direction); - } - a->moving|=2; - } - - actorX = a->walkdata.x; - actorY = a->walkdata.y; - newx = a->walkdata.newx; - newy = a->walkdata.newy; - - if (a->walkbox != a->walkdata.curbox) { - if (checkXYInBoxBounds(a->walkdata.curbox, a->x, a->y)) { - a->walkbox = a->walkdata.curbox; - a->mask = getMaskFromBox(a->walkdata.curbox); - setupActorScale(a); + direction = updateActorDirection(a); + if (!(a->moving&MF_IN_LEG) || a->facing!=direction) { + if (a->walkFrame != a->frame || a->facing != direction) { + startWalkAnim(a, a->walkFrame==a->frame ? 2 : 1, direction); } + a->moving|=MF_IN_LEG; } - newXDist = abs(newx - actorX); - - if (newXDist <= abs(a->x - actorX) && - abs(newy - actorY) <= abs(a->y - actorY) ){ - a->moving&=~2; + actorX = a->x; + actorY = a->y; + + if (a->walkbox != a->walkdata.curbox && + checkXYInBoxBounds(a->walkdata.curbox, actorX, actorY)) { + setActorBox(a, a->walkdata.curbox); + } + + distX = abs(a->walkdata.newx - a->walkdata.x); + distY = abs(a->walkdata.newy - a->walkdata.y); + + if ( + abs(actorX - a->walkdata.x) >= distX && + abs(actorY - a->walkdata.y) >= distY + ) { + a->moving &= ~MF_IN_LEG; return 0; } - XYFactor = (XYFactor>>8) * a->scalex; - YXFactor = (YXFactor>>8) * a->scalex; + tmpX = ((actorX + 8000)<<16) + a->walkdata.xfrac + + (a->walkdata.XYFactor>>8) * a->scalex; + a->walkdata.xfrac = (uint16)tmpX; + actorX = (tmpX>>16) - 8000; + + tmpY = (actorY<<16) + a->walkdata.yfrac + + (a->walkdata.YXFactor>>8) * a->scalex; + a->walkdata.yfrac = (uint16)tmpY; + actorY = (tmpY>>16); - tmp = ((a->x + 8000)<<16) + a->walkdata.xfrac + XYFactor; - tmp2 = (a->y<<16) + a->walkdata.yfrac + YXFactor; - - a->x = (tmp>>16)-8000; - a->y = tmp2>>16; - - if (abs(a->x - actorX) > newXDist) { - a->x = newx; + if (abs(actorX - a->walkdata.x) > distX) { + actorX = a->walkdata.newx; } - if (abs(a->y - actorY) > abs(newy - actorY)) { - a->y = newy; - } - - a->walkdata.xfrac = tmp&0xFFFF; - a->walkdata.yfrac = tmp2&0xFFFF; - - if (a->x == newx && - a->y == newy) { - a->moving&=~2; - return 0; + if (abs(actorY - a->walkdata.y) > distY) { + actorY = a->walkdata.newy; } + a->x = actorX; + a->y = actorY; return 1; } + void Scumm::setupActorScale(Actor *a) { uint16 scale; byte *resptr; @@ -232,68 +298,27 @@ void Scumm::setupActorScale(Actor *a) { a->scaley = (byte)scale; } -int Scumm::getProgrDirChange(Actor *a, int mode) { - int flags; - byte facing, newdir; - byte XYflag, YXflag; - byte lookdir; - - const byte direction_transtab[] = { - 0,2,2,3,2,1,2,3,0,1,2,1,0,1,0,3 - }; - - flags = 0; - if (!a->ignoreBoxes) - flags = getBoxFlags(a->walkbox); - - facing = a->facing; - newdir = a->newDirection; - - XYflag = a->walkdata.XYFactor>0 ? 1 : 0; - YXflag = a->walkdata.YXFactor>0 ? 1 : 0; - - if ((flags&8) || getClass(a->number, 0x1E)) { - if (!(newdir&2)) - newdir^=1; - XYflag = 1 - XYflag; +#if defined(FULL_THROTTLE) +void Scumm::startAnimActor(Actor *a, int frame) { + switch(frame) { + case 1001: frame = a->initFrame; break; + case 1002: frame = a->walkFrame; break; + case 1003: frame = a->standFrame; break; + case 1004: frame = a->talkFrame1; break; + case 1005: frame = a->talkFrame2; break; } - if ((flags&0x10) || getClass(a->number, 0x1D)) { - if (newdir&2) - newdir^=1; - YXflag = 1 - YXflag; + if (a->costume != 0) { + a->animProgress = 0; + a->needRedraw = true; + a->needBgReset = true; + if (frame == a->initFrame) + initActorCostumeData(a); + akos_decodeData(a, frame, (uint)-1); } - - lookdir = direction_transtab[facing*4+newdir]; - - if (!(flags&=0x7)) - return lookdir; - - if (mode==0) { - lookdir = newdir; - if (flags==1 && newdir!=1) - lookdir = 0; - - if (flags==2 && newdir!=3) - lookdir = 2; - } else { - if (flags==1) - lookdir = XYflag; - if (flags==2) - lookdir = 3 - YXflag; - } - if (flags==3) - lookdir=0; - if (flags==4) - lookdir=1; - if (flags==6) - lookdir=2; - if (flags==5) - lookdir = 3; - return lookdir; } - -void Scumm::startAnimActor(Actor *a, int frame, byte direction) { +#else +void Scumm::startAnimActor(Actor *a, int frame) { if (frame==0x38) frame = a->initFrame; @@ -320,27 +345,15 @@ void Scumm::startAnimActor(Actor *a, int frame, byte direction) { initActorCostumeData(a); if (frame!=0x3E) { - decodeCostData(a, frame*4 + direction, -1); + decodeCostData(a, frame, -1); } - - if (a->facing != direction) - fixActorDirection(a, direction); } - a->facing = direction; a->needBgReset = true; } +#endif -void Scumm::initActorCostumeData(Actor *a) { - CostumeData *cd = &a->cost; - int i; - - cd->hdr = 0; - for (i=0; i<16; i++) - cd->a[i] = cd->b[i] = cd->c[i] = cd->d[i] = 0xFFFF; -} - -void Scumm::fixActorDirection(Actor *a, byte direction) { +void Scumm::fixActorDirection(Actor *a, int direction) { uint mask; int i; uint16 vald; @@ -348,69 +361,29 @@ void Scumm::fixActorDirection(Actor *a, byte direction) { if (a->facing == direction) return; + a->facing = direction; + + if (a->costume==0) + return; + +#if !defined(FULL_THROTTLE) + cost.loadCostume(a->costume); +#endif + mask = 0x8000; for (i=0; i<16; i++,mask>>=1) { - vald = a->cost.d[i]; - if (vald==0xFFFF || (vald&3)==direction) + vald = a->cost.frame[i]; + if (vald==0xFFFF) continue; - decodeCostData(a, (vald&0xFC)|direction, mask); +#if !defined(FULL_THROTTLE) + decodeCostData(a, vald, mask); +#else + akos_decodeData(a, vald, mask); +#endif } - a->facing = direction; -} -void Scumm::decodeCostData(Actor *a, int frame, uint usemask) { - byte *p,*r; - uint mask,j; - int i; - byte extra,cmd; - byte *dataptr; - - p = cost._ptr; - if (frame > p[6]) - return; - - r = p + READ_LE_UINT16(p + frame*2 + cost._numColors + 42); - if (r==p) - return; - - dataptr = p + READ_LE_UINT16(p + cost._numColors + 8); - - mask = READ_LE_UINT16(r); - r+=2; - i = 0; - do { - if (mask&0x8000) { - j = READ_LE_UINT16(r); - r+=2; - if (usemask&0x8000) { - if (j==0xFFFF) { - a->cost.a[i] = 0xFFFF; - a->cost.b[i] = 0; - a->cost.d[i] = frame; - } else { - extra = *r++; - cmd = dataptr[j]; - if (cmd==0x7A) { - a->cost.hdr &= ~(1<cost.hdr |= (1<cost.a[i] = a->cost.b[i] = j; - a->cost.c[i] = j + (extra&0x7F); - if (extra&0x80) - a->cost.a[i] |= 0x8000; - a->cost.d[i] = frame; - } - } - } else { - if (j!=0xFFFF) - r++; - } - } - i++; - usemask <<= 1; - mask <<= 1; - } while ((uint16)mask); + a->needRedraw = true; + a->needBgReset = true; } void Scumm::putActor(Actor *a, int x, int y, byte room) { @@ -431,7 +404,7 @@ void Scumm::putActor(Actor *a, int x, int y, byte room) { if (a->visible) { if (_currentRoom == room) { if (a->moving) { - startAnimActor(a, a->standFrame, a->facing); + startAnimActor(a, a->standFrame); a->moving = 0; } adjustActorPos(a); @@ -452,7 +425,7 @@ int Scumm::getActorXYPos(Actor *a) { return 0; } -AdjustBoxResult Scumm::adjustXYToBeInBox(Actor *a, int x, int y) { +AdjustBoxResult Scumm::adjustXYToBeInBox(Actor *a, int x, int y, int pathfrom) { AdjustBoxResult abr,tmp; uint threshold; uint best; @@ -475,6 +448,9 @@ AdjustBoxResult Scumm::adjustXYToBeInBox(Actor *a, int x, int y) { flags = getBoxFlags(box); if (flags&0x80 && (!(flags&0x20) || getClass(a->number, 0x1F)) ) continue; + + if (pathfrom && !getPathToDestBox(pathfrom, box)) + continue; if (!inBoxQuickReject(box, x, y, threshold)) continue; @@ -516,15 +492,15 @@ void Scumm::adjustActorPos(Actor *a) { AdjustBoxResult abr; byte flags; - abr = adjustXYToBeInBox(a, a->x, a->y); + abr = adjustXYToBeInBox(a, a->x, a->y, 0); a->x = abr.x; a->y = abr.y; - a->walkbox = (byte)abr.dist; /* not a dist */ a->walkdata.destbox = (byte)abr.dist; - a->mask = getMaskFromBox(abr.dist); + + setActorBox(a, abr.dist); + a->walkdata.destx = -1; - setupActorScale(a); a->moving = 0; a->cost.animCounter2 = 0; @@ -540,7 +516,7 @@ void Scumm::hideActor(Actor *a) { return; if (a->moving) { - startAnimActor(a, a->standFrame, a->facing); + startAnimActor(a, a->standFrame); a->moving = 0; } a->visible = false; @@ -550,8 +526,15 @@ void Scumm::hideActor(Actor *a) { } void Scumm::turnToDirection(Actor *a, int newdir) { - a->moving = 4; - a->newDirection = newdir; + if (newdir==-1) + return; + + a->moving &= ~4; + + if (newdir != a->facing) { + a->moving = 4; + a->newDirection = newdir; + } } void Scumm::showActor(Actor *a) { @@ -563,7 +546,7 @@ void Scumm::showActor(Actor *a) { ensureResourceLoaded(rtCostume, a->costume); if (a->costumeNeedsInit) { - startAnimActor(a, a->initFrame, a->facing); + startAnimActor(a, a->initFrame); a->costumeNeedsInit = false; } a->moving = 0; @@ -594,7 +577,7 @@ void Scumm::stopTalk() { if (act && act<0x80) { Actor *a = derefActorSafe(act, "stopTalk"); if (_currentRoom == a->room && _useTalkAnims) { - startAnimActor(a, a->talkFrame2, a->facing); + startAnimActor(a, a->talkFrame2); _useTalkAnims = false; } _vars[VAR_TALK_ACTOR] = 0xFF; @@ -637,6 +620,37 @@ void Scumm::playActorSounds() { } } + +void Scumm::startWalkAnim(Actor *a, int cmd, int angle) { + int16 args[16]; + + if (angle == -1) + angle = a->facing; + + if (a->walk_script != 0) { + args[2] = angle; + args[0] = a->number; + args[1] = cmd; + runScript(a->walk_script, 1, 0, args); + } else { + switch(cmd) { + case 1: /* start walk */ + //a->facing = angle; + fixActorDirection(a, angle); + startAnimActor(a, a->walkFrame); + break; + case 2: /* change dir only */ + fixActorDirection(a, angle); + break; + case 3: /* stop walk */ + turnToDirection(a, angle); + startAnimActor(a, a->standFrame); + break; + } + } +} + + void Scumm::walkActor(Actor *a) { int j; @@ -649,41 +663,59 @@ void Scumm::walkActor(Actor *a) { if (a->moving&8) { a->moving = 0; - - j = a->walkdata.destbox; - if (j) { - a->walkbox = j; - a->mask = getMaskFromBox(j); - } - startAnimActor(a, a->standFrame, a->facing); - if (a->walkdata.destdir==0xFF || - a->walkdata.destdir==a->newDirection) - return; - a->newDirection = a->walkdata.destdir; - a->moving = 4; + setActorBox(a, a->walkdata.destbox); + startWalkAnim(a, 3, a->walkdata.destdir); return; } if (a->moving&4) { - j = getProgrDirChange(a, 0); + j = updateActorDirection(a); if (a->facing != j) - startAnimActor(a, 0x3E, j); + fixActorDirection(a,j); else a->moving = 0; return; } - a->walkbox = a->walkdata.curbox; - a->mask = getMaskFromBox(a->walkdata.curbox); - - setupActorScale(a); - a->moving = (a->moving&2)|1; + setActorBox(a, a->walkdata.curbox); + a->moving &= 2; } +#if OLD + a->moving &= ~1; + + if (!a->walkbox) { + a->walkbox = a->walkdata.destbox; + a->walkdata.curbox = a->walkdata.destbox; + a->moving |= 8; + calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty); + return; + } + + if (a->ignoreBoxes || a->walkbox==a->walkdata.destbox) { + a->walkdata.curbox = a->walkbox; + a->moving |= 8; + calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty); + return; + } + j = getPathToDestBox(a->walkbox,a->walkdata.destbox); + if (j==0) { + error("walkActor: no path found between %d and %d", a->walkbox, a->walkdata.destbox); + } + + a->walkdata.curbox = j; + if (findPathTowards(a, a->walkbox, j, a->walkdata.destbox)) { + a->moving |= 8; + calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty); + return; + } + calcMovementFactor(a, _foundPathX, _foundPathY); +#endif +#if 1 do { a->moving&=~1; if (!a->walkbox) { - a->walkbox = a->walkdata.destbox; + setActorBox(a, a->walkdata.destbox); a->walkdata.curbox = a->walkdata.destbox; break; } @@ -701,12 +733,11 @@ void Scumm::walkActor(Actor *a) { if (calcMovementFactor(a, _foundPathX, _foundPathY)) return; - a->walkbox = a->walkdata.curbox; - a->mask = getMaskFromBox(a->walkdata.curbox); - setupActorScale(a); + setActorBox(a, a->walkdata.curbox); } while (1); a->moving |= 8; calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty); +#endif } void Scumm::processActors() { @@ -741,9 +772,6 @@ void Scumm::processActors() { do { a = *ac; if (a->costume) { - setupActorScale(a); - setupCostumeRenderer(&cost, a); - setActorCostPalette(a); CHECK_HEAP drawActorCostume(a); CHECK_HEAP @@ -779,31 +807,83 @@ void Scumm::setActorCostPalette(Actor *a) { } } +#if !defined(FULL_THROTTLE) void Scumm::drawActorCostume(Actor *a) { if (a==NULL || !a->needRedraw) return; - + + setupActorScale(a); + setupCostumeRenderer(&cost, a); + setActorCostPalette(a); + a->top = 0xFF; a->needRedraw = 0; a->bottom = 0; cost.loadCostume(a->costume); - cost._mirror = a->facing!=0 || (cost._ptr[7]&0x80); + cost._mirror = newDirToOldDir(a->facing)!=0 || (cost._ptr[7]&0x80); - if (cost.drawCostume(a)) { - a->needRedraw = true; - a->needBgReset = true;; - } + cost.drawCostume(a); } +#else +void Scumm::drawActorCostume(Actor *a) { + AkosRenderer ar; + + if (a==NULL || !a->needRedraw) + return; + + a->needRedraw = false; + + setupActorScale(a); + + ar.x = a->x - virtscr->xstart; + ar.y = a->y - a->elevation; + ar.scale_x = a->scalex; + ar.scale_y = a->scaley; + ar.clipping = a->neverZClip; + if (ar.clipping == 100) { + ar.clipping = a->mask; + if (ar.clipping > (byte)gdi._numZBuffer) + ar.clipping = gdi._numZBuffer; + } + + ar.outptr = getResourceAddress(rtBuffer, 1) + virtscr->xstart; + ar.outwidth = virtscr->width; + ar.outheight = virtscr->height; + + akos_setCostume(&ar, a->costume); + akos_setPalette(&ar, a->palette); + akos_setFacing(&ar, a); + + ar.dirty_id = a->number; + + ar.cd = &a->cost; + + ar.draw_top = a->top = 0x7fffffff; + ar.draw_bottom = a->bottom = 0; + akos_drawCostume(&ar); + a->top = ar.draw_top; + a->bottom = ar.draw_bottom; +} +#endif void Scumm::actorAnimate(Actor *a) { - if (a==NULL) + byte *akos; + + if (a==NULL || a->costume == 0) return; a->animProgress++; if (a->animProgress >= a->animSpeed) { a->animProgress = 0; + +#if defined(FULL_THROTTLE) + akos = getResourceAddress(rtCostume, a->costume); + assert(akos); + if (akos_increaseAnims(akos, a)) { +#else cost.loadCostume(a->costume); if (cost.animate(a)) { +#endif a->needRedraw = true; a->needBgReset = true; } @@ -811,14 +891,14 @@ void Scumm::actorAnimate(Actor *a) { } void Scumm::setActorRedrawFlags() { - int i,j; - int bits; + uint i,j; + uint32 bits; for (i=0; i<40; i++) { - bits = actorDrawBits[_screenStartStrip+i]; - if (bits&0x3FFF) { + bits = gfxUsageBits[_screenStartStrip+i]; + if (bits&0x3FFFFFFF) { for(j=0; jneedRedraw = true; a->needBgReset = true; @@ -829,11 +909,11 @@ void Scumm::setActorRedrawFlags() { } int Scumm::getActorFromPos(int x, int y) { - uint16 drawbits; + uint32 drawbits; int i; - drawbits = actorDrawBits[x>>3]; - if (!(drawbits & 0x3FFF)) + drawbits = gfxUsageBits[x>>3]; + if (!(drawbits & 0x3FFFFFFF)) return 0; for (i=1; inumber; if (!string[0].no_talk_anim) { - startAnimActor(a,a->talkFrame1,a->facing); + startAnimActor(a,a->talkFrame1); _useTalkAnims = true; } oldact = _vars[VAR_TALK_ACTOR]; @@ -909,31 +989,24 @@ void Scumm::setActorCostume(Actor *a, int c) { void Scumm::startWalkActor(Actor *a, int x, int y, int dir) { AdjustBoxResult abr; - abr = adjustXYToBeInBox(a, x, y); - - _xPos = abr.x; - _yPos = abr.y; + abr = adjustXYToBeInBox(a, x, y, a->walkbox); if (a->room != _currentRoom) { - a->x = _xPos; - a->y = _yPos; - if (dir != 0xFF) + a->x = abr.x; + a->y = abr.y; + if (dir != -1) a->facing = dir; return; } if (a->ignoreBoxes!=0) { - abr.x = _xPos; - abr.y = _yPos; abr.dist = 0; a->walkbox = 0; } else { - if (checkXYInBoxBounds(a->walkdata.destbox, _xPos,_yPos)) { - abr.x = _xPos; - abr.y = _yPos; + if (checkXYInBoxBounds(a->walkdata.destbox, abr.x,abr.y)) { abr.dist = a->walkdata.destbox; } else { - abr = adjustXYToBeInBox(a, _xPos, _yPos); + abr = adjustXYToBeInBox(a, abr.x, abr.y, a->walkbox); } if (a->moving && a->walkdata.destdir == dir && a->walkdata.destx == abr.x @@ -942,10 +1015,7 @@ void Scumm::startWalkActor(Actor *a, int x, int y, int dir) { } if (a->x==abr.x && a->y==abr.y) { - if (dir!=0xFF && dir!=a->facing) { - a->newDirection = dir; - a->moving = 4; - } + turnToDirection(a, dir); return; } @@ -954,7 +1024,6 @@ void Scumm::startWalkActor(Actor *a, int x, int y, int dir) { a->walkdata.destbox = (byte)abr.dist; /* a box */ a->walkdata.destdir = dir; a->moving = (a->moving&2)|1; - a->walkdata.curbox = a->walkbox; } byte *Scumm::getActorName(Actor *a) { @@ -976,4 +1045,8 @@ bool Scumm::isCostumeInUse(int cost) { } return false; -} \ No newline at end of file +} + +void Scumm::remapActor(Actor *a, int b, int c, int d, int e) { + warning("stub remapActor(%d,%d,%d,%d,%d)", a->number, b, c, d, e); +} diff --git a/akos.cpp b/akos.cpp new file mode 100644 index 00000000000..8d429f143aa --- /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<cost.stopped &= ~(1<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; ipalette[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<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; imove_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; iwidth; 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; imove_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; iwidth; 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; imove_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; iheight; 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<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 ab; + 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 diff --git a/boxes.cpp b/boxes.cpp index 96779c4f62a..fc5038760e1 100644 --- a/boxes.cpp +++ b/boxes.cpp @@ -49,71 +49,73 @@ Box *Scumm::getBoxBaseAddr(int box) { } bool Scumm::checkXYInBoxBounds(int b, int x, int y) { + BoxCoords box; + if (b==0) return 0; - getBoxCoordinates(b); + getBoxCoordinates(b, &box); - if (x < box.upperLeftX && x < box.upperRightX && - x < box.lowerLeftX && x < box.lowerRightX) + if (x < box.ul.x && x < box.ur.x && + x < box.ll.x && x < box.lr.x) return 0; - if (x > box.upperLeftX && x > box.upperRightX && - x > box.lowerLeftX && x > box.lowerRightX) + if (x > box.ul.x && x > box.ur.x && + x > box.ll.x && x > box.lr.x) return 0; - if (y < box.upperLeftY && y < box.upperRightY && - y < box.lowerLeftY && y < box.lowerRightY) + if (y < box.ul.y && y < box.ur.y && + y < box.ll.y && y < box.lr.y) return 0; - if (y > box.upperLeftY && y > box.upperRightY && - y > box.lowerLeftY && y > box.lowerRightY) + if (y > box.ul.y && y > box.ur.y && + y > box.ll.y && y > box.lr.y) return 0; - if (box.upperLeftX == box.upperRightX && - box.upperLeftY == box.upperRightY && - box.lowerLeftX == box.lowerRightX && - box.lowerLeftY == box.lowerRightY || - box.upperLeftX == box.lowerRightX && - box.upperLeftY == box.lowerRightY && - box.upperRightX== box.lowerLeftX && - box.upperRightY== box.lowerLeftY) { + if (box.ul.x == box.ur.x && + box.ul.y == box.ur.y && + box.ll.x == box.lr.x && + box.ll.y == box.lr.y || + box.ul.x == box.lr.x && + box.ul.y == box.lr.y && + box.ur.x== box.ll.x && + box.ur.y== box.ll.y) { Point pt; - pt = closestPtOnLine(box.upperLeftX, box.upperLeftY, box.lowerLeftX, box.lowerLeftY, x, y); + pt = closestPtOnLine(box.ul.x, box.ul.y, box.ll.x, box.ll.y, x, y); if (distanceFromPt(x, y, pt.x,pt.y) <= 4) return 1; } if (!getSideOfLine( - box.upperLeftX, box.upperLeftY, box.upperRightX, box.upperRightY, x,y,b)) + box.ul.x, box.ul.y, box.ur.x, box.ur.y, x,y,b)) return 0; if (!getSideOfLine( - box.upperRightX, box.upperRightY, box.lowerLeftX, box.lowerLeftY, x,y,b)) + box.ur.x, box.ur.y, box.ll.x, box.ll.y, x,y,b)) return 0; if (!getSideOfLine( - box.lowerLeftX, box.lowerLeftY, box.lowerRightX, box.lowerRightY, x,y,b)) + box.ll.x, box.ll.y, box.lr.x, box.lr.y, x,y,b)) return 0; if (!getSideOfLine( - box.lowerRightX, box.lowerRightY, box.upperLeftX, box.upperLeftY, x,y,b)) + box.lr.x, box.lr.y, box.ul.x, box.ul.y, x,y,b)) return 0; return 1; } -void Scumm::getBoxCoordinates(int b) { - Box *bp = getBoxBaseAddr(b); - box.upperLeftX = (int16)FROM_LE_16(bp->ulx); - box.upperRightX = (int16)FROM_LE_16(bp->urx); - box.lowerLeftX = (int16)FROM_LE_16(bp->llx); - box.lowerRightX = (int16)FROM_LE_16(bp->lrx); - box.upperLeftY = (int16)FROM_LE_16(bp->uly); - box.upperRightY = (int16)FROM_LE_16(bp->ury); - box.lowerLeftY = (int16)FROM_LE_16(bp->lly); - box.lowerRightY = (int16)FROM_LE_16(bp->lry); +void Scumm::getBoxCoordinates(int boxnum, BoxCoords *box) { + Box *bp = getBoxBaseAddr(boxnum); + box->ul.x = (int16)FROM_LE_16(bp->ulx); + box->ul.y = (int16)FROM_LE_16(bp->uly); + box->ur.x = (int16)FROM_LE_16(bp->urx); + box->ur.y = (int16)FROM_LE_16(bp->ury); + box->ll.x = (int16)FROM_LE_16(bp->llx); + box->ll.y = (int16)FROM_LE_16(bp->lly); + box->lr.x = (int16)FROM_LE_16(bp->lrx); + box->lr.y = (int16)FROM_LE_16(bp->lry); } uint Scumm::distanceFromPt(int x, int y, int ptx, int pty) { @@ -212,30 +214,31 @@ type2:; bool Scumm::inBoxQuickReject(int b, int x, int y, int threshold) { int t; + BoxCoords box; - getBoxCoordinates(b); + getBoxCoordinates(b, &box); if (threshold==0) return 1; t = x - threshold; - if (t > box.upperLeftX && t > box.upperRightX && - t > box.lowerLeftX && t > box.lowerRightX) + if (t > box.ul.x && t > box.ur.x && + t > box.ll.x && t > box.lr.x) return 0; t = x + threshold; - if (t < box.upperLeftX && t < box.upperRightX && - t < box.lowerLeftX && t < box.lowerRightX) + if (t < box.ul.x && t < box.ur.x && + t < box.ll.x && t < box.lr.x) return 0; t = y - threshold; - if (t > box.upperLeftY && t > box.upperRightY && - t > box.lowerLeftY && t > box.lowerRightY) + if (t > box.ul.y && t > box.ur.y && + t > box.ll.y && t > box.lr.y) return 0; t = y + threshold; - if (t < box.upperLeftY && t < box.upperRightY && - t < box.lowerLeftY && t < box.lowerRightY) + if (t < box.ul.y && t < box.ur.y && + t < box.ll.y && t < box.lr.y) return 0; return 1; @@ -246,10 +249,11 @@ AdjustBoxResult Scumm::getClosestPtOnBox(int b, int x, int y) { AdjustBoxResult best; uint dist; uint bestdist = (uint)0xFFFF; + BoxCoords box; - getBoxCoordinates(b); + getBoxCoordinates(b, &box); - pt = closestPtOnLine(box.upperLeftX,box.upperLeftY,box.upperRightX,box.upperRightY,x,y); + pt = closestPtOnLine(box.ul.x,box.ul.y,box.ur.x,box.ur.y,x,y); dist = distanceFromPt(x, y, pt.x, pt.y); if (dist < bestdist) { bestdist = dist; @@ -257,7 +261,7 @@ AdjustBoxResult Scumm::getClosestPtOnBox(int b, int x, int y) { best.y = pt.y; } - pt = closestPtOnLine(box.upperRightX,box.upperRightY,box.lowerLeftX,box.lowerLeftY,x,y); + pt = closestPtOnLine(box.ur.x,box.ur.y,box.ll.x,box.ll.y,x,y); dist = distanceFromPt(x, y, pt.x, pt.y); if (dist < bestdist) { bestdist = dist; @@ -265,7 +269,7 @@ AdjustBoxResult Scumm::getClosestPtOnBox(int b, int x, int y) { best.y = pt.y; } - pt = closestPtOnLine(box.lowerLeftX,box.lowerLeftY,box.lowerRightX,box.lowerRightY,x,y); + pt = closestPtOnLine(box.ll.x,box.ll.y,box.lr.x,box.lr.y,x,y); dist = distanceFromPt(x, y, pt.x, pt.y); if (dist < bestdist) { bestdist = dist; @@ -273,7 +277,7 @@ AdjustBoxResult Scumm::getClosestPtOnBox(int b, int x, int y) { best.y = pt.y; } - pt = closestPtOnLine(box.lowerRightX,box.lowerRightY,box.upperLeftX,box.upperLeftY,x,y); + pt = closestPtOnLine(box.lr.x,box.lr.y,box.ul.x,box.ul.y,x,y); dist = distanceFromPt(x, y, pt.x, pt.y); if (dist < bestdist) { bestdist = dist; @@ -291,9 +295,9 @@ byte *Scumm::getBoxMatrixBaseAddr() { return ptr; } -int Scumm::getPathToDestBox(int from, int to) { +int Scumm::getPathToDestBox(byte from, byte to) { byte *boxm; - int i; + byte i; if (from==to) return to; @@ -316,171 +320,153 @@ int Scumm::getPathToDestBox(int from, int to) { return 0; } -int Scumm::findPathTowards(Actor *a, int box1, int box2, int box3) { - int upperLeftX, upperLeftY; - int upperRightX, upperRightY; - int lowerLeftX, lowerLeftY; - int lowerRightX, lowerRightY; - int i,j,m,n,p,q,r; - int tmp_x, tmp_y; - int tmp; - - getBoxCoordinates(box1); - upperLeftX = box.upperLeftX; - upperLeftY = box.upperLeftY; - upperRightX = box.upperRightX; - upperRightY = box.upperRightY; - lowerLeftX = box.lowerLeftX; - lowerLeftY = box.lowerLeftY; - lowerRightX = box.lowerRightX; - lowerRightY = box.lowerRightY; - getBoxCoordinates(box2); +int Scumm::findPathTowards(Actor *a, byte box1nr, byte box2nr, byte box3nr) { + BoxCoords box1; + BoxCoords box2; + Point tmp; + int i,j; + int flag; + int q,pos; - i = 0; - do { - if (i >= 4) goto ExitPos; - for (j=0; j<4; j++) { - if (upperRightX==upperLeftX && - box.upperLeftX==upperLeftX && - box.upperRightX==upperRightX) { - -ExitPos:; - n = m = 0; - if (upperRightY < upperLeftY) { - m = 1; - SWAP(upperRightY, upperLeftY); + getBoxCoordinates(box1nr,&box1); + getBoxCoordinates(box2nr,&box2); + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + if (box1.ul.x==box1.ur.x && + box1.ul.x==box2.ul.x && + box1.ul.x==box2.ur.x) { + flag = 0; + if (box1.ul.y > box1.ur.y) { + SWAP(box1.ul.y, box1.ur.y); + flag |= 1; } - if (box.upperRightY < box.upperLeftY) { - n = 1; - SWAP(box.upperRightY, box.upperLeftY); + + if (box2.ul.y > box2.ur.y) { + SWAP(box2.ul.y, box2.ur.y); + flag |= 2; } - if (box.upperRightY >= upperLeftY && - box.upperLeftY <= upperRightY && - (box.upperLeftY != upperRightY && - box.upperRightY!= upperLeftY || - upperRightY==upperLeftY || - box.upperRightY==box.upperLeftY)) { - if (box2==box3) { - m = a->walkdata.destx - a->x; - p = a->walkdata.desty - a->y; - tmp = upperLeftX - a->x; - i = a->y; - if (m) { - q = tmp * p; - r = q/m; - if (r==0 && (q<=0 || m<=0) && (q>=0 || m>=0)) { - r = -1; - } - i += r; + + if (box1.ul.y > box2.ur.y || box2.ul.y > box1.ur.y || + (box1.ur.y==box2.ul.y || box2.ur.y==box1.ul.y) && + box1.ul.y!=box1.ur.y && box2.ul.y!=box2.ur.y) { + if (flag&1) + SWAP(box1.ul.y, box1.ur.y); + if (flag&2) + SWAP(box2.ul.y, box2.ur.y); + } else { + if (box2nr == box3nr) { + int diffX = a->walkdata.destx - a->x; + int diffY = a->walkdata.desty - a->y; + int boxDiffX = box1.ul.x - a->x; + + if (diffX!=0) { + int t; + + diffY *= boxDiffX; + t = diffY / diffX; + if (t==0 && (diffY<=0 || diffX<=0) && (diffY>=0 || diffX>=0)) + t = -1; + pos = a->y + t; + } else { + pos = a->y; } } else { - i = a->y; + pos = a->y; } - q = i; - if (q < box.upperLeftY) - q = box.upperLeftY; - if (q > box.upperRightY) - q = box.upperRightY; - if (q < upperLeftY) - q = upperLeftY; - if (q > upperRightY) - q = upperRightY; - if (q==i && box2==box3) + + q = pos; + if (q < box2.ul.y) + q = box2.ul.y; + if (q > box2.ur.y) + q = box2.ur.y; + if (q < box1.ul.y) + q = box1.ul.y; + if (q > box1.ur.y) + q = box1.ur.y; + if (q==pos && box2nr==box3nr) return 1; - _foundPathX = upperLeftX; _foundPathY = q; + _foundPathX = box1.ul.x; return 0; - } else { - if (m) { - SWAP(upperRightY, upperLeftY); - } - if (n) { - SWAP(box.upperRightY, box.upperLeftY); - } } } - if (upperLeftY==upperRightY && - box.upperLeftY==upperLeftY && - box.upperRightY==upperRightY) { - n = m = 0; - if(upperRightX < upperLeftX) { - m = 1; - SWAP(upperRightX, upperLeftX); + + if (box1.ul.y==box1.ur.y && + box1.ul.y==box2.ul.y && + box1.ul.y==box2.ur.y) { + flag = 0; + if (box1.ul.x > box1.ur.x) { + SWAP(box1.ul.x, box1.ur.x); + flag |= 1; } - if (box.upperRightX < box.upperLeftX) { - n = 1; - SWAP(box.upperRightX, box.upperLeftX); + + if (box2.ul.x > box2.ur.x) { + SWAP(box2.ul.x, box2.ur.x); + flag |= 2; } - if (box.upperRightX >= upperLeftX && - box.upperLeftX <= upperRightX && - (box.upperLeftX != upperRightX && - box.upperRightX!= upperLeftX || - upperRightX==upperLeftX || - box.upperRightX==box.upperLeftX)) { - if (box2==box3) { - m = a->walkdata.destx - a->x; - p = a->walkdata.desty - a->y; - i = upperLeftY - a->y; - tmp = a->x; - if (p) { - tmp += i * m / p; + + if (box1.ul.x > box2.ur.x || box2.ul.x > box1.ur.x || + (box1.ur.x==box2.ul.x || box2.ur.x==box1.ul.x) && + box1.ul.x!=box1.ur.x && box2.ul.x!=box2.ur.x) { + if (flag&1) + SWAP(box1.ul.x, box1.ur.x); + if (flag&2) + SWAP(box2.ul.x, box2.ur.x); + } else { + + if (box2nr == box3nr) { + int diffX = a->walkdata.destx - a->x; + int diffY = a->walkdata.desty - a->y; + int boxDiffY = box1.ul.y - a->y; + + pos = a->x; + if (diffY!=0) { + pos += diffX * boxDiffY / diffY; } } else { - tmp = a->x; + pos = a->x; } - q = tmp; - if (q < box.upperLeftX) - q = box.upperLeftX; - if (q > box.upperRightX) - q = box.upperRightX; - if (q < upperLeftX) - q = upperLeftX; - if (q > upperRightX) - q = upperRightX; - if (tmp==q && box2==box3) + + q = pos; + if (q < box2.ul.x) + q = box2.ul.x; + if (q > box2.ur.x) + q = box2.ur.x; + if (q < box1.ul.x) + q = box1.ul.x; + if (q > box1.ur.x) + q = box1.ur.x; + if (q==pos && box2nr==box3nr) return 1; _foundPathX = q; - _foundPathY = upperLeftY; + _foundPathY = box1.ul.y; return 0; - } else { - if (m != 0) { - SWAP(upperRightX, upperLeftX); - } - if (n != 0) { - SWAP(box.upperRightX, box.upperLeftX); - } } } - tmp_x = upperLeftX; - tmp_y = upperLeftY; - upperLeftX = upperRightX; - upperLeftY = upperRightY; - upperRightX = lowerLeftX; - upperRightY = lowerLeftY; - lowerLeftX = lowerRightX; - lowerLeftY = lowerRightY; - lowerRightX = tmp_x; - lowerRightY = tmp_y; + tmp = box1.ul; + box1.ul = box1.ur; + box1.ur = box1.ll; + box1.ll = box1.lr; + box1.lr = tmp; } - - tmp_x = box.upperLeftX; - tmp_y = box.upperLeftY; - box.upperLeftX = box.upperRightX; - box.upperLeftY = box.upperRightY; - box.upperRightX = box.lowerLeftX; - box.upperRightY = box.lowerLeftY; - box.lowerLeftX = box.lowerRightX; - box.lowerLeftY = box.lowerRightY; - box.lowerRightX = tmp_x; - box.lowerRightY = tmp_y; - i++; - } while (1); + tmp = box2.ul; + box2.ul = box2.ur; + box2.ur = box2.ll; + box2.ll = box2.lr; + box2.lr = tmp; + } + error("findPathTowards: default"); } - - void Scumm::setBoxFlags(int box, int val) { - Box *b = getBoxBaseAddr(box); - b->flags = val; + /* FULL_THROTTLE stuff */ + if (val & 0xC000) { + assert(box>=0 && box<65); + _extraBoxFlags[box] = val; + } else { + Box *b = getBoxBaseAddr(box); + b->flags = val; + } } void Scumm::setBoxScale(int box, int scale) { @@ -673,30 +659,18 @@ PathNode *Scumm::unkMatrixProc2(PathVertex *vtx, int i) { } /* Check if two boxes are neighbours */ -bool Scumm::areBoxesNeighbours(int box1, int box2) { - int upperLeftX, upperLeftY; - int upperRightX, upperRightY; - int lowerLeftX, lowerLeftY; - int lowerRightX, lowerRightY; +bool Scumm::areBoxesNeighbours(int box1nr, int box2nr) { int j,k,m,n; int tmp_x, tmp_y; bool result; + BoxCoords box; + BoxCoords box2; - if (getBoxFlags(box1)&0x80 || getBoxFlags(box2)&0x80) + if (getBoxFlags(box1nr)&0x80 || getBoxFlags(box2nr)&0x80) return false; - getBoxCoordinates(box1); - - upperLeftX = box.upperLeftX; - upperLeftY = box.upperLeftY; - upperRightX = box.upperRightX; - upperRightY = box.upperRightY; - lowerLeftX = box.lowerLeftX; - lowerLeftY = box.lowerLeftY; - lowerRightX = box.lowerRightX; - lowerRightY = box.lowerRightY; - - getBoxCoordinates(box2); + getBoxCoordinates(box1nr, &box2); + getBoxCoordinates(box2nr, &box); result = false; j = 4; @@ -704,99 +678,99 @@ bool Scumm::areBoxesNeighbours(int box1, int box2) { do { k = 4; do { - if (upperRightX == upperLeftX && - box.upperLeftX == upperLeftX && - box.upperRightX == upperRightX) { + if (box2.ur.x == box2.ul.x && + box.ul.x == box2.ul.x && + box.ur.x == box2.ur.x) { n = m = 0; - if (upperRightY < upperLeftY) { + if (box2.ur.y < box2.ul.y) { n = 1; - SWAP(upperRightY, upperLeftY); + SWAP(box2.ur.y, box2.ul.y); } - if (box.upperRightY < box.upperLeftY) { + if (box.ur.y < box.ul.y) { m = 1; - SWAP(box.upperRightY, box.upperLeftY); + SWAP(box.ur.y, box.ul.y); } - if (box.upperRightY < upperLeftY || - box.upperLeftY > upperRightY || - (box.upperLeftY == upperRightY || - box.upperRightY==upperLeftY) && - upperRightY != upperLeftY && - box.upperLeftY!=box.upperRightY) { + if (box.ur.y < box2.ul.y || + box.ul.y > box2.ur.y || + (box.ul.y == box2.ur.y || + box.ur.y==box2.ul.y) && + box2.ur.y != box2.ul.y && + box.ul.y!=box.ur.y) { if (n) { - SWAP(upperRightY, upperLeftY); + SWAP(box2.ur.y, box2.ul.y); } if (m) { - SWAP(box.upperRightY, box.upperLeftY); + SWAP(box.ur.y, box.ul.y); } } else { if (n) { - SWAP(upperRightY, upperLeftY); + SWAP(box2.ur.y, box2.ul.y); } if (m) { - SWAP(box.upperRightY, box.upperLeftY); + SWAP(box.ur.y, box.ul.y); } result = true; } } - if (upperRightY == upperLeftY && - box.upperLeftY == upperLeftY && - box.upperRightY == upperRightY) { + if (box2.ur.y == box2.ul.y && + box.ul.y == box2.ul.y && + box.ur.y == box2.ur.y) { n = m = 0; - if (upperRightX < upperLeftX) { + if (box2.ur.x < box2.ul.x) { n = 1; - SWAP(upperRightX, upperLeftX); + SWAP(box2.ur.x, box2.ul.x); } - if (box.upperRightX < box.upperLeftX) { + if (box.ur.x < box.ul.x) { m = 1; - SWAP(box.upperRightX, box.upperLeftX); + SWAP(box.ur.x, box.ul.x); } - if (box.upperRightX < upperLeftX || - box.upperLeftX > upperRightX || - (box.upperLeftX == upperRightX || - box.upperRightX==upperLeftX) && - upperRightX != upperLeftX && - box.upperLeftX!=box.upperRightX) { + if (box.ur.x < box2.ul.x || + box.ul.x > box2.ur.x || + (box.ul.x == box2.ur.x || + box.ur.x==box2.ul.x) && + box2.ur.x != box2.ul.x && + box.ul.x!=box.ur.x) { if (n) { - SWAP(upperRightX, upperLeftX); + SWAP(box2.ur.x, box2.ul.x); } if (m) { - SWAP(box.upperRightX, box.upperLeftX); + SWAP(box.ur.x, box.ul.x); } } else { if (n) { - SWAP(upperRightX, upperLeftX); + SWAP(box2.ur.x, box2.ul.x); } if (m) { - SWAP(box.upperRightX, box.upperLeftX); + SWAP(box.ur.x, box.ul.x); } result = true; } } - tmp_x = upperLeftX; - tmp_y = upperLeftY; - upperLeftX = upperRightX; - upperLeftY = upperRightY; - upperRightX = lowerLeftX; - upperRightY = lowerLeftY; - lowerLeftX = lowerRightX; - lowerLeftY = lowerRightY; - lowerRightX = tmp_x; - lowerRightY = tmp_y; + tmp_x = box2.ul.x; + tmp_y = box2.ul.y; + box2.ul.x = box2.ur.x; + box2.ul.y = box2.ur.y; + box2.ur.x = box2.ll.x; + box2.ur.y = box2.ll.y; + box2.ll.x = box2.lr.x; + box2.ll.y = box2.lr.y; + box2.lr.x = tmp_x; + box2.lr.y = tmp_y; } while (--k); - tmp_x = box.upperLeftX; - tmp_y = box.upperLeftY; - box.upperLeftX = box.upperRightX; - box.upperLeftY = box.upperRightY; - box.upperRightX = box.lowerLeftX; - box.upperRightY = box.lowerLeftY; - box.lowerLeftX = box.lowerRightX; - box.lowerLeftY = box.lowerRightY; - box.lowerRightX = tmp_x; - box.lowerRightY = tmp_y; + tmp_x = box.ul.x; + tmp_y = box.ul.y; + box.ul.x = box.ur.x; + box.ul.y = box.ur.y; + box.ur.x = box.ll.x; + box.ur.y = box.ll.y; + box.ll.x = box.lr.x; + box.ll.y = box.lr.y; + box.lr.x = tmp_x; + box.lr.y = tmp_y; } while (--j); return result; diff --git a/costume.cpp b/costume.cpp index 395cb1b9d39..ede1fb09db2 100644 --- a/costume.cpp +++ b/costume.cpp @@ -292,8 +292,8 @@ byte CostumeRenderer::mainRoutine(Actor *a, int slot, int frame) { CHECK_HEAP - if (a->data8) { - proc_special(a->data8); + if (a->unk1) { + proc_special(a->unk1); return b; } @@ -672,7 +672,7 @@ void CostumeRenderer::proc_special(byte code) { void CostumeRenderer::loadCostume(int id) { _ptr = _vm->getResourceAddress(rtCostume, id); - if (_vm->_majorScummVersion == 6) { + if (_vm->_features&GF_AFTER_V6) { _ptr += 8; } else { _ptr += 2; @@ -698,24 +698,39 @@ void CostumeRenderer::loadCostume(int id) { _dataptr = _ptr + READ_LE_UINT16(_ptr + _numColors + 8); } +void Scumm::initActorCostumeData(Actor *a) { + CostumeData *cd = &a->cost; + int i; + + cd->stopped = 0; + for (i=0; i<16; i++) { + cd->active[i] = 0; + cd->curpos[i] = cd->start[i] = cd->end[i] = cd->frame[i] = 0xFFFF; + } +} + byte CostumeRenderer::drawOneSlot(Actor *a, int slot) { +#if !defined(FULL_THROTTLE) int i; int code; CostumeData *cd = &a->cost; - if (cd->a[slot]==0xFFFF || cd->hdr & (1<curpos[slot]==0xFFFF || cd->stopped & (1<a[slot]&0x7FFF; + i = cd->curpos[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); } +#endif return 0; + } byte CostumeRenderer::drawCostume(Actor *a) { @@ -733,18 +748,18 @@ byte CostumeRenderer::animateOneSlot(Actor *a, int slot) { int i,end; byte code,nc; - if (a->cost.a[slot]==0xFFFF) + if (a->cost.curpos[slot]==0xFFFF) return 0; - highflag = a->cost.a[slot]&0x8000; - i = a->cost.a[slot]&0x7FFF; - end = a->cost.c[slot]; + 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.b[slot]; + i = a->cost.start[slot]; } else { if (i != end) i++; @@ -754,25 +769,25 @@ byte CostumeRenderer::animateOneSlot(Actor *a, int slot) { if (nc==0x7C) { a->cost.animCounter1++; - if(a->cost.b[slot] != end) + if(a->cost.start[slot] != end) continue; } else { - if (_vm->_majorScummVersion == 6) { + if (_vm->_features&GF_AFTER_V6) { if (nc>=0x71 && nc<=0x78) { _vm->addSoundToQueue2(a->sound[nc-0x71]); - if(a->cost.b[slot] != end) + if(a->cost.start[slot] != end) continue; } } else { if (nc==0x78) { a->cost.animCounter2++; - if(a->cost.b[slot] != end) + if(a->cost.start[slot] != end) continue; } } } - a->cost.a[slot] = i|highflag; + a->cost.curpos[slot] = i|highflag; return (_dataptr[i]&0x7F) != code; } while(1); } @@ -781,10 +796,75 @@ byte CostumeRenderer::animate(Actor *a) { int i; byte r = 0; +#if !defined(FULL_THROTTLE) for (i=0; i<16; i++) { - if(a->cost.a[i]!=0xFFFF) + if(a->cost.curpos[i]!=0xFFFF) r+=animateOneSlot(a, i); } +#endif return r; } +int Scumm::cost_frameToAnim(Actor *a, int frame) { + return newDirToOldDir(a->facing) + frame * 4; +} + +void Scumm::decodeCostData(Actor *a, int frame, uint usemask) { + byte *p,*r; + uint mask,j; + int i; + byte extra,cmd; + byte *dataptr; + int anim; + + anim = cost_frameToAnim(a, frame); + + p = cost._ptr; + if (anim > p[6]) { + return; + } + + r = p + READ_LE_UINT16(p + anim*2 + cost._numColors + 42); + if (r==p) { + return; + } + + dataptr = p + READ_LE_UINT16(p + cost._numColors + 8); + + mask = READ_LE_UINT16(r); + r+=2; + i = 0; + do { + if (mask&0x8000) { + 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<cost.stopped |= (1<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); +} diff --git a/debug.cpp b/debug.cpp index fd18dcaf4b4..169178d4d01 100644 --- a/debug.cpp +++ b/debug.cpp @@ -198,7 +198,7 @@ void ScummDebugger::printActors(int act) { a = &_s->actor[i]; if (a->visible) printf("|%2d|%4d|%3d %3d|%4d|%3d|%5d|%3d|%3d|%2d|%5d|%5d|%3d|%3d|\n", - i,a->room,a->x,a->y,a->elevation,a->costume,a->width,a->walkbox,a->moving,a->neverZClip,a->animIndex,a->scalex,a->speedx,a->facing); + i,a->room,a->x,a->y,a->elevation,a->costume,a->width,a->walkbox,a->moving,a->neverZClip,a->frame,a->scalex,a->speedx,a->facing); } } printf("+--------------------------------------------------------------+\n"); diff --git a/gfx.cpp b/gfx.cpp index 10c9430992a..b56d6d6a90d 100644 --- a/gfx.cpp +++ b/gfx.cpp @@ -260,14 +260,14 @@ void Scumm::setCameraAt(int dest) { } cd->_destPos = dest; - t = _vars[VAR_CAMERA_MIN]; + t = _vars[VAR_CAMERA_MIN_X]; if (cd->_curPos < t) cd->_curPos = t; - t = _vars[VAR_CAMERA_MAX]; + t = _vars[VAR_CAMERA_MAX_X]; if (cd->_curPos > t) cd->_curPos = t; if (_vars[VAR_SCROLL_SCRIPT]) { - _vars[VAR_CAMERA_CUR_POS] = cd->_curPos; + _vars[VAR_CAMERA_POS_X] = cd->_curPos; runScript(_vars[VAR_SCROLL_SCRIPT], 0, 0, 0); } @@ -309,7 +309,7 @@ void Scumm::initBGBuffers() { room = getResourceAddress(rtRoom, _roomResource); - ptr = findResource(MKID('RMIH'), findResource(MKID('RMIM'), room, 0), 0); + ptr = findResource(MKID('RMIH'), findResource(MKID('RMIM'), room)); gdi._numZBuffer = READ_LE_UINT16(ptr+8) + 1; @@ -382,9 +382,8 @@ void Scumm::initCycl(byte *ptr) { int i, j; ColorCycle *cycl; - for (i=0,cycl=_colorCycle; i<16; i++,cycl++) - cycl->delay = 0; - + memset(_colorCycle, 0, sizeof(_colorCycle)); + while ((j=*ptr++) != 0) { if (j<1 || j>16) { error("Invalid color cycle index %d", j); @@ -537,9 +536,9 @@ void Scumm::redrawBGAreas() { val = 0; - if (_fullRedraw==0 && _BgNeedsRedraw) { + if (!_fullRedraw && _BgNeedsRedraw) { for (i=0; i<40; i++) { - if (actorDrawBits[_screenStartStrip + i]&0x8000) { + if (gfxUsageBits[_screenStartStrip + i]&0x80000000) { redrawBGStrip(i, 1); } } @@ -552,12 +551,12 @@ void Scumm::redrawBGAreas() { val = 1; redrawBGStrip(0, 1); } else if (_fullRedraw!=0 || cd->_curPos != cd->_lastPos) { - _BgNeedsRedraw = 0; + _BgNeedsRedraw = false; redrawBGStrip(0, 40); } drawRoomObjects(val); - _BgNeedsRedraw = 0; + _BgNeedsRedraw = false; } const uint32 zplane_tags[] = { @@ -567,7 +566,7 @@ const uint32 zplane_tags[] = { MKID('ZP03') }; -void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, int stripnr, int numstrip, bool flag) { +void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, int stripnr, int numstrip, byte flag) { byte *smap_ptr,*where_draw_ptr; int i; byte *zplane_list[4]; @@ -578,14 +577,14 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, int stripnr CHECK_HEAP - smap_ptr = findResource(MKID('SMAP'), ptr, 0); + smap_ptr = findResource(MKID('SMAP'), ptr); assert(smap_ptr); numzbuf = _disable_zbuffer ? 0 : _numZBuffer; for(i=1; ihasCharsetMask(sx<<3, y, (sx+1)<<3, bottom)) { - if (_vm->_vars[VAR_V5_DRAWFLAGS]&2) - draw8ColWithMasking(); - else + if (flag&dbClear) clear8ColWithMasking(); - } else { - if (_vm->_vars[VAR_V5_DRAWFLAGS]&2) - blit(_backbuff_ptr, _bgbak_ptr, 8, h); else + draw8ColWithMasking(); + } else { + if (flag&dbClear) clear8Col(); + else + blit(_backbuff_ptr, _bgbak_ptr, 8, h); } } CHECK_HEAP + if (flag & dbDrawMaskOnBoth) { + _z_plane_ptr = zplane_list[1] + READ_LE_UINT16(zplane_list[1] + stripnr*2 + 8); + _mask_ptr_dest = _vm->getResourceAddress(rtBuffer, 9) + y*40 + x; + if (_useOrDecompress && flag&dbAllowMaskOr) + decompressMaskImgOr(); + else + decompressMaskImg(); + } + for (i=1; igetResourceAddress(rtBuffer, 9) + y*40 + x + _imgBufOffs[i]; - if (_useOrDecompress && flag) + if (_useOrDecompress && flag&dbAllowMaskOr) decompressMaskImgOr(); else decompressMaskImg(); @@ -869,11 +877,11 @@ void Gdi::decompressMaskImgOr() { void Scumm::redrawBGStrip(int start, int num) { int s = _screenStartStrip + start; - assert(s>=0 && s=0 && sheight > _scrHeight) { error("Screen Y size %d < Room height %d", _curVirtScreen->height, @@ -1208,7 +1216,7 @@ void Scumm::restoreBG(int left, int top, int right, int bottom) { if (bottom>=height) bottom=height; - updateDirtyRect(vs->number, left, right, top-topline,bottom-topline, 0x4000); + updateDirtyRect(vs->number, left, right, top-topline,bottom-topline, 0x40000000); height = (top-topline) * 320 + vs->xstart + left; @@ -1223,7 +1231,7 @@ void Scumm::restoreBG(int left, int top, int right, int bottom) { width = right - left; widthmod = (width >> 2) + 2; - if (vs->alloctwobuffers && _currentRoom!=0 && _vars[VAR_V5_DRAWFLAGS]&2) { + if (vs->alloctwobuffers && _currentRoom!=0 /*&& _vars[VAR_V5_DRAWFLAGS]&2*/) { blit(backbuff, bgbak, width, height); if (vs->number==0 && charset._hasMask && height) { do { @@ -1241,10 +1249,10 @@ void Scumm::restoreBG(int left, int top, int right, int bottom) { } } -void Scumm::updateDirtyRect(int virt, int left, int right, int top, int bottom, uint16 dirtybits) { +void Scumm::updateDirtyRect(int virt, int left, int right, int top, int bottom, uint32 dirtybits) { VirtScreen *vs = &virtscr[virt]; int lp,rp; - uint16 *sp; + uint32 *sp; int num; if (top > vs->height || bottom < 0) @@ -1263,7 +1271,7 @@ void Scumm::updateDirtyRect(int virt, int left, int right, int top, int bottom, rp = 200; if (lp <= rp) { num = rp - lp + 1; - sp = &actorDrawBits[lp]; + sp = &gfxUsageBits[lp]; do { *sp++ |= dirtybits; } while (--num); @@ -1435,18 +1443,18 @@ void Scumm::moveCamera() { cd->_curPos &= 0xFFF8; - if (cd->_curPos < _vars[VAR_CAMERA_MIN]) { - if (_vars[VAR_CAMERA_FAST]) - cd->_curPos = _vars[VAR_CAMERA_MIN]; + if (cd->_curPos < _vars[VAR_CAMERA_MIN_X]) { + if (_vars[VAR_CAMERA_FAST_X]) + cd->_curPos = _vars[VAR_CAMERA_MIN_X]; else cd->_curPos += 8; cameraMoved(); return; } - if (cd->_curPos > _vars[VAR_CAMERA_MAX]) { - if (_vars[VAR_CAMERA_FAST]) - cd->_curPos = _vars[VAR_CAMERA_MAX]; + if (cd->_curPos > _vars[VAR_CAMERA_MAX_X]) { + if (_vars[VAR_CAMERA_FAST_X]) + cd->_curPos = _vars[VAR_CAMERA_MAX_X]; else cd->_curPos-=8; cameraMoved(); @@ -1460,7 +1468,7 @@ void Scumm::moveCamera() { t = (actorx>>3) - _screenStartStrip; if (t < cd->_leftTrigger || t > cd->_rightTrigger) { - if (_vars[VAR_CAMERA_FAST]) { + if (_vars[VAR_CAMERA_FAST_X]) { if (t > 35) cd->_destPos = actorx + 80; if (t < 5) @@ -1475,13 +1483,13 @@ void Scumm::moveCamera() { cd->_destPos = a->x; } - if (cd->_destPos < _vars[VAR_CAMERA_MIN]) - cd->_destPos = _vars[VAR_CAMERA_MIN]; + if (cd->_destPos < _vars[VAR_CAMERA_MIN_X]) + cd->_destPos = _vars[VAR_CAMERA_MIN_X]; - if (cd->_destPos > _vars[VAR_CAMERA_MAX]) - cd->_destPos = _vars[VAR_CAMERA_MAX]; + if (cd->_destPos > _vars[VAR_CAMERA_MAX_X]) + cd->_destPos = _vars[VAR_CAMERA_MAX_X]; - if (_vars[VAR_CAMERA_FAST]) { + if (_vars[VAR_CAMERA_FAST_X]) { cd->_curPos = cd->_destPos; } else { if (cd->_curPos < cd->_destPos) @@ -1498,7 +1506,7 @@ void Scumm::moveCamera() { cameraMoved(); if (pos != cd->_curPos && _vars[VAR_SCROLL_SCRIPT]) { - _vars[VAR_CAMERA_CUR_POS] = cd->_curPos; + _vars[VAR_CAMERA_POS_X] = cd->_curPos; runScript(_vars[VAR_SCROLL_SCRIPT], 0, 0, 0); } } @@ -1627,23 +1635,19 @@ void Scumm::screenEffect(int effect) { void Scumm::resetActorBgs() { Actor *a; - int i,bitpos; - int top,bottom; - uint16 onlyActorFlags; + int i; + uint32 onlyActorFlags,bitpos; int offs; for(i=0; i<40; i++) { - onlyActorFlags = (actorDrawBits[_screenStartStrip + i]&=0x3FFF); + onlyActorFlags = (gfxUsageBits[_screenStartStrip + i]&=0x3FFFFFFF); a = getFirstActor(); bitpos = 1; while (onlyActorFlags) { if(onlyActorFlags&1 && a->top!=0xFF && a->needBgReset) { - top = a->top; - bottom = a->bottom; - actorDrawBits[_screenStartStrip + i] ^= bitpos; + gfxUsageBits[_screenStartStrip + i] ^= bitpos; gdi.resetBackground(a->top, a->bottom, i); - } bitpos<<=1; onlyActorFlags>>=1; @@ -1673,7 +1677,7 @@ void Gdi::resetBackground(byte top, byte bottom, int strip) { _numLinesToProcess = bottom - top; if (_numLinesToProcess) { - if (_vm->_vars[VAR_V5_DRAWFLAGS]&2) { + if (1/*_vm->_vars[VAR_V5_DRAWFLAGS]&2*/) { if(_vm->hasCharsetMask(strip<<3, top, (strip+1)<<3, bottom)) draw8ColWithMasking(); else @@ -1761,11 +1765,11 @@ byte *Scumm::findPalInPals(byte *pal, int index) { byte *offs; uint32 size; - pal = findResource(MKID('WRAP'), pal, 0); + pal = findResource(MKID('WRAP'), pal); if (pal==NULL) return NULL; - offs = findResource(MKID('OFFS'),pal, 0); + offs = findResource(MKID('OFFS'),pal); if (offs==NULL) return NULL; @@ -1945,3 +1949,53 @@ void Scumm::decompressDefaultCursor(int index) { _grabbedCursor[16*i+8] = color; } } + + +int Scumm::remapPaletteColor(byte r, byte g, byte b, uint threshold) { + int i; + byte ar,ag,ab; + uint sum,j,bestsum,bestitem; + byte *pal = _currentPalette; + + bestsum = (uint)-1; + + r &= ~3; + g &= ~3; + b &= ~3; + + for(i=0; i<256; i++,pal+=3) { + ar = pal[0]&~3; + ag = pal[1]&~3; + ab = pal[2]&~3; + if (ar==r && ag==g && ab==b) + return i; + + j=abs(ar-r)*3; + sum = j*j; + j=abs(ag-g)*6; + sum += j*j; + j=abs(ab-b)*2; + sum += j*j; + + if (sum < bestsum) { + bestsum = sum; + bestitem = i; + } + } + + if (threshold != -1 && bestsum > threshold*threshold*(2+3+6)) { + pal = _currentPalette + (256-2)*3; + for(i=254; i>48; i--,pal-=3) { + if (pal[0]>=252 && pal[1]>=252 && pal[2]>=252) { + setPalColor(i, r, g, b); + return i; + } + } + } + + return bestitem; +} + +void Scumm::setupShadowPalette(int slot,int rfact,int gfact,int bfact,int from,int to) { + +} \ No newline at end of file diff --git a/gui.cpp b/gui.cpp index 4b89bda31d4..5f87ba1c8c2 100644 --- a/gui.cpp +++ b/gui.cpp @@ -366,7 +366,7 @@ const char *Gui::queryString(int string, int id) { return namebuf; } - if (_s->_majorScummVersion==6) { + if (_s->_features&GF_AFTER_V6) { string = _s->_vars[string_map_table_v6[string-1]]; } else { string = string_map_table_v5[string-1]; @@ -437,12 +437,16 @@ void Gui::addLetter(byte letter) { } byte Gui::getDefaultColor(int color) { - if (_s->_majorScummVersion == 6) { +#if defined(FULL_THROTTLE) + return 0; +#else + if (_s->_features&GF_AFTER_V6) { if (color==8) color=1; return _s->readArray(110, 0, color); } else { return _s->getStringAddress(21)[color]; } +#endif } void Gui::init(Scumm *s) { diff --git a/object.cpp b/object.cpp index a661a2095f4..f68e48e1407 100644 --- a/object.cpp +++ b/object.cpp @@ -45,31 +45,36 @@ void Scumm::putClass(int obj, int cls, bool set) { int Scumm::getOwner(int obj) { checkRange(_numGlobalObjects-1, 0, obj, "Object %d out of range in getOwner"); - return _objectFlagTable[obj]&OF_OWNER_MASK; + return _objectOwnerTable[obj]; } void Scumm::putOwner(int act, int owner) { checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in putOwner"); - checkRange(15, 0, owner, "Owner %d out of range in putOwner"); - _objectFlagTable[act] = (_objectFlagTable[act]&~OF_OWNER_MASK) | owner; + checkRange(0xFF, 0, owner, "Owner %d out of range in putOwner"); + _objectOwnerTable[act] = owner; } int Scumm::getState(int act) { checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in getState"); - return _objectFlagTable[act]>>4; + return _objectStateTable[act]; } void Scumm::putState(int act, int state) { checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in putState"); - checkRange(15, 0, state, "State %d out of range in putState"); - _objectFlagTable[act] = (_objectFlagTable[act]&~OF_STATE_MASK) | - (state<= _numGlobalObjects) return WIO_NOT_FOUND; - if ((_objectFlagTable[object]&OF_OWNER_MASK)!=OF_OWNER_ROOM) { + if (_objectOwnerTable[object] != OF_OWNER_ROOM) { for (i=0; i<_maxInventoryItems; i++) if (_inventory[i] == object) return WIO_INVENTORY; @@ -106,19 +111,22 @@ int Scumm::whereIsObject(int object) { } int Scumm::getObjectOrActorXY(int object) { - if (object <= _vars[VAR_NUM_ACTOR]) { + if (object < NUM_ACTORS) { return getActorXYPos(derefActorSafe(object, "getObjectOrActorXY")); } switch(whereIsObject(object)) { case WIO_NOT_FOUND: return -1; case WIO_INVENTORY: - return getActorXYPos(derefActorSafe(_objectFlagTable[object]&OF_OWNER_MASK,"getObjectOrActorXY(2)")); + return getActorXYPos(derefActorSafe(_objectOwnerTable[object],"getObjectOrActorXY(2)")); } getObjectXYPos(object); return 0; } +/* Return the position of an object. + Returns X, Y and direction in angles + */ void Scumm::getObjectXYPos(int object) { ObjectData *od = &_objs[getObjectIndex(object)]; int state; @@ -127,31 +135,33 @@ void Scumm::getObjectXYPos(int object) { int x,y; AdjustBoxResult abr; - if (_majorScummVersion==6) { + if (_features&GF_AFTER_V6) { state = getState(object)-1; if (state<0) state = 0; if (od->fl_object_index) { ptr = getResourceAddress(rtFlObject, od->fl_object_index); - ptr = findResource(MKID('OBIM'), ptr, 0); + ptr = findResource(MKID('OBIM'), ptr); } else { ptr = getResourceAddress(rtRoom, _roomResource); ptr += od->offs_obim_to_room; } assert(ptr); - imhd = (ImageHeader*)findResource(MKID('IMHD'), ptr, 0); - x = od->x_pos*8 + (int16)READ_LE_UINT16(&imhd->hotspot[state].x); - y = od->y_pos*8 + (int16)READ_LE_UINT16(&imhd->hotspot[state].y); + imhd = (ImageHeader*)findResource(MKID('IMHD'), ptr); + x = od->x_pos + (int16)READ_LE_UINT16(&imhd->hotspot[state].x); + y = od->y_pos + (int16)READ_LE_UINT16(&imhd->hotspot[state].y); } else { x = od->walk_x; y = od->walk_y; } - abr = adjustXYToBeInBox(0, x, y); - _xPos = abr.x; - _yPos = abr.y; - _dir = od->actordir&3; +// abr = adjustXYToBeInBox(0, x, y); +// _xPos = abr.x; +// _yPos = abr.y; + _xPos = x; + _yPos = y; + _dir = oldDirToNewDir(od->actordir&3); } int Scumm::getObjActToObjActDist(int a, int b) { @@ -159,10 +169,10 @@ int Scumm::getObjActToObjActDist(int a, int b) { Actor *acta = NULL; Actor *actb = NULL; - if (a<=_vars[VAR_NUM_ACTOR]) + if (aroom==actb->room && acta->room && @@ -179,7 +189,7 @@ int Scumm::getObjActToObjActDist(int a, int b) { return 0xFF; if (acta) { - AdjustBoxResult r = adjustXYToBeInBox(acta, _xPos, _yPos); + AdjustBoxResult r = adjustXYToBeInBox(acta, _xPos, _yPos, 0); _xPos = r.x; _yPos = r.y; } @@ -192,7 +202,8 @@ int Scumm::getObjActToObjActDist(int a, int b) { } int Scumm::findObject(int x, int y) { - int i,a,b; + int i,b; + byte a; for (i=1; i<=_numObjectsInRoom; i++) { if (!_objs[i].obj_nr || getClass(_objs[i].obj_nr, 32)) @@ -202,44 +213,39 @@ int Scumm::findObject(int x, int y) { a = _objs[b].parentstate; b = _objs[b].parent; if (b==0) { - if (_objs[i].x_pos <= (x>>3) && - _objs[i].numstrips + _objs[i].x_pos > (x>>3) && - _objs[i].y_pos <= (y>>3) && - _objs[i].height + _objs[i].y_pos > (y>>3)) + if (_objs[i].x_pos <= x && + _objs[i].width + _objs[i].x_pos > x && + _objs[i].y_pos <= y && + _objs[i].height + _objs[i].y_pos > y) return _objs[i].obj_nr; break; } - } while ( (_objs[b].ownerstate&OF_STATE_MASK) == a); + } while ( _objs[b].state == a); } return 0; } void Scumm::drawRoomObjects(int arg) { - int num = _numObjectsInRoom; + int i; ObjectData *od; - int a; + byte a; - if (num==0) - return; - - do { - od = &_objs[num]; - if (!od->obj_nr || !(od->ownerstate&OF_STATE_MASK)) + for(i=1; i<=_numObjectsInRoom; i++) { + od = &_objs[i]; + if (!od->obj_nr || !od->state || od->fl_object_index) continue; - do { a = od->parentstate; if (!od->parent) { - drawObject(num, arg); + drawObject(i, arg); break; } od = &_objs[od->parent]; - } while ((od->ownerstate & OF_STATE_MASK)==a); - - } while (--num); + } while (od->state==a); + } } -const uint32 state_tags[] = { +const uint32 IMxx_tags[] = { MKID('IM00'), MKID('IM01'), MKID('IM02'), @@ -272,9 +278,9 @@ void Scumm::drawObject(int obj, int arg) { od = &_objs[obj]; - xpos = od->x_pos; + xpos = od->x_pos>>3; ypos = od->y_pos; - width = od->numstrips; + width = od->width>>3; height = od->height; if (width==0 || xpos > _screenEndStrip || xpos + width < _screenStartStrip) @@ -282,13 +288,13 @@ void Scumm::drawObject(int obj, int arg) { if (od->fl_object_index) { ptr = getResourceAddress(rtFlObject, od->fl_object_index); - ptr = findResource(MKID('OBIM'), ptr, 0); + ptr = findResource(MKID('OBIM'), ptr); } else { ptr = getResourceAddress(rtRoom, _roomResource); ptr = ptr + od->offs_obim_to_room; } - ptr = findResource(state_tags[getState(od->obj_nr)], ptr, 0); + ptr = findResource(IMxx_tags[getState(od->obj_nr)], ptr); if (!ptr) return; @@ -302,19 +308,18 @@ void Scumm::drawObject(int obj, int arg) { continue; if (tmp < _screenStartStrip || tmp > _screenEndStrip) continue; - actorDrawBits[tmp] |= 0x8000; + gfxUsageBits[tmp] |= 0x80000000; if (tmp < x) x = tmp; numstrip++; } - if (numstrip!=0) - gdi.drawBitmap(ptr, _curVirtScreen, x, ypos<<3, height<<3, x-xpos, numstrip, true); - -// _drawBmpY = ypos << 3; -// gdi._numLinesToProcess = height << 3; -// _drawBmpX = x; -// drawBmp(ptr, x - xpos, b, 1, "Object", od->obj_nr); + if (numstrip!=0) { + byte flags = Gdi::dbAllowMaskOr; + if (getClass(od->obj_nr, 22)) + flags |= Gdi::dbDrawMaskOnBoth; + gdi.drawBitmap(ptr, _curVirtScreen, x, ypos, height, x-xpos, numstrip, flags); + } } void Scumm::loadRoomObjects() { @@ -322,7 +327,7 @@ void Scumm::loadRoomObjects() { ObjectData *od; byte *ptr; uint16 obim_id; - byte *room; + byte *room,*searchptr; ImageHeader *imhd; RoomHeader *roomhdr; @@ -331,7 +336,7 @@ void Scumm::loadRoomObjects() { CHECK_HEAP room = getResourceAddress(rtRoom, _roomResource); - roomhdr = (RoomHeader*)findResource(MKID('RMHD'), room, 0); + roomhdr = (RoomHeader*)findResource(MKID('RMHD'), room); _numObjectsInRoom = READ_LE_UINT16(&roomhdr->numObjects); @@ -342,8 +347,9 @@ void Scumm::loadRoomObjects() { error("More than %d objects in room %d", _numLocalObjects, _roomResource); od = &_objs[1]; + searchptr = room; for (i=0; i<_numObjectsInRoom; i++,od++) { - ptr = findResource(MKID('OBCD'), room, i); + ptr = findResource(MKID('OBCD'), searchptr); if (ptr==NULL) error("Room %d missing object code block(s)", _roomResource); @@ -358,10 +364,12 @@ void Scumm::loadRoomObjects() { dumpResource(buf, od->obj_nr, ptr); } while (0); #endif + searchptr = NULL; } + searchptr = room; for (i=0; i<_numObjectsInRoom; i++) { - ptr = findResource(MKID('OBIM'), room, i); + ptr = findResource(MKID('OBIM'), searchptr); if (ptr==NULL) error("Room %d missing image blocks(s)", _roomResource); @@ -372,52 +380,74 @@ void Scumm::loadRoomObjects() { if (_objs[j].obj_nr==obim_id) _objs[j].offs_obim_to_room = ptr - room; } + searchptr = NULL; } od = &_objs[1]; for (i=1; i<=_numObjectsInRoom; i++,od++) { - ptr = room + od->offs_obcd_to_room; - cdhd = (CodeHeader*)findResource(MKID('CDHD'), ptr,0); - od->obj_nr = READ_LE_UINT16(&cdhd->obj_id); - - if (_majorScummVersion == 6) { - od->numstrips = READ_LE_UINT16(&cdhd->v6.w)>>3; - od->height = READ_LE_UINT16(&cdhd->v6.h)>>3; - od->x_pos = ((int16)READ_LE_UINT16(&cdhd->v6.x))>>3; - od->y_pos = ((int16)READ_LE_UINT16(&cdhd->v6.y))>>3; - if (cdhd->v6.flags == 0x80) { - od->parentstate = 1<<4; - } else { - od->parentstate = (cdhd->v6.flags&0xF)<parent = cdhd->v6.parent; - od->actordir = cdhd->v6.actordir; - } else { - od->numstrips = cdhd->v5.w; - od->height = cdhd->v5.h; - od->x_pos = cdhd->v5.x; - od->y_pos = cdhd->v5.y; - if (cdhd->v5.flags == 0x80) { - od->parentstate = 1<<4; - } else { - od->parentstate = (cdhd->v5.flags&0xF)<parent = cdhd->v5.parent; - od->walk_x = READ_LE_UINT16(&cdhd->v5.walk_x); - od->walk_y = READ_LE_UINT16(&cdhd->v5.walk_y); - od->actordir = cdhd->v5.actordir; - } - od->fl_object_index = 0; + setupRoomObject(od, room); } CHECK_HEAP } +void Scumm::setupRoomObject(ObjectData *od, byte *room) { + byte *obcd; + CodeHeader *cdhd; + ImageHeader *imhd; + + cdhd = (CodeHeader*)findResource(MKID('CDHD'), room + od->offs_obcd_to_room); + + od->obj_nr = READ_LE_UINT16(&cdhd->obj_id); + +#if !defined(FULL_THROTTLE) + if (_features & GF_AFTER_V6) { + od->width = READ_LE_UINT16(&cdhd->v6.w); + od->height = READ_LE_UINT16(&cdhd->v6.h); + od->x_pos = ((int16)READ_LE_UINT16(&cdhd->v6.x)); + od->y_pos = ((int16)READ_LE_UINT16(&cdhd->v6.y)); + if (cdhd->v6.flags == 0x80) { + od->parentstate = 1<<4; + } else { + od->parentstate = (cdhd->v6.flags&0xF)<parent = cdhd->v6.parent; + od->actordir = cdhd->v6.actordir; + } else { + od->width = cdhd->v5.w<<3; + od->height = cdhd->v5.h<<3; + od->x_pos = cdhd->v5.x<<3; + od->y_pos = cdhd->v5.y<<3; + if (cdhd->v5.flags == 0x80) { + od->parentstate = 1<<4; + } else { + od->parentstate = (cdhd->v5.flags&0xF)<parent = cdhd->v5.parent; + od->walk_x = READ_LE_UINT16(&cdhd->v5.walk_x); + od->walk_y = READ_LE_UINT16(&cdhd->v5.walk_y); + od->actordir = cdhd->v5.actordir; + } +#else + od->parent = cdhd->parent; + od->parentstate = cdhd->parentstate; + + imhd = (ImageHeader*)findResource(MKID('IMHD'), room + od->offs_obim_to_room); + od->x_pos = imhd->x_pos; + od->y_pos = imhd->y_pos; + od->width = imhd->width; + od->height = imhd->height; + od->actordir = imhd->actordir; + +#endif + od->fl_object_index = 0; +} + void Scumm::fixObjectFlags() { int i; ObjectData *od = &_objs[1]; for (i=1; i<=_numObjectsInRoom; i++,od++) { - od->ownerstate = _objectFlagTable[od->obj_nr]; + od->state = _objectStateTable[od->obj_nr]; } } @@ -463,10 +493,8 @@ void Scumm::clearOwnerOf(int obj) { if (!a[0] && a[1]) { a[0] = a[1]; a[1] = 0; - ptr = getResourceAddress(rtInventory, i+1); _baseInventoryItems[i] = _baseInventoryItems[i+1]; - _baseInventoryItems[i+1] = 0; - /* TODO: some wacky write is done here */ + _baseInventoryItems[i+1] = NULL; } } return; @@ -476,18 +504,18 @@ void Scumm::clearOwnerOf(int obj) { void Scumm::removeObjectFromRoom(int obj) { int i,cnt; - uint16 *ptr; + uint32 *ptr; for(i=1; i<=_numObjectsInRoom; i++) { - if (_objs[i].obj_nr==obj) { - if (_objs[i].numstrips != 0) { - ptr = &actorDrawBits[_objs[i].x_pos]; - cnt = _objs[i].numstrips; + if (_objs[i].obj_nr==(uint16)obj) { + if (_objs[i].width != 0) { + ptr = &gfxUsageBits[_objs[i].x_pos>>3]; + cnt = _objs[i].width>>3; do { - *ptr++ |= 0x8000; + *ptr++ |= 0x80000000; } while (--cnt); } - _BgNeedsRedraw = 1; + _BgNeedsRedraw = true; return; } } @@ -506,20 +534,20 @@ void Scumm::clearDrawObjectQueue() { byte *Scumm::getObjOrActorName(int obj) { byte *objptr; - if (obj <= _vars[VAR_NUM_ACTOR]) + if (obj < NUM_ACTORS) return getActorName(derefActorSafe(obj, "getObjOrActorName")); objptr = getObjectAddress(obj); if (objptr==NULL) return (byte*)" "; - return findResource(MKID('OBNA'), objptr, 0) + 8; + return findResource(MKID('OBNA'), objptr) + 8; } uint32 Scumm::getOBCDOffs(int object) { int i; - if ((_objectFlagTable[object]&OF_OWNER_MASK)!=OF_OWNER_ROOM) + if (_objectOwnerTable[object] != OF_OWNER_ROOM) return 0; for (i=_numObjectsInRoom; i>0; i--) { if (_objs[i].obj_nr == object) { @@ -534,7 +562,7 @@ uint32 Scumm::getOBCDOffs(int object) { byte *Scumm::getObjectAddress(int obj) { int i; - if ((_objectFlagTable[obj]&OF_OWNER_MASK)!=OF_OWNER_ROOM) { + if (_objectOwnerTable[obj] != OF_OWNER_ROOM) { for(i=0; i<_maxInventoryItems; i++) { if (_inventory[i] == obj) return getResourceAddress(rtInventory, i); @@ -553,12 +581,9 @@ byte *Scumm::getObjectAddress(int obj) { void Scumm::addObjectToInventory(uint obj, uint room) { int i, slot; - byte *ptr,*obcdptr; - uint32 size,cdoffs; - int numobj; - byte *roomptr; - CodeHeader *cdhd; - RoomHeader *roomhdr; + uint32 size; + byte *obcdptr,*ptr; + FindObjectInRoom foir; debug(1,"Adding object %d from room %d into inventory", obj, room); @@ -573,37 +598,79 @@ void Scumm::addObjectToInventory(uint obj, uint room) { createResource(rtInventory, slot, size); ptr = getResourceAddress(rtFlObject, _objs[i].fl_object_index) + 64; memcpy(getResourceAddress(rtInventory, slot), ptr, size); - CHECK_HEAP + } else { + findObjectInRoom(&foir, foCodeHeader, obj, room); + size = READ_BE_UINT32_UNALIGNED(foir.obcd+4); + slot = getInventorySlot(); + _inventory[slot] = obj; + createResource(rtInventory, slot, size); + obcdptr = getResourceAddress(rtRoom, room) - foir.roomptr + foir.obcd; + memcpy(getResourceAddress(rtInventory,slot),obcdptr,size); + } + + CHECK_HEAP +} + +void Scumm::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id, uint room) { + CodeHeader *cdhd; + int i, numobj; + byte *roomptr,*obcdptr,*obimptr,*searchptr; + RoomHeader *roomhdr; + ImageHeader *imhd; + + if (findWhat&foCheckAlreadyLoaded && getObjectIndex(id) != -1) { + fo->obcd = obcdptr = getObjectAddress(id); + assert((byte*)obcdptr > (byte*)256); + fo->obim = obimptr = obcdptr + READ_BE_UINT32(&((ImageHeader*)obcdptr)->size); + fo->cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcdptr); + fo->imhd = (ImageHeader*)findResource(MKID('IMHD'), obimptr); return; } -// ensureResourceLoaded(rtRoom, room); - roomptr = getResourceAddress(rtRoom, room); - roomhdr = (RoomHeader*)findResource(MKID('RMHD'), roomptr, 0); + + fo->roomptr = roomptr = getResourceAddress(rtRoom, room); + roomhdr = (RoomHeader*)findResource(MKID('RMHD'), roomptr); numobj = READ_LE_UINT16(&roomhdr->numObjects); if (numobj==0) - error("addObjectToInventory: No object found in room %d", room); + error("findObjectInRoom: No object found in room %d", room); if (numobj > _numLocalObjects) - error("addObjectToInventory: More (%d) than %d objects in room %d", numobj, _numLocalObjects, room); + error("findObjectInRoom: More (%d) than %d objects in room %d", numobj, _numLocalObjects, room); - for (i=0; iobj_id) == obj) { - cdoffs = obcdptr - roomptr; - size = READ_BE_UINT32_UNALIGNED(obcdptr+4); - slot = getInventorySlot(); - _inventory[slot] = obj; - createResource(rtInventory, slot, size); - obcdptr = getResourceAddress(rtRoom, room) + cdoffs; - memcpy(getResourceAddress(rtInventory,slot),obcdptr,size); - CHECK_HEAP - return; + if (findWhat & foCodeHeader) { + searchptr = roomptr; + for (i=0;;) { + obcdptr = findResource(MKID('OBCD'), searchptr); + if(obcdptr==NULL) + error("findObjectInRoom: Not enough code blocks in room %d", room); + cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcdptr, 0); + if ( READ_LE_UINT16(&cdhd->obj_id) == (uint16)id) { + fo->cdhd = cdhd; + fo->obcd = obcdptr; + break; + } + if (++i == numobj) + error("findObjectInRoom: Object %d not found in room %d", id, room); + searchptr = NULL; } } - error("addObjectToInventory: Object %d not found in room %d", obj, room); + if (findWhat & foImageHeader) { + searchptr = roomptr; + for(i=0;;) { + obimptr = findResource(MKID('OBIM'), searchptr); + if (obimptr==NULL) + error("findObjectInRoom: Not enough image blocks in room %d", room); + imhd = (ImageHeader*)findResource(MKID('IMHD'), obimptr, 0); + if (READ_LE_UINT16(&imhd->obj_id) == (uint16)id) { + fo->obim = obimptr; + fo->imhd = imhd; + break; + } + + if (++i==numobj) + error("findObjectInRoom: Object %d image not found in room %d", id, room); + searchptr = NULL; + } + } } int Scumm::getInventorySlot() { @@ -632,7 +699,7 @@ void Scumm::setOwnerOf(int obj, int owner) { } int Scumm::getObjX(int obj) { - if (obj <= _vars[VAR_NUM_ACTOR]) { + if (obj < NUM_ACTORS) { return derefActorSafe(obj,"getObjX")->x; } else { if (whereIsObject(obj)==WIO_NOT_FOUND) @@ -643,7 +710,7 @@ int Scumm::getObjX(int obj) { } int Scumm::getObjY(int obj) { - if (obj <= _vars[VAR_NUM_ACTOR]) { + if (obj < NUM_ACTORS) { return derefActorSafe(obj,"getObjY")->y; } else { if (whereIsObject(obj)==WIO_NOT_FOUND) @@ -654,8 +721,8 @@ int Scumm::getObjY(int obj) { } int Scumm::getObjDir(int obj) { - if (obj <= _vars[VAR_NUM_ACTOR]) { - return derefActorSafe(obj,"getObjDir")->facing; + if (obj < NUM_ACTORS) { + return newDirToOldDir(derefActorSafe(obj,"getObjDir")->facing); } else { getObjectXYPos(obj); return _dir; @@ -687,12 +754,14 @@ void Scumm::setObjectState(int obj, int state, int x, int y) { int i; i = getObjectIndex(obj); - if (i==-1) + if (i==-1) { + warning("setObjectState: no such object"); return; + } if (x != -1) { - _objs[i].x_pos = x; - _objs[i].y_pos = y; + _objs[i].x_pos = x<<3; + _objs[i].y_pos = y<<3; } addObjectToDrawQue(i); @@ -717,7 +786,7 @@ int Scumm::getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, int e, if (is_obj_1) { if (getObjectOrActorXY(b)==-1) return -1; - if (b < _vars[VAR_NUM_ACTOR]) + if (b < NUM_ACTORS) i = derefActorSafe(b, "unkObjProc1")->scalex; x = _xPos; y = _yPos; @@ -729,7 +798,7 @@ int Scumm::getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, int e, if (is_obj_2) { if (getObjectOrActorXY(e)==-1) return -1; - if (e < _vars[VAR_NUM_ACTOR]) + if (e < NUM_ACTORS) j = derefActorSafe(e, "unkObjProc1(2)")->scalex; x2 = _xPos; y2 = _yPos; @@ -741,66 +810,42 @@ int Scumm::getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, int e, return getDist(x,y,x2,y2) * 0xFF / ((i + j)>>1); } -void Scumm::setCursorImg(uint room, uint img) { +void Scumm::setCursorImg(uint img, uint room, uint imgindex) { byte *ptr; int index; - CodeHeader *cdhd; - ImageHeader *imhd; int w,h; - byte *roomptr,*obcd,*obim,*dataptr,*bomp; + byte *roomptr,*obim,*dataptr,*bomp; RoomHeader *rmhd; int i,numobj; uint32 size; + FindObjectInRoom foir; + + if (room==(uint)-1) + room = getObjectRoom(img); - if (getObjectIndex(img)!=-1) { - obim = getObjectAddress(img); - ptr = obim + READ_BE_UINT32(&((ImageHeader*)obim)->size); - cdhd = (CodeHeader*)findResource(MKID('CDHD'), obim, 0); - imhd = (ImageHeader*)findResource(MKID('IMHD'), ptr, 0); - } else { - ensureResourceLoaded(1, room); - roomptr = getResourceAddress(1, room); - rmhd = (RoomHeader*)findResource(MKID('RMHD'), roomptr, 0); - - numobj = READ_LE_UINT16(&rmhd->numObjects); - for(i=0; ;i++) { - if (i>=numobj) - error("setCursorImg: object %d code not found in room %d", img, room); - - obcd = findResource(MKID('OBCD'), roomptr, i); - if (obcd==NULL) - error("setCursorImg: not enough code blocks in room %d", room); - cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcd, 0); - if (READ_LE_UINT16(&cdhd->obj_id) == img) - break; - } - - for(i=0; ;i++) { - if (i>=numobj) - error("setCursorImg: object %d image not found in room %d", img, room); - obim = findResource(MKID('OBIM'), roomptr, i); - if (obim==NULL) - error("setCursorImg: not enough image blocks in room %d", room); - imhd = (ImageHeader*)findResource(MKID('IMHD'), obim, 0); - if (READ_LE_UINT16(&imhd->obj_id) == img) - break; - } - } + findObjectInRoom(&foir, foCodeHeader | foImageHeader | foCheckAlreadyLoaded, img, room); setCursorHotspot2( - READ_LE_UINT16(&imhd->hotspot[0].x), - READ_LE_UINT16(&imhd->hotspot[0].y)); + READ_LE_UINT16(&foir.imhd->hotspot[0].x), + READ_LE_UINT16(&foir.imhd->hotspot[0].y)); - w = READ_LE_UINT16(&cdhd->v6.w)>>3; - h = READ_LE_UINT16(&cdhd->v6.h)>>3; +#if !defined(FULL_THROTTLE) + w = READ_LE_UINT16(&foir.cdhd->v6.w)>>3; + h = READ_LE_UINT16(&foir.cdhd->v6.h)>>3; +#else + w = READ_LE_UINT16(&foir.imhd->width)>>3; + h = READ_LE_UINT16(&foir.imhd->height)>>3; +#endif - size = READ_BE_UINT32(&cdhd->size); + dataptr = findResource(IMxx_tags[imgindex],foir.obim); + if (dataptr==NULL) + error("setCursorImg: No such image"); + + size = READ_BE_UINT32(dataptr+4); if (size > sizeof(_grabbedCursor)) error("setCursorImg: Cursor image too large"); - - dataptr = findResource(MKID('IM01'),obim, 0); - if ((bomp = findResource(MKID('BOMP'), dataptr, 0)) != NULL) + if ((bomp = findResource(MKID('BOMP'), dataptr)) != NULL) useBompCursor(bomp, w, h); else useIm01Cursor(dataptr, w, h); @@ -838,13 +883,13 @@ void Scumm::enqueueObject(int a, int b, int c, int d, int e, int f, int g, int h eo->y = c; if (d==0) { od = &_objs[getObjectIndex(a)]; - eo->width = od->numstrips<<3; + eo->width = od->width; } else { eo->width = d; } if (e==0) { od = &_objs[getObjectIndex(a)]; - eo->height = od->height<<3; + eo->height = od->height; } else { eo->height = e; } @@ -887,14 +932,14 @@ void Scumm::drawEnqueuedObject(EnqueuedObject *eo) { } else if (eo->a!=0) { od = &_objs[getObjectIndex(eo->a)]; ptr = getResourceAddress(rtFlObject, od->fl_object_index); - ptr = findResource(MKID('OBIM'), ptr, 0); + ptr = findResource(MKID('OBIM'), ptr); } else { warning("drawEnqueuedObject: invalid"); return; } - ptr = findResource(MKID('IM01'), ptr, 0); - bomp = findResource(MKID('BOMP'), ptr, 0); + ptr = findResource(MKID('IM01'), ptr); + bomp = findResource(MKID('BOMP'), ptr); width = READ_LE_UINT16(&((BompHeader*)bomp)->width); height = READ_LE_UINT16(&((BompHeader*)bomp)->height); @@ -906,9 +951,11 @@ void Scumm::drawEnqueuedObject(EnqueuedObject *eo) { if (eo->a) { dataptr = bomp + 18; - } +// debug(1, "drawEnqueuedObject(%d,%d,%d,%d,%d, %d,%d,%d,%d,%d,%d,%d)", +// eo->x, eo->y, eo->width, eo->height, eo->a, eo->b, eo->c, eo->d, eo->e, eo->j, eo->k, eo->l); + updateDirtyRect(vs->number, x, x+width,y,y+height,0); } @@ -928,3 +975,58 @@ void Scumm::removeEnqueuedObject(EnqueuedObject *eo) { restoreBG(eo->x, eo->y, eo->x + eo->width, eo->y + eo->height); } +int Scumm::findFlObjectSlot() { + int i; + for(i=1; i<_maxFLObject; i++) { + if (_baseFLObject[i] == NULL) + return i; + } + error("findFlObjectSlot: Out of FLObject slots"); +} + +void Scumm::loadFlObject(uint object, uint room) { + FindObjectInRoom foir; + int slot; + ObjectData *od; + byte *flob,*roomptr; + uint32 obcd_size, obim_size, flob_size; + + /* Don't load an already loaded object */ + if (whereIsObject(object) != WIO_NOT_FOUND) + return; + + if (room==(uint)-1) + room = getObjectRoom(object); + + /* Locate the object in the room resource */ + findObjectInRoom(&foir, foImageHeader | foCodeHeader, object, room); + + /* Add an entry for the new floating object in the local object table */ + if (++_numObjectsInRoom > _numLocalObjects) + error("loadFlObject: Local Object Table overflow"); + od = &_objs[_numObjectsInRoom]; + + /* Setup sizes */ + obcd_size = READ_BE_UINT32(foir.obcd + 4); + od->offs_obcd_to_room = 8; + od->offs_obim_to_room = obcd_size + 8; + obim_size = READ_BE_UINT32(foir.obim + 4); + flob_size = obcd_size + obim_size + 8; + + /* Allocate slot & memory for floating object */ + slot = findFlObjectSlot(); + createResource(rtFlObject, slot, flob_size); + + /* Copy object code + object image to floating object */ + roomptr = getResourceAddress(rtRoom, room); + flob = getResourceAddress(rtFlObject, slot); + ((uint32*)flob)[0] = MKID('FLOB'); + ((uint32*)flob)[1] = TO_BE_32(flob_size); + memcpy(flob + 8, roomptr - foir.roomptr + foir.obcd, obcd_size); + memcpy(flob + 8 + obcd_size, roomptr - foir.roomptr + foir.obim, obim_size); + + /* Setup local object flags */ + setupRoomObject(od, flob); + + od->fl_object_index = slot; +} diff --git a/resource.cpp b/resource.cpp index 0128e699a0f..4c71656532f 100644 --- a/resource.cpp +++ b/resource.cpp @@ -58,10 +58,14 @@ void Scumm::openRoom(int room) { _fileOffset = _roomFileOffsets[room]; return; } +#if defined(FULL_THROTTLE) + sprintf(buf, "%s.la%d", _exe_name, + room==0 ? 0 : res.roomno[rtRoom][room]); +#else sprintf(buf, "%s.%.3d", _exe_name, room==0 ? 0 : res.roomno[rtRoom][room]); - - _encbyte = 0x69; +#endif + _encbyte = (_features & GF_USE_KEY) ? 0x69 : 0; if (openResourceFile(buf)) { if (room==0) return; @@ -152,18 +156,54 @@ void Scumm::askForDisk(const char *filename) { error("Cannot find '%s'", filename); } -void Scumm::readIndexFileV5(int mode) { +void Scumm::readIndexFile() { uint32 blocktype,itemsize; int numblock = 0; -#if defined(SCUMM_BIG_ENDIAN) - int i; -#endif + int num, i; - debug(9, "readIndexFile(%d)",mode); + debug(9, "readIndexFile()"); openRoom(-1); openRoom(0); - + + if (!(_features & GF_AFTER_V6)) { + /* Figure out the sizes of various resources */ + while (!fileEof(_fileHandle)) { + blocktype = fileReadDword(); + itemsize = fileReadDwordBE(); + if (fileReadFailed(_fileHandle)) + break; + switch(blocktype) { + case MKID('DOBJ'): + _numGlobalObjects = fileReadWordLE(); + itemsize-=2; + break; + case MKID('DROO'): + _numRooms = fileReadWordLE(); + itemsize-=2; + break; + + case MKID('DSCR'): + _numScripts = fileReadWordLE(); + itemsize-=2; + break; + + case MKID('DCOS'): + _numCostumes = fileReadWordLE(); + itemsize-=2; + break; + + case MKID('DSOU'): + _numSounds = fileReadWordLE(); + itemsize-=2; + break; + } + fileSeek(_fileHandle, itemsize-8,SEEK_CUR); + } + clearFileReadFailed(_fileHandle); + fileSeek(_fileHandle, 0, SEEK_SET); + } + while (1) { blocktype = fileReadDword(); @@ -179,108 +219,33 @@ void Scumm::readIndexFileV5(int mode) { break; case MKID('DOBJ'): - _numGlobalObjects = fileReadWordLE(); - _objectFlagTable = (byte*)alloc(_numGlobalObjects); - if (mode==1) { - fileSeek(_fileHandle, itemsize - 10, 1); - break; + num = fileReadWordLE(); + assert(num == _numGlobalObjects); + + if (_features & GF_AFTER_V7) { + fileRead(_fileHandle, _objectStateTable, num); + fileRead(_fileHandle, _objectRoomTable, num); + memset(_objectOwnerTable, 0xFF, num); + + } else { + fileRead(_fileHandle, _objectOwnerTable, num); + for (i=0; i>OF_STATE_SHL; + _objectOwnerTable[i] &= OF_OWNER_MASK; + } } - - _classData = (uint32*)alloc(_numGlobalObjects * sizeof(uint32)); - fileRead(_fileHandle, _objectFlagTable, _numGlobalObjects); - fileRead(_fileHandle, _classData, _numGlobalObjects * sizeof(uint32)); -#if defined(SCUMM_BIG_ENDIAN) - for (i=0; i<_numGlobalObjects; i++) - _classData[i] = FROM_LE_32(_classData[i]); -#endif - break; - - case MKID('RNAM'): - fileSeek(_fileHandle, itemsize-8,1); - break; - - case MKID('DROO'): - readResTypeList(rtRoom,MKID('ROOM'),"room"); - break; - - case MKID('DSCR'): - readResTypeList(rtScript,MKID('SCRP'),"script"); - break; - - case MKID('DCOS'): - readResTypeList(rtCostume,MKID('COST'),"costume"); - break; - - case MKID('MAXS'): - fileReadWordLE(); - fileReadWordLE(); - fileReadWordLE(); - fileReadWordLE(); - fileReadWordLE(); - fileReadWordLE(); - fileReadWordLE(); - fileReadWordLE(); - fileReadWordLE(); - break; - - case MKID('DSOU'): - readResTypeList(rtSound,MKID('SOUN'),"sound"); - break; - - default: - error("Bad ID %c%c%c%c found in directory!", blocktype&0xFF, blocktype>>8, blocktype>>16, blocktype>>24); - return; - } - } - - clearFileReadFailed(_fileHandle); - - if (numblock!=8) - error("Not enough blocks read from directory"); - - openRoom(-1); - - _numGlobalScripts = _maxScripts; - _dynamicRoomOffsets = true; -} - -void Scumm::readIndexFileV6() { - uint32 blocktype,itemsize; - int numblock = 0; - int num, i; - - debug(9, "readIndexFile()"); - - openRoom(-1); - openRoom(0); - - while (1) { - blocktype = fileReadDword(); - - if (fileReadFailed(_fileHandle)) - break; - itemsize = fileReadDwordBE(); - - numblock++; - - switch(blocktype) { - case MKID('DCHR'): - readResTypeList(rtCharset,MKID('CHAR'),"charset"); - break; - - case MKID('DOBJ'): - num = fileReadWordLE(); - assert(num == _numGlobalObjects); - fileRead(_fileHandle, _objectFlagTable, num); fileRead(_fileHandle, _classData, num * sizeof(uint32)); + #if defined(SCUMM_BIG_ENDIAN) - for (i=0; i<_numGlobalObjects; i++) + for (i=0; i=0 && id=512) { + if (num>=2000) { error("Too many %ss (%d) in directory", name, num); } @@ -425,8 +388,10 @@ void Scumm::ensureResourceLoaded(int type, int i) { loadResource(type, i); +#if !defined(FULL_THROTTLE) if (type==rtRoom && i==_roomResource) _vars[VAR_ROOM_FLAG] = 1; +#endif } int Scumm::loadResource(int type, int index) { @@ -434,7 +399,7 @@ int Scumm::loadResource(int type, int index) { uint32 fileOffs; uint32 size, tag; - debug(9, "loadResource(%d,%d)", type,index); +// debug(1, "loadResource(%d,%d)", type,index); roomNr = getResourceRoomNr(type, index); if (roomNr == 0 || index >= res.num[type]) { @@ -503,7 +468,7 @@ int Scumm::readSoundResource(int type, int index) { basetag = fileReadDwordLE(); size = fileReadDwordBE(); -#ifdef SAMNMAX +#if defined(SAMNMAX) || defined(FULL_THROTTLE) if (basetag == MKID('MIDI')) { fileSeek(_fileHandle, -8, SEEK_CUR); fileRead(_fileHandle,createResource(type, index, size+8), size+8); @@ -565,7 +530,7 @@ byte *Scumm::getStringAddress(int i) { if (!b) return b; - if (_majorScummVersion==6) + if (_features & GF_NEW_OPCODES) return ((ArrayHeader*)b)->data; return b; } @@ -586,7 +551,7 @@ byte *Scumm::createResource(int type, int index, uint32 size) { debug(9, "createResource(%d,%d,%d)", type, index,size); if (size > 65536*4+37856) - error("Invalid size allocating"); + warning("Probably invalid size allocating"); validateResource("allocating", type, index); nukeResource(type, index); @@ -631,6 +596,47 @@ void Scumm::nukeResource(int type, int index) { } } +byte *Scumm::findResourceData(uint32 tag, byte *ptr) { + ptr = findResource(tag,ptr); + if (ptr==NULL) + return NULL; + return ptr + 8; +} + +struct FindResourceState { + uint32 size,pos; + byte *ptr; +}; + +/* just O(N) complexity when iterating with this function */ +byte *findResource(uint32 tag, byte *searchin) { + uint32 size; + static FindResourceState frs; + FindResourceState *f = &frs; /* easier to make it thread safe like this */ + + if (searchin) { + f->size = READ_BE_UINT32_UNALIGNED(searchin+4); + f->pos = 8; + f->ptr = searchin+8; + goto StartScan; + } + + do { + size = READ_BE_UINT32_UNALIGNED(f->ptr+4); + if ((int32)size <= 0) + return NULL; + + f->pos += size; + f->ptr += size; + +StartScan: + if (f->pos >= f->size) + return NULL; + } while (READ_UINT32_UNALIGNED(f->ptr) != tag); + + return f->ptr; +} + byte *findResource(uint32 tag, byte *searchin, int index) { uint32 maxsize,curpos,totalsize,size; @@ -712,6 +718,8 @@ void Scumm::expireResources(uint32 size) { int best_type, best_res; uint32 oldAllocatedSize; + return; + if (_expire_counter != 0xFF) { _expire_counter = 0xFF; increaseResourceCounter(); @@ -817,52 +825,93 @@ void Scumm::unkHeapProc2(int a, int b) { warning("unkHeapProc2: not implemented"); } -void Scumm::loadFlObject(int a, int b) { - warning("loadFlObject(%d,%d):not implemented", a, b); -} - void Scumm::readMAXS() { - _numVariables = fileReadWordLE(); - fileReadWordLE(); - _numBitVariables = fileReadWordLE(); - _numLocalObjects = fileReadWordLE(); - _numArray = fileReadWordLE(); - fileReadWordLE(); - _numVerbs = fileReadWordLE(); - _numFlObject = fileReadWordLE(); - _numInventory = fileReadWordLE(); - _numRooms = fileReadWordLE(); - _numScripts = fileReadWordLE(); - _numSounds = fileReadWordLE(); - _numCharsets = fileReadWordLE(); - _numCostumes = fileReadWordLE(); - _numGlobalObjects = fileReadWordLE(); + if (_features & GF_AFTER_V7) { + fileSeek(_fileHandle, 50+50, SEEK_CUR); + _numVariables = fileReadWordLE(); + _numBitVariables = fileReadWordLE(); + fileReadWordLE(); + _numGlobalObjects = fileReadWordLE(); + _numLocalObjects = fileReadWordLE(); + _numNewNames = fileReadWordLE(); + _numVerbs = fileReadWordLE(); + _numFlObject = fileReadWordLE(); + _numInventory = fileReadWordLE(); + _numArray = fileReadWordLE(); + _numRooms = fileReadWordLE(); + _numScripts = fileReadWordLE(); + _numSounds = fileReadWordLE(); + _numCharsets = fileReadWordLE(); + _numCostumes = fileReadWordLE(); + + _objectRoomTable = (byte*)alloc(_numGlobalObjects); + _numGlobalScripts = 2000; + } else if (_features & GF_AFTER_V6) { + _numVariables = fileReadWordLE(); + fileReadWordLE(); + _numBitVariables = fileReadWordLE(); + _numLocalObjects = fileReadWordLE(); + _numArray = fileReadWordLE(); + fileReadWordLE(); + _numVerbs = fileReadWordLE(); + _numFlObject = fileReadWordLE(); + _numInventory = fileReadWordLE(); + _numRooms = fileReadWordLE(); + _numScripts = fileReadWordLE(); + _numSounds = fileReadWordLE(); + _numCharsets = fileReadWordLE(); + _numCostumes = fileReadWordLE(); + _numGlobalObjects = fileReadWordLE(); + _numNewNames = 50; + + _objectRoomTable = NULL; + _numGlobalScripts = 200; + } else { + _numVariables = fileReadWordLE(); /* 800 */ + fileReadWordLE(); /* 16 */ + _numBitVariables = fileReadWordLE(); /* 2048 */ + _numLocalObjects = fileReadWordLE(); /* 200 */ + _numArray = 50; + _numVerbs = 100; + _numNewNames = 0; + _objectRoomTable = NULL; + + fileReadWordLE(); /* 50 */ + _numCharsets = fileReadWordLE(); /* 9 */ + fileReadWordLE(); /* 100 */ + fileReadWordLE(); /* 50 */ + _numInventory = fileReadWordLE(); /* 80 */ + _numGlobalScripts = 200; + } - allocResTypeData(rtCostume, MKID('COST'), _numCostumes, "costume", 1); - allocResTypeData(rtRoom, MKID('ROOM'), _numRooms, "room", 1); - allocResTypeData(rtSound, MKID('SOUN'), _numSounds, "sound", 1); - allocResTypeData(rtScript, MKID('SCRP'), _numScripts, "script", 1); - allocResTypeData(rtCharset, MKID('CHAR'), _numCharsets, "charset", 1); - allocResTypeData(rtObjectName, MKID('NONE'),50,"new name", 0); allocateArrays(); - - _objectFlagTable = (byte*)alloc(_numGlobalObjects); - _arrays = (byte*)alloc(_numArray); - _newNames = (uint16*)alloc(50 * sizeof(uint16)); - _classData = (uint32*)alloc(_numGlobalObjects * sizeof(uint32)); - - _numGlobalScripts = 200; _dynamicRoomOffsets = 1; } void Scumm::allocateArrays() { + _objectOwnerTable = (byte*)alloc(_numGlobalObjects); + _objectStateTable = (byte*)alloc(_numGlobalObjects); + _classData = (uint32*)alloc(_numGlobalObjects * sizeof(uint32)); + _arrays = (byte*)alloc(_numArray); + _newNames = (uint16*)alloc(_numNewNames * sizeof(uint16)); + _inventory = (uint16*)alloc(_numInventory * sizeof(uint16)); _verbs = (VerbSlot*)alloc(_numVerbs * sizeof(VerbSlot)); _objs = (ObjectData*)alloc(_numLocalObjects * sizeof(ObjectData)); _vars = (int16*)alloc(_numVariables * sizeof(int16)); _bitVars = (byte*)alloc(_numBitVariables >> 3); +#if defined(FULL_THROTTLE) + allocResTypeData(rtCostume, MKID('AKOS'), _numCostumes, "costume", 1); +#else + allocResTypeData(rtCostume, MKID('COST'), _numCostumes, "costume", 1); +#endif + allocResTypeData(rtRoom, MKID('ROOM'), _numRooms, "room", 1); + allocResTypeData(rtSound, MKID('SOUN'), _numSounds, "sound", 1); + allocResTypeData(rtScript, MKID('SCRP'), _numScripts, "script", 1); + allocResTypeData(rtCharset, MKID('CHAR'), _numCharsets, "charset", 1); + allocResTypeData(rtObjectName, MKID('NONE'),_numNewNames,"new name", 0); allocResTypeData(rtInventory, MKID('NONE'), _numInventory, "inventory", 0); allocResTypeData(rtTemp,MKID('NONE'),10, "temp", 0); allocResTypeData(rtScaleTable,MKID('NONE'),5, "scale table", 0); diff --git a/saveload.cpp b/saveload.cpp index 13d96e215c9..199eea4594f 100644 --- a/saveload.cpp +++ b/saveload.cpp @@ -138,6 +138,7 @@ bool Scumm::loadState(int slot, bool compat) { debug(1,"State loaded from '%s'", filename); + pauseSounds(false); return true; @@ -193,14 +194,13 @@ void Scumm::saveOrLoad(Serializer *s) { MKLINE(ObjectData,obj_nr,sleUint16), MKLINE(ObjectData,x_pos,sleInt16), MKLINE(ObjectData,y_pos,sleInt16), - MKLINE(ObjectData,numstrips,sleUint16), + MKLINE(ObjectData,width,sleUint16), MKLINE(ObjectData,height,sleUint16), MKLINE(ObjectData,actordir,sleByte), MKLINE(ObjectData,parentstate,sleByte), MKLINE(ObjectData,parent,sleByte), - MKLINE(ObjectData,ownerstate,sleByte), + MKLINE(ObjectData,state,sleByte), MKLINE(ObjectData,fl_object_index,sleByte), - MKLINE(ObjectData,unk_3,sleByte), MKEND() }; @@ -211,7 +211,7 @@ void Scumm::saveOrLoad(Serializer *s) { MKLINE(Actor,bottom,sleInt16), MKLINE(Actor,elevation,sleInt16), MKLINE(Actor,width,sleUint16), - MKLINE(Actor,facing,sleByte), + MKLINE(Actor,facing,sleUint16), MKLINE(Actor,costume,sleUint16), MKLINE(Actor,room,sleByte), MKLINE(Actor,talkColor,sleByte), @@ -219,7 +219,8 @@ void Scumm::saveOrLoad(Serializer *s) { MKLINE(Actor,scaley,sleByte), MKLINE(Actor,charset,sleByte), MKARRAY(Actor,sound[0],sleByte, 8), - MKLINE(Actor,newDirection,sleByte), + MKARRAY(Actor,animVariable[0],sleUint16, 8), + MKLINE(Actor,newDirection,sleUint16), MKLINE(Actor,moving,sleByte), MKLINE(Actor,ignoreBoxes,sleByte), MKLINE(Actor,neverZClip,sleByte), @@ -232,10 +233,11 @@ void Scumm::saveOrLoad(Serializer *s) { MKLINE(Actor,speedy,sleUint16), MKLINE(Actor,cost.animCounter1,sleUint16), MKLINE(Actor,cost.animCounter2,sleByte), - MKARRAY(Actor,palette[0],sleByte,32), + MKARRAY(Actor,palette[0],sleByte,64), MKLINE(Actor,mask,sleByte), + MKLINE(Actor,unk1,sleByte), MKLINE(Actor,visible,sleByte), - MKLINE(Actor,animIndex,sleByte), + MKLINE(Actor,frame,sleByte), MKLINE(Actor,animSpeed,sleByte), MKLINE(Actor,animProgress,sleByte), MKLINE(Actor,walkbox,sleByte), @@ -247,12 +249,14 @@ void Scumm::saveOrLoad(Serializer *s) { MKLINE(Actor,new_2,sleInt16), MKLINE(Actor,new_3,sleByte), + MKLINE(Actor,talk_script,sleUint16), + MKLINE(Actor,walk_script,sleUint16), + MKLINE(Actor,walkdata.destx,sleInt16), MKLINE(Actor,walkdata.desty,sleInt16), MKLINE(Actor,walkdata.destbox,sleByte), - MKLINE(Actor,walkdata.destdir,sleByte), + MKLINE(Actor,walkdata.destdir,sleUint16), MKLINE(Actor,walkdata.curbox,sleByte), - MKLINE(Actor,walkdata.field_7,sleByte), MKLINE(Actor,walkdata.x,sleInt16), MKLINE(Actor,walkdata.y,sleInt16), MKLINE(Actor,walkdata.newx,sleInt16), @@ -262,11 +266,12 @@ void Scumm::saveOrLoad(Serializer *s) { MKLINE(Actor,walkdata.xfrac,sleUint16), MKLINE(Actor,walkdata.yfrac,sleUint16), - MKLINE(Actor,cost.hdr,sleUint16), - MKARRAY(Actor,cost.a[0],sleUint16,16), - MKARRAY(Actor,cost.b[0],sleUint16,16), - MKARRAY(Actor,cost.c[0],sleUint16,16), - MKARRAY(Actor,cost.d[0],sleUint16,16), + MKARRAY(Actor,cost.active[0],sleByte,16), + MKLINE(Actor,cost.stopped,sleUint16), + MKARRAY(Actor,cost.curpos[0],sleUint16,16), + MKARRAY(Actor,cost.start[0],sleUint16,16), + MKARRAY(Actor,cost.end[0],sleUint16,16), + MKARRAY(Actor,cost.frame[0],sleUint16,16), MKEND() }; @@ -309,7 +314,7 @@ void Scumm::saveOrLoad(Serializer *s) { MKLINE(Scumm,_roomResource,sleByte), MKLINE(Scumm,_numObjectsInRoom,sleByte), MKLINE(Scumm,_currentScript,sleByte), - MKARRAY(Scumm,_localScriptList[0],sleUint32,0x39), + MKARRAY(Scumm,_localScriptList[0],sleUint32,NUM_LOCALSCRIPT), MKARRAY(Scumm,vm.localvar[0][0],sleUint16,NUM_SCRIPT_SLOT*17), MKARRAY(Scumm,_resourceMapper[0],sleByte,128), MKARRAY(Scumm,charset._colorMap[0],sleByte,16), @@ -336,7 +341,7 @@ void Scumm::saveOrLoad(Serializer *s) { MKLINE(Scumm,_talkDelay,sleInt16), MKLINE(Scumm,_defaultTalkDelay,sleInt16), MKLINE(Scumm,_numInMsgStack,sleInt16), - MKLINE(Scumm,_sentenceIndex,sleByte), + MKLINE(Scumm,_sentenceNum,sleByte), MKLINE(Scumm,vm.cutSceneStackPointer,sleByte), MKARRAY(Scumm,vm.cutScenePtr[0],sleUint32,5), @@ -357,7 +362,7 @@ void Scumm::saveOrLoad(Serializer *s) { MKLINE(Scumm,_switchRoomEffect2,sleByte), MKLINE(Scumm,_BgNeedsRedraw,sleByte), - MKARRAY(Scumm,actorDrawBits[0],sleUint16,200), + MKARRAY(Scumm,gfxUsageBits[0],sleUint32,200), MKLINE(Scumm,gdi._transparency,sleByte), MKARRAY(Scumm,_currentPalette[0],sleByte,768), /* virtscr */ @@ -451,7 +456,7 @@ void Scumm::saveOrLoad(Serializer *s) { s->saveLoadEntries(this,mainEntries); - s->saveLoadArrayOf(actor+1, 12, sizeof(actor[0]), actorEntries); + s->saveLoadArrayOf(actor, NUM_ACTORS, sizeof(actor[0]), actorEntries); s->saveLoadArrayOf(vm.slot, NUM_SCRIPT_SLOT, sizeof(vm.slot[0]), scriptSlotEntries); s->saveLoadArrayOf(_objs, _numLocalObjects, sizeof(_objs[0]), objectEntries); s->saveLoadArrayOf(_verbs, _numVerbs, sizeof(_verbs[0]), verbEntries); @@ -465,7 +470,14 @@ void Scumm::saveOrLoad(Serializer *s) { for(j=1; jsaveLoadArrayOf(_objectFlagTable, _numGlobalObjects, sizeof(_objectFlagTable[0]), sleByte); + s->saveLoadArrayOf(_objectOwnerTable, _numGlobalObjects, sizeof(_objectOwnerTable[0]), sleByte); + s->saveLoadArrayOf(_objectStateTable, _numGlobalObjects, sizeof(_objectStateTable[0]), sleByte); + if (_objectRoomTable) + s->saveLoadArrayOf(_objectRoomTable, _numGlobalObjects, sizeof(_objectRoomTable[0]), sleByte); + + if (_shadowPalette) + s->saveLoadArrayOf(_shadowPalette, NUM_SHADOW_PALETTE * 256, 1, sleByte); + s->saveLoadArrayOf(_classData, _numGlobalObjects, sizeof(_classData[0]), sleUint32); s->saveLoadArrayOf(_vars, _numVariables, sizeof(_vars[0]), sleInt16); s->saveLoadArrayOf(_bitVars, _numBitVariables>>3, 1, sleByte); @@ -489,6 +501,7 @@ void Scumm::saveOrLoad(Serializer *s) { if (_soundDriver) ((SoundEngine*)_soundDriver)->save_or_load(s); + } void Scumm::saveLoadResource(Serializer *ser, int type, int index) { @@ -497,7 +510,7 @@ void Scumm::saveLoadResource(Serializer *ser, int type, int index) { byte flag; /* don't save/load these resource types */ - if (type==rtFlObject || type==rtTemp || type==rtBuffer || res.mode[type]) + if (/*type==rtFlObject ||*/ type==rtTemp || type==rtBuffer || res.mode[type]) return; if (ser->isSaving()) { diff --git a/script.cpp b/script.cpp index eec8d2b4d8f..28f9f7f1c77 100644 --- a/script.cpp +++ b/script.cpp @@ -50,7 +50,6 @@ void Scumm::runScript(int script, int a, int b, int16 *lvarptr) { scriptOffs = _localScriptList[script - _numGlobalScripts]; if (scriptOffs == 0) error("Local script %d is not in room %d", script, _roomResource); - scriptOffs += 9; scriptType = WIO_LOCAL; } @@ -298,7 +297,7 @@ int Scumm::readVar(uint var) { return _vars[var]; } - if (var&0x2000 && _majorScummVersion==5) { + if (var&0x2000 && !(_features&GF_NEW_OPCODES)) { a = fetchScriptWord(); if (a&0x2000) var = (var+readVar(a&~0x2000))&~0x2000; @@ -451,6 +450,7 @@ bool Scumm::isScriptInUse(int script) { return false; } + void Scumm::runHook(int i) { int16 tmp[16]; tmp[0] = i; @@ -575,9 +575,9 @@ void Scumm::killScriptsAndResources() { /* Nuke local object names */ if (_newNames) { - for (i=0; i<50; i++) { + for (i=0; i<_numNewNames; i++) { int j = _newNames[i]; - if (j && (getOwner(j)&OF_OWNER_MASK) == 0) { + if (j && getOwner(j) == 0) { _newNames[i] = 0; nukeResource(rtObjectName, i); } @@ -597,31 +597,33 @@ void Scumm::checkAndRunVar33() { return; } - if (_sentenceIndex > 0x7F || sentence[_sentenceIndex].unk) + if (!_sentenceNum || sentence[_sentenceNum-1].unk) return; - - if (sentence[_sentenceIndex].unk2 && - sentence[_sentenceIndex].unk3==sentence[_sentenceIndex].unk4) { - _sentenceIndex--; - return; - } - _localParamList[0] = sentence[_sentenceIndex].unk5; - _localParamList[1] = sentence[_sentenceIndex].unk4; - _localParamList[2] = sentence[_sentenceIndex].unk3; - _sentenceIndex--; + _sentenceNum--; + +#if !defined(FULL_THROTTLE) + if (sentence[_sentenceNum].unk2 && + sentence[_sentenceNum].unk3==sentence[_sentenceNum].unk4) + return; +#endif + + _localParamList[0] = sentence[_sentenceNum].unk5; + _localParamList[1] = sentence[_sentenceNum].unk4; + _localParamList[2] = sentence[_sentenceNum].unk3; _currentScript = 0xFF; if (_vars[VAR_SENTENCE_SCRIPT]) runScript(_vars[VAR_SENTENCE_SCRIPT], 0, 0, _localParamList); } void Scumm::runInputScript(int a, int cmd, int mode) { - memset(_localParamList, 0, sizeof(_localParamList)); - _localParamList[0] = a; - _localParamList[1] = cmd; - _localParamList[2] = mode; + int16 args[16]; + memset(args, 0, sizeof(args)); + args[0] = a; + args[1] = cmd; + args[2] = mode; if (_vars[VAR_VERB_SCRIPT]) - runScript(_vars[VAR_VERB_SCRIPT], 0, 0, _localParamList); + runScript(_vars[VAR_VERB_SCRIPT], 0, 0, args); } void Scumm::decreaseScriptDelay(int amount) { @@ -695,7 +697,7 @@ int Scumm::getVerbEntrypoint(int obj, int entry) { objptr = getObjectAddress(obj); assert(objptr); - verbptr = findResource(MKID('VERB'), objptr, 0); + verbptr = findResource(MKID('VERB'), objptr); if (verbptr==NULL) error("No verb block in object %d", obj); @@ -777,61 +779,93 @@ void Scumm::faceActorToObj(int act, int obj) { if (getObjectOrActorXY(obj)==-1) return; - dir = (_xPos > x) ? 1 : 0; + dir = (_xPos > x) ? 90 : 270; turnToDirection(derefActorSafe(act, "faceActorToObj"), dir); } void Scumm::animateActor(int act, int anim) { +#if defined(FULL_THROTTLE) + int cmd,dir; + Actor *a; + + a = derefActorSafe(act, "animateActor"); + + if (anim==0xFF) + anim = 2000; + + cmd = anim / 1000; + dir = anim % 1000; + + /* temporary code */ +// dir = newDirToOldDir(dir); + + switch(cmd) { + case 2: + stopActorMoving(a); + startAnimActor(a, a->standFrame); + break; + case 3: + a->moving &= ~4; + fixActorDirection(a, dir); + break; + case 4: + turnToDirection(a, dir); + break; + default: + startAnimActor(a, anim); + } + + +#else int shr,dir; bool inRoom; Actor *a; a = derefActorSafe(act, "animateActor"); - shr = anim>>2; dir = anim&3; - inRoom = (a->room == _currentRoom); - - if (shr == 0x3F) { - if (inRoom) { - startAnimActor(a, a->standFrame, a->facing); - a->moving = 0; - } - return; + switch(anim>>2) { + case 0x3F: + stopActorMoving(a); + startAnimActor(a, a->standFrame); + break; + case 0x3E: + a->moving &= ~4; + fixActorDirection(a, oldDirToNewDir(dir)); + break; + case 0x3D: + turnToDirection(a, oldDirToNewDir(dir)); + break; + default: + startAnimActor(a, anim); } - if (shr == 0x3E) { - if (inRoom) { - startAnimActor(a, 0x3E, dir); - a->moving &= ~4; - } - a->facing = dir; - return; - } - - if (shr == 0x3D) { - if (inRoom) { - turnToDirection(a, dir); - } else { - a->facing = dir; - } - return; - } - - startAnimActor(a, anim, a->facing); +#endif } -int Scumm::getScriptRunning(int script) { +bool Scumm::isScriptRunning(int script) { int i; ScriptSlot *ss = vm.slot; for (i=0; inumber==script && (ss->where==WIO_GLOBAL || ss->where==WIO_LOCAL) && ss->status) - return 1; - return 0; + return true; + return false; } +bool Scumm::isRoomScriptRunning(int script) { + int i; + ScriptSlot *ss = vm.slot; + for (i=0; inumber==script && ss->where==WIO_ROOM && ss->status) + return true; + return false; + +} + + + void Scumm::beginOverride() { int index; uint32 *ptr; @@ -970,4 +1004,47 @@ void Scumm::exitCutscene() { _vars[VAR_OVERRIDE] = 1; vm.cutScenePtr[vm.cutSceneStackPointer] = 0; } -} \ No newline at end of file +} +#if defined(FULL_THROTTLE) +void Scumm::doSentence(int c, int b, int a) { + SentenceTab *st; + + if (b==a) + return; + + st = &sentence[_sentenceNum-1]; + + if (_sentenceNum && + st->unk5 == c && st->unk4==b && st->unk3==a) + return; + + _sentenceNum++; + st++; + + st->unk5 = c; + st->unk4 = b; + st->unk3 = a; + st->unk = 0; + + warning("dosentence(%d,%d,%d)", c, b, a); + +} + +#else +void Scumm::doSentence(int c, int b, int a) { + SentenceTab *st; + + st = &sentence[_sentenceNum++]; + + st->unk5 = c; + st->unk4 = b; + st->unk3 = a; + + if (!(st->unk3&0xFF00)) + st->unk2 = 0; + else + st->unk2 = 1; + + st->unk = 0; +} +#endif \ No newline at end of file diff --git a/script_v1.cpp b/script_v1.cpp index c1cc62c096f..828fcb28364 100644 --- a/script_v1.cpp +++ b/script_v1.cpp @@ -461,7 +461,7 @@ FixRoom: a->animProgress = 0; break; case 23: /* unk2 */ - a->data8 = getVarOrDirectByte(0x80); /* unused */ + a->unk1 = getVarOrDirectByte(0x80); /* unused? */ break; default: error("o5_actorSet: default case"); @@ -578,7 +578,7 @@ void Scumm::o5_cursorCommand() { case 10: /* set cursor img */ i = getVarOrDirectByte(0x80); j = getVarOrDirectByte(0x40); - setCursorImg(i, j); + setCursorImg(i, j, 1); break; case 11: /* set cursor hotspot */ i = getVarOrDirectByte(0x80); @@ -653,17 +653,15 @@ void Scumm::o5_doSentence() { int a,b; SentenceTab *st; - _sentenceIndex++; - a = getVarOrDirectByte(0x80); if (a==0xFE) { - _sentenceIndex = 0xFF; + _sentenceNum = 0; stopScriptNr(_vars[VAR_SENTENCE_SCRIPT]); clearClickedStatus(); return; } - st = &sentence[_sentenceIndex]; + st = &sentence[_sentenceNum++]; st->unk5 = a; st->unk4 = getVarOrDirectWord(0x40); @@ -693,16 +691,17 @@ void Scumm::o5_drawBox() { void Scumm::o5_drawObject() { int state,obj,index,i; ObjectData *od; - byte x,y,w,h; + uint16 x,y,w,h; + int xpos, ypos; state = 1; - _xPos = _yPos = 255; + xpos = ypos = 255; obj = getVarOrDirectWord(0x80); switch((_opcode = fetchScriptByte())&0x1F) { case 1: /* draw at */ - _xPos = getVarOrDirectWord(0x80); - _yPos = getVarOrDirectWord(0x40); + xpos = getVarOrDirectWord(0x80); + ypos = getVarOrDirectWord(0x40); break; case 2: /* set state */ state = getVarOrDirectWord(0x80); @@ -717,23 +716,23 @@ void Scumm::o5_drawObject() { if (index==-1) return; od = &_objs[index]; - if (_xPos!=0xFF) { - od->walk_x += (_xPos - od->x_pos)<<3; - od->x_pos = _xPos; - od->walk_y += (_yPos - od->y_pos)<<3; - od->y_pos = _yPos; + if (xpos!=0xFF) { + od->walk_x += (xpos<<3) - od->x_pos; + od->x_pos = xpos<<3; + od->walk_y += (ypos<<3) - od->y_pos; + od->y_pos = ypos<<3; } addObjectToDrawQue(index); x = od->x_pos; y = od->y_pos; - w = od->numstrips; + w = od->width; h = od->height; i = _numObjectsInRoom; do { if (_objs[i].x_pos == x && _objs[i].y_pos == y - && _objs[i].numstrips == w && _objs[i].height==h) + && _objs[i].width == w && _objs[i].height==h) putState(_objs[i].obj_nr, 0); } while (--i); @@ -829,7 +828,7 @@ void Scumm::o5_getActorElevation() { void Scumm::o5_getActorFacing() { getResultPos(); - setResult(derefActorSafe(getVarOrDirectByte(0x80),"o5_getActorFacing")->facing); + setResult(newDirToOldDir(derefActorSafe(getVarOrDirectByte(0x80),"o5_getActorFacing")->facing)); } void Scumm::o5_getActorMoving() { @@ -924,7 +923,7 @@ void Scumm::o5_getRandomNr() { void Scumm::o5_getScriptRunning() { getResultPos(); - setResult(getScriptRunning(getVarOrDirectByte(0x80))); + setResult(isScriptRunning(getVarOrDirectByte(0x80))); } void Scumm::o5_getVerbEntrypoint() { @@ -1046,11 +1045,11 @@ void Scumm::o5_lights() { b = fetchScriptByte(); c = fetchScriptByte(); - if (c==0) +/* if (c==0) _vars[VAR_V5_DRAWFLAGS] = a; - else if (c==1) { + else if (c==1) {*/ warning("o5_lights: lights not implemented"); - } +// } _fullRedraw=1; } @@ -1069,8 +1068,8 @@ void Scumm::o5_loadRoomWithEgo() { a = derefActorSafe(_vars[VAR_EGO], "o5_loadRoomWithEgo"); - /* Warning: uses _xPos, _yPos from a previous update of those */ - putActor(a, _xPos, _yPos, room); + /* Warning: used previously _xPos, _yPos from a previous update of those */ + putActor(a, a->x, a->y, room); x = (int16)fetchScriptWord(); y = (int16)fetchScriptWord(); @@ -1087,7 +1086,7 @@ void Scumm::o5_loadRoomWithEgo() { _fullRedraw=1; if (x != -1) { - startWalkActor(a, x, y, 0xFF); + startWalkActor(a, x, y, -1); } } @@ -1327,8 +1326,8 @@ void Scumm::o5_roomOps() { if (a > ((_scrWidthIn8Unit-20)<<3)) a=((_scrWidthIn8Unit-20)<<3); if (b < 160) b=160; if (b > ((_scrWidthIn8Unit-20)<<3)) b=((_scrWidthIn8Unit-20)<<3); - _vars[VAR_CAMERA_MIN] = a; - _vars[VAR_CAMERA_MAX] = b; + _vars[VAR_CAMERA_MIN_X] = a; + _vars[VAR_CAMERA_MAX_X] = b; break; case 2: /* room color */ error("room-color is no longer a valid command"); @@ -1486,7 +1485,7 @@ void Scumm::o5_setObjectName() { int a; int i; - if (act <= _vars[VAR_NUM_ACTOR]) + if (act < NUM_ACTORS) error("Can't set actor %d name with new-name-of", act); if (!getObjectAddress(act)) @@ -1812,8 +1811,8 @@ void Scumm::o5_wait() { break; return; case 4: /* wait for sentence */ - if (_sentenceIndex!=0xFF) { - if (sentence[_sentenceIndex].unk && + if (_sentenceNum) { + if (sentence[_sentenceNum-1].unk && !isScriptInUse(_vars[VAR_SENTENCE_SCRIPT]) ) return; break; @@ -1836,7 +1835,7 @@ void Scumm::o5_walkActorTo() { a = derefActorSafe(getVarOrDirectByte(0x80), "o5_walkActorTo"); x = getVarOrDirectWord(0x40); y = getVarOrDirectWord(0x20); - startWalkActor(a, x, y, 0xFF); + startWalkActor(a, x, y, -1); } void Scumm::o5_walkActorToActor() { @@ -1875,7 +1874,7 @@ void Scumm::o5_walkActorToActor() { else x -= b; - startWalkActor(a, x, y, 0xFF); + startWalkActor(a, x, y, -1); } void Scumm::o5_walkActorToObject() { diff --git a/script_v2.cpp b/script_v2.cpp index cb98b718eb9..f4f2155d53e 100644 --- a/script_v2.cpp +++ b/script_v2.cpp @@ -276,7 +276,7 @@ void Scumm::setupOpcodes2() { &Scumm::o6_distObjectPt, &Scumm::o6_distPtPt, /* C8 */ - &Scumm::o6_invalid, + &Scumm::o6_kernelFunction, &Scumm::o6_miscOps, &Scumm::o6_breakMaybe, &Scumm::o6_pickOneOf, @@ -292,11 +292,11 @@ void Scumm::setupOpcodes2() { &Scumm::o6_invalid, /* D4 */ &Scumm::o6_invalid, - &Scumm::o6_invalid, + &Scumm::o6_jumpToScript, &Scumm::o6_invalid, &Scumm::o6_invalid, /* D8 */ - &Scumm::o6_invalid, + &Scumm::o6_isRoomScriptRunning, &Scumm::o6_invalid, &Scumm::o6_invalid, &Scumm::o6_invalid, @@ -353,7 +353,9 @@ void Scumm::setupOpcodes2() { int Scumm::readArray(int array, int index, int base) { ArrayHeader *ah = (ArrayHeader*)getResourceAddress(rtString, readVar(array)); - assert(ah); + if (ah==NULL) { + error("readArray: invalid array %d (%d)", array, readVar(array)); + } base += index*ah->dim1_size; @@ -617,6 +619,17 @@ void Scumm::o6_startScriptEx() { runScript(script, flags&1, flags&2, args); } +void Scumm::o6_jumpToScript() { + int16 args[16]; + int script,flags; + + getStackList(args,sizeof(args)/sizeof(args[0])); + script = pop(); + flags = pop(); + o6_stopObjectCode(); + runScript(script, flags&1, flags&2, args); +} + void Scumm::o6_startScript() { int16 args[16]; int script; @@ -638,14 +651,19 @@ void Scumm::o6_startObject() { void Scumm::o6_setObjectState() { int a = pop(); + int b = pop(); if (a==0) a=1; - setObjectState(pop(), a, -1, -1); +// debug(1, "setObjectState(%d,%d)", a, b); + + setObjectState(b, a, -1, -1); } void Scumm::o6_setObjectXY() { int y = pop(); int x = pop(); - setObjectState(pop(), 1, x, y); + int obj = pop(); +// debug(1, "setObjectXY(%d,%d,%d)", obj, x, y); + setObjectState(obj, 1, x, y); } void Scumm::o6_stopObjectCode() { @@ -711,7 +729,7 @@ void Scumm::o6_cursorCommand() { break; case 0x99: a = pop(); - setCursorImg(a, pop()); + setCursorImg(a, pop(), 1); break; case 0x9A: a = pop(); @@ -728,6 +746,8 @@ void Scumm::o6_cursorCommand() { case 0xD6: makeCursorColorTransparent(pop()); break; + default: + error("o6_cursorCommand: default case"); } _vars[VAR_CURSORSTATE] = _cursorState; @@ -783,6 +803,8 @@ void Scumm::o6_setState() { int state = pop(); int obj = pop(); +// debug(1, "setState(%d,%d)", obj, state); + putState(obj, state); removeObjectFromRoom(obj); if (_BgNeedsRedraw) @@ -851,7 +873,7 @@ void Scumm::o6_walkActorToObj() { obj = pop(); a = derefActorSafe(pop(), "o6_walkActorToObj"); - if (obj >= 17) { + if (obj >= NUM_ACTORS) { if (whereIsObject(obj)==WIO_NOT_FOUND) return; getObjectXYPos(obj); @@ -870,7 +892,7 @@ void Scumm::o6_walkActorToObj() { x += dist; else x -= dist; - startWalkActor(a, x, a2->y, 0xFF); + startWalkActor(a, x, a2->y, -1); } } @@ -878,7 +900,7 @@ void Scumm::o6_walkActorTo() { int x,y; y = pop(); x = pop(); - startWalkActor(derefActorSafe(pop(), "o6_walkActorTo"), x, y, 0xFF); + startWalkActor(derefActorSafe(pop(), "o6_walkActorTo"), x, y, -1); } void Scumm::o6_putActorInRoom() { @@ -889,6 +911,7 @@ void Scumm::o6_putActorInRoom() { y = pop(); x = pop(); a = derefActorSafe(pop(), "o6_putActorInRoom"); + if (room==0xFF) { room = a->room; } else { @@ -905,8 +928,13 @@ void Scumm::o6_putActorAtObject() { int room,obj,x,y; Actor *a; - room = pop(); - obj = pop(); + if (_features & GF_HAS_ROOMTABLE) { + obj = pop(); + room = getObjectRoom(obj); + } else { + room = pop(); + obj = pop(); + } a = derefActorSafe(pop(), "o6_putActorAtObject"); if (whereIsObject(obj)!=WIO_NOT_FOUND) { @@ -943,35 +971,37 @@ void Scumm::o6_animateActor() { void Scumm::o6_doSentence() { int a,b,c; - SentenceTab *st; a = pop(); pop(); //dummy pop b = pop(); c = pop(); - st = &sentence[++_sentenceIndex]; - - st->unk5 = c; - st->unk4 = b; - st->unk3 = a; - - if (!(st->unk3&0xFF00)) - st->unk2 = 0; - else - st->unk2 = 1; - - st->unk = 0; + doSentence(c,b,a); } void Scumm::o6_pickupObject() { int obj, room; + int i; - room = pop(); - obj = pop(); + if (_features & GF_HAS_ROOMTABLE) { + obj = pop(); + room = getObjectRoom(obj); + } else { + room = pop(); + obj = pop(); + if (room==0) + room = _roomResource; + } + + for(i=1; i<_maxInventoryItems; i++) { + if (_inventory[i] == (uint16)obj) { + putOwner(obj, _vars[VAR_EGO]); + runHook(obj); + return; + } + } - if (room==0) - room = _roomResource; addObjectToInventory(obj, room); putOwner(obj, _vars[VAR_EGO]); putClass(obj, 32, 1); @@ -987,9 +1017,15 @@ void Scumm::o6_loadRoomWithEgo() { y = pop(); x = pop(); - room = pop(); - obj = pop(); - + + if (_features & GF_HAS_ROOMTABLE) { + obj = pop(); + room = getObjectRoom(obj); + } else { + room = pop(); + obj = pop(); + } + a = derefActorSafe(_vars[VAR_EGO], "o_loadRoomWithEgo"); putActor(a, 0, 0, room); @@ -1004,7 +1040,7 @@ void Scumm::o6_loadRoomWithEgo() { setCameraFollows(a); _fullRedraw=1; if (x != -1) { - startWalkActor(a, x, y, 0xFF); + startWalkActor(a, x, y, -1); } } @@ -1028,7 +1064,11 @@ void Scumm::o6_getActorMoving() { } void Scumm::o6_getScriptRunning() { - push(getScriptRunning(pop())); + push(isScriptRunning(pop())); +} + +void Scumm::o6_isRoomScriptRunning() { + push(isRoomScriptRunning(pop())); } void Scumm::o6_getActorRoom() { @@ -1044,11 +1084,18 @@ void Scumm::o6_getObjectY() { } void Scumm::o6_getObjectDir() { - push(getObjDir(pop())); + int dir = getObjDir(pop()); + + if (_features & GF_USE_ANGLES) { + dir = oldDirToNewDir(dir); + } + + push(dir); } void Scumm::o6_getActorWalkBox() { - push(derefActorSafe(pop(),"o6_getActorWalkBox")->walkbox); + Actor *a = derefActorSafe(pop(),"o6_getActorWalkBox"); + push(a->ignoreBoxes ? 0 : a->walkbox); } void Scumm::o6_getActorCostume() { @@ -1086,7 +1133,7 @@ void Scumm::o6_setObjectName() { int obj = pop(); int i; - if (obj <= _vars[VAR_NUM_ACTOR]) + if (obj < NUM_ACTORS) error("Can't set actor %d name with new-name-of", obj); if (!getObjectAddress(obj)) @@ -1137,6 +1184,7 @@ void Scumm::o6_createBoxMatrix() { void Scumm::o6_resourceRoutines() { int res; + int obj,room; switch(fetchScriptByte()) { case 100: /* load script */ @@ -1226,8 +1274,7 @@ void Scumm::o6_resourceRoutines() { nukeCharset(res); break; case 119:/* load fl object */ - res = pop(); - loadFlObject(pop(), res); + loadFlObject(pop(), (_features & GF_HAS_ROOMTABLE) ? -1 : pop()); break; default: error("o6_resourceRoutines: default case"); @@ -1245,8 +1292,8 @@ void Scumm::o6_roomOps() { if (a > ((_scrWidthIn8Unit-20)<<3)) a=((_scrWidthIn8Unit-20)<<3); if (b < 160) b=160; if (b > ((_scrWidthIn8Unit-20)<<3)) b=((_scrWidthIn8Unit-20)<<3); - _vars[VAR_CAMERA_MIN] = a; - _vars[VAR_CAMERA_MAX] = b; + _vars[VAR_CAMERA_MIN_X] = a; + _vars[VAR_CAMERA_MAX_X] = b; break; case 174: /* set screen */ @@ -1430,6 +1477,7 @@ void Scumm::o6_actorSet() { case 93: a->neverZClip = 0; break; + case 225: case 94: a->neverZClip = pop(); break; @@ -1448,8 +1496,8 @@ FixRooms:; a->animSpeed = pop(); a->animProgress = 0; break; - case 98: /* set data8 */ - a->data8 = pop(); + case 98: + a->unk1 = pop(); break; case 99: a->new_1 = pop(); @@ -1463,9 +1511,22 @@ FixRooms:; break; case 217: initActor(a, 2); - break; + break; + case 235: /* talk_script */ + a->talk_script = pop(); + break; + + case 198: /* set anim variable */ + case 227: /* actor_unk2 */ + case 228: /* actor script */ + case 229: /* stand */ + case 230: /* turn? */ + case 231: /* turn? */ + case 233: /* ? */ + case 234: /* ? */ + default: - error("o6_actorset: default case"); + error("o6_actorset: default case %d", b); } } @@ -1742,8 +1803,8 @@ void Scumm::o6_wait() { break; return; case 171: - if (_sentenceIndex!=0xFF) { - if (sentence[_sentenceIndex].unk && + if (_sentenceNum) { + if (sentence[_sentenceNum-1].unk && !isScriptInUse(_vars[VAR_SENTENCE_SCRIPT]) ) return; break; @@ -1832,7 +1893,7 @@ void Scumm::o6_delayVeryLong() { } void Scumm::o6_stopSentence() { - _sentenceIndex = 0xFF; + _sentenceNum = 0; stopScriptNr(_vars[VAR_SENTENCE_SCRIPT]); clearClickedStatus(); } @@ -1992,6 +2053,78 @@ void Scumm::o6_miscOps() { Actor *a; getStackList(args,sizeof(args)/sizeof(args[0])); + +#if defined(FULL_THROTTLE) + switch(args[0]) { + case 4: + grabCursor(args[1], args[2], args[3], args[4]); + break; + case 6: + warning("o6_miscOps: startVideo(%d,%s)", args[1], getStringAddress(_vars[0xf6/2])); + break; + case 7: + warning("o6_miscOps: stub7()"); + break; + case 10: + warning("o6_miscOps: stub10(%d,%d,%d,%d)",args[1],args[2],args[3],args[4]); + break; + case 11: + warning("o6_miscOps: stub11(%d)", args[1]); + break; + case 12: + setCursorImg(args[1], -1, args[2]); + break; + case 13: + warning("o6_miscOps: stub13(%d,%d,%d,%d)",args[1],args[2],args[3],args[4]); + break; + case 14: + remapActor(derefActorSafe(args[1], "o6_miscOps:14"), args[2],args[3],args[4],args[5]); + break; + case 15: + warning("o6_miscOps: stub15(%d)", args[1]); + break; + case 16: + warning("o6_miscOps: stub16(%d,%d,%d,%d)",args[1],args[2],args[3],args[4]); + break; + case 17: + warning("o6_miscOps: stub17(%d,%d,%d,%d)",args[1],args[2],args[3],args[4]); + break; + case 18: + warning("o6_miscOps: stub18(%d,%d)", args[1], args[2]); + break; + case 107: + a = derefActorSafe(args[1], "o6_miscops: 107"); + a->scalex = args[2]; + a->needBgReset = true; + a->needRedraw = true; + break; + case 108: + setupShadowPalette(args[1],args[2],args[3],args[4],args[5],args[6]); + break; + case 109: + setupShadowPalette(0, args[1],args[2],args[3],args[4],args[5]); + break; + case 114: + warning("o6_miscOps: stub114()"); + break; + case 117: + warning("o6_miscOps: stub117()"); + break; + case 118: + warning("o6_miscOps: stub118(%d,%d,%d,%d,%d,%d,%d,%d)",args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]); + break; + case 119: + warning("o6_miscOps: stub119(%d,%d,%d,%d,%d,%d,%d,%d)",args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]); + break; + case 120: + warning("o6_miscOps: stub120(%d,%d)", args[1], args[2]); + break; + case 124: + warning("o6_miscOps: stub124(%d)", args[1]); + break; + } + +#else switch(args[0]) { case 3: warning("o6_miscOps: nothing in 3"); @@ -2049,7 +2182,7 @@ void Scumm::o6_miscOps() { case 111: a = derefActorSafe(args[1], "o6_miscops: 111"); - a->data8 = args[2] + args[3]; + a->unk1 = args[2] + args[3]; break; case 112: @@ -2099,6 +2232,54 @@ void Scumm::o6_miscOps() { default: error("o6_miscOps: default case %d", args[0]); } +#endif +} + +void Scumm::o6_kernelFunction() { + int16 args[30]; + int i; + Actor *a; + + getStackList(args,sizeof(args)/sizeof(args[0])); + + switch(args[0]) { + case 115: + warning("o6_kernelFunction: stub115(%d,%d)", args[1], args[2]); + push(0); + break; + case 116: + push(checkXYInBoxBounds(args[3], args[1], args[2])); + break; + case 206: + push(remapPaletteColor(args[1],args[2],args[3],(uint)-1)); + break; + case 207: + i = getObjectIndex(pop()); + push(_objs[i].x_pos); + break; + case 208: + i = getObjectIndex(pop()); + push(_objs[i].y_pos); + break; + case 209: + i = getObjectIndex(pop()); + push(_objs[i].width); + break; + case 210: + i = getObjectIndex(pop()); + push(_objs[i].height); + break; + case 211: + warning("o6_kernelFunction: stub211(%d)", args[1]); + push(0); + break; + case 212: + a = derefActorSafe(args[1], "o6_kernelFunction:212"); + push(a->frame); + break; + default: + error("o6_kernelFunction: default case %d", args[0]); + } } void Scumm::o6_breakMaybe() { @@ -2179,7 +2360,8 @@ void Scumm::decodeParseString2(int m, int n) { switch(m) { case 0: actorTalk(); break; case 1: drawString(1); break; - case 2: unkMessage1(); break; + + case 2: unkMessage1(); break; case 3: unkMessage2(); break; } _scriptPointer = _messagePtr; diff --git a/scumm.h b/scumm.h index cca1a404027..cb577ec010b 100644 --- a/scumm.h +++ b/scumm.h @@ -34,14 +34,20 @@ enum { BITS_PER_SAMPLE = 16, NUM_MIXER = 4, NUM_SCRIPT_SLOT = 25, + NUM_LOCALSCRIPT = 60, + NUM_SHADOW_PALETTE = 8, +#if defined(FULL_THROTTLE) + NUM_ACTORS = 30 +#else NUM_ACTORS = 13 +#endif }; + struct Point { int x,y; }; - #pragma START_PACK_STRUCTS #define SIZEOF_BOX 20 @@ -61,6 +67,9 @@ struct ResHeader { struct RoomHeader { uint32 tag, size; +#ifdef FULL_THROTTLE + uint32 version; +#endif uint16 width,height; uint16 numObjects; } GCC_PACK; @@ -71,6 +80,39 @@ struct BompHeader { uint16 width,height; } GCC_PACK; +struct AkosHeader { + uint32 tag; + uint32 size; + byte x_1[2]; + byte flags; + byte x_2; + uint16 num_anims; + uint16 x_3; + uint16 codec; +} GCC_PACK; + +struct AkosOffset { + uint32 akcd; + uint16 akci; +} GCC_PACK; + +struct AkosCI { + uint16 width,height; + int16 rel_x, rel_y; + int16 move_x, move_y; +} GCC_PACK; + +#if defined(FULL_THROTTLE) +struct CodeHeader { + uint32 tag; + uint32 size; + uint32 version; + uint16 obj_id; + byte parent; + byte parentstate; +} GCC_PACK; + +#else struct CodeHeader { uint32 id; uint32 size; @@ -96,7 +138,25 @@ struct CodeHeader { } v6; }; } GCC_PACK; +#endif +#if defined(FULL_THROTTLE) +struct ImageHeader { /* file format */ + uint32 tag; + uint32 size; + uint32 version; + uint16 obj_id; + uint16 unk[1]; + int16 x_pos,y_pos; + uint16 width,height; + byte unk2[3]; + byte actordir; + uint16 unk_2; + struct { + int16 x,y; + } hotspot[15]; +} GCC_PACK; +#else struct ImageHeader { /* file format */ uint32 id; uint32 size; @@ -109,7 +169,7 @@ struct ImageHeader { /* file format */ int16 x,y; } hotspot[15]; } GCC_PACK; - +#endif #pragma END_PACK_STRUCTS struct AdjustBoxResult { @@ -139,27 +199,29 @@ public: uint16 obj_nr; int16 x_pos; int16 y_pos; - uint16 numstrips; + uint16 width; uint16 height; byte actordir; byte parent; byte parentstate; - byte ownerstate; + byte state; byte fl_object_index; - byte unk_3; }; struct CostumeData { - uint16 hdr; + byte active[16]; uint16 animCounter1; byte animCounter2; - byte x_1; - uint16 a[16], b[16], c[16], d[16]; + uint16 stopped; + uint16 curpos[16]; + uint16 start[16]; + uint16 end[16]; + uint16 frame[16]; }; struct EnqueuedObject { uint16 a,b,c,d,e; - uint16 x,y; + int16 x,y; uint16 width,height; uint16 j,k,l; }; @@ -190,9 +252,8 @@ struct VirtScreen { struct ActorWalkData { int16 destx,desty; byte destbox; - byte destdir; + int16 destdir; byte curbox; - byte field_7; int16 x,y,newx,newy; int32 XYFactor, YXFactor; uint16 xfrac,yfrac; @@ -232,9 +293,11 @@ enum { sleUint32 = 5 }; +#if !defined(FULL_THROTTLE) + enum ScummVars { VAR_EGO = 1, - VAR_CAMERA_CUR_POS = 2, + VAR_CAMERA_POS_X = 2, VAR_HAVE_MSG = 3, VAR_ROOM = 4, VAR_OVERRIDE = 5, @@ -243,8 +306,8 @@ enum ScummVars { VAR_TMR_1 = 11, VAR_TMR_2 = 12, VAR_TMR_3 = 13, - VAR_CAMERA_MIN = 17, - VAR_CAMERA_MAX = 18, + VAR_CAMERA_MIN_X = 17, + VAR_CAMERA_MAX_X = 18, VAR_TIMER_NEXT = 19, VAR_VIRT_MOUSE_X = 20, VAR_VIRT_MOUSE_Y = 21, @@ -252,7 +315,7 @@ enum ScummVars { VAR_LAST_SOUND = 23, VAR_CUTSCENEEXIT_KEY = 24, VAR_TALK_ACTOR = 25, - VAR_CAMERA_FAST = 26, + VAR_CAMERA_FAST_X = 26, VAR_SCROLL_SCRIPT = 27, VAR_ENTRY_SCRIPT = 28, VAR_ENTRY_SCRIPT2 = 29, @@ -305,9 +368,90 @@ enum ScummVars { VAR_V6_SCREEN_HEIGHT = 54, VAR_V6_EMSSPACE = 76, VAR_V6_RANDOM_NR = 118, - }; +#else + +enum ScummVars { + VAR_MOUSE_X = 1, + VAR_MOUSE_Y = 2, + VAR_VIRT_MOUSE_X = 3, + VAR_VIRT_MOUSE_Y = 4, + VAR_V6_SCREEN_WIDTH = 5, + VAR_V6_SCREEN_HEIGHT = 6, + VAR_CAMERA_POS_X = 7, + VAR_CAMERA_POS_Y = 8, + VAR_OVERRIDE = 9, + VAR_ROOM = 10, + VAR_ROOM_RESOURCE = 11, + VAR_TALK_ACTOR = 12, + VAR_HAVE_MSG = 13, + VAR_TIMER = 14, + VAR_TMR_4 = 15, + VAR_PERFORMANCE_1 = 26, + VAR_PERFORMANCE_2 = 27, + VAR_GAME_LOADED = 29, + VAR_V6_RANDOM_NR = 34, + VAR_NEW_ROOM = 35, + VAR_WALKTO_OBJ = 36, + + VAR_SCROLL_SCRIPT = 50, + VAR_ENTRY_SCRIPT = 51, + VAR_ENTRY_SCRIPT2 = 52, + VAR_EXIT_SCRIPT = 53, + VAR_EXIT_SCRIPT2 = 54, + VAR_VERB_SCRIPT = 55, + VAR_SENTENCE_SCRIPT = 56, + VAR_HOOK_SCRIPT = 57, + VAR_CUTSCENE_START_SCRIPT = 58, + VAR_CUTSCENE_END_SCRIPT = 59, + VAR_UNK_SCRIPT = 60, + VAR_UNK_SCRIPT_2 = 61, + + VAR_PAUSE_KEY = 63, + VAR_RESTART_KEY = 64, /* ?? */ + VAR_TALKSTOP_KEY = 65, /* ?? */ + VAR_SAVELOADDIALOG_KEY = 66, /* ?? */ + VAR_CUTSCENEEXIT_KEY = 24, + + VAR_TIMER_NEXT = 97, + VAR_TMR_1 = 98, + VAR_TMR_2 = 99, + VAR_TMR_3 = 100, + + VAR_CAMERA_MIN_X = 101, + VAR_CAMERA_MAX_X = 102, + VAR_CAMERA_MIN_Y = 103, + VAR_CAMERA_MAX_Y = 104, + VAR_CAMERA_FAST_X = 105, + VAR_CAMERA_FAST_Y = 106, + VAR_CAMERA_SPEED_X = 107, + VAR_CAMERA_SPEED_Y = 108, + VAR_CAMERA_ACCEL_X = 109, + VAR_CAMERA_ACCEL_Y = 110, + + VAR_EGO = 111, + + VAR_CURSORSTATE = 112, + VAR_USERPUT = 113, + VAR_DEFAULT_TALK_DELAY = 114, + VAR_CHARINC = 115, + VAR_DEBUGMODE = 116, + + //VAR_V5_DRAWFLAGS = 9, + VAR_MI1_TIMER = 14, + VAR_V5_OBJECT_LO = 15, + VAR_V5_OBJECT_HI = 16, + VAR_V5_TALK_STRING_Y = 54, + VAR_V5_CHARFLAG = 60, + + VAR_V6_EMSSPACE = 76, + +}; + +#endif + + enum ResTypes { rtFirst = 1, rtRoom = 1, @@ -333,7 +477,12 @@ enum ResTypes { enum { OF_OWNER_MASK = 0x0F, OF_STATE_MASK = 0xF0, + +#if defined(FULL_THROTTLE) + OF_OWNER_ROOM = 0xFF, +#else OF_OWNER_ROOM = 0x0F, +#endif OF_STATE_SHL = 4 }; @@ -357,6 +506,13 @@ enum { RF_USAGE_MAX = RF_USAGE }; +enum MoveFlags { + MF_NEW_LEG = 1, + MF_IN_LEG = 2, + MF_TURN = 4, + MF_LAST_LEG = 8, +}; + #define _maxRooms res.num[rtRoom] #define _maxScripts res.num[rtScript] #define _maxCostumes res.num[rtCostume] @@ -424,6 +580,58 @@ struct CharsetRenderer { void addLinebreaks(int a, byte *str, int pos, int maxwidth); }; +struct AkosRenderer { + CostumeData *cd; + int x,y; /* where to draw costume */ + byte scale_x, scale_y; /* scaling */ + byte clipping; /* clip mask */ + byte actor_unk1; + uint16 codec; + bool mirror; /* draw actor mirrored */ + byte dirty_id; + byte *outptr; + int outwidth, outheight; + + /* pointer to various parts of the costume resource */ + byte *akos; + AkosHeader *akhd; + + /* current move offset */ + int move_x, move_y; + /* movement of cel to decode */ + int move_x_cur, move_y_cur; + /* width and height of cel to decode */ + int width,height; + + byte *srcptr; + + struct { + /* codec stuff */ + const byte *scaletable; + byte mask,shl; + bool doContinue; + byte repcolor; + byte replen; + int scaleXstep; + int x,y; + int tmp_x, tmp_y; + int y_pitch; + int skip_width; + byte *destptr; + byte *mask_ptr,*mask_ptr_dest; + int imgbufoffs; + } v1; + + /* put less used stuff at the bottom to optimize opcodes */ + int draw_top, draw_bottom; + byte *akpl,*akci,*aksq; + AkosOffset *akof; + byte *akcd; + + + byte palette[256]; +}; + struct CostumeRenderer { Scumm *_vm; byte *_ptr; @@ -485,30 +693,37 @@ struct Actor { int elevation; uint width; byte number; - byte facing; + uint16 facing; uint16 costume; byte room; byte talkColor; byte scalex,scaley; byte charset; - byte newDirection; + int16 newDirection; byte moving; byte ignoreBoxes; byte neverZClip; byte initFrame,walkFrame,standFrame,talkFrame1,talkFrame2; bool needRedraw, needBgReset,costumeNeedsInit,visible; + byte unk1; +#if defined(FULL_THROTTLE) + bool flip; +#endif uint speedx,speedy; - byte data8; - byte animIndex; + byte frame; byte walkbox; byte mask; byte animProgress, animSpeed; int16 new_1,new_2; + uint16 talk_script, walk_script; byte new_3; - byte sound[8]; ActorWalkData walkdata; +//#if defined(FULL_THROTTLE) + int16 animVariable[16]; +//#endif + uint16 sound[8]; CostumeData cost; - byte palette[32]; + byte palette[64]; }; struct CameraData { @@ -606,7 +821,7 @@ struct Gdi { void decompressBitmap(); - void drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, int stripnr, int numstrip, bool flag); + void drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, int stripnr, int numstrip, byte flag); void clearUpperMask(); void disableZBuffer() { _disable_zbuffer++; } @@ -621,6 +836,13 @@ struct Gdi { void resetBackground(byte top, byte bottom, int strip); void drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b); void updateDirtyScreen(VirtScreen *vs); + + + enum DrawBitmapFlags { + dbAllowMaskOr = 1, + dbDrawMaskOnBoth = 2, + dbClear = 4, + }; }; struct MixerChannel { @@ -642,6 +864,17 @@ enum GameId { GID_SAMNMAX = 5, }; +enum GameFeatures { + GF_NEW_OPCODES = 1, + GF_AFTER_V6 = 2, + GF_AFTER_V7 = 4, + GF_HAS_ROOMTABLE = GF_AFTER_V7, + GF_USE_KEY = 8, + GF_USE_ANGLES = GF_AFTER_V7, + + GF_DEFAULT = GF_USE_KEY, +}; + struct ScummDebugger; struct Serializer; @@ -654,12 +887,20 @@ enum WhereIsObject { WIO_FLOBJECT = 4, }; +struct BoxCoords { + Point ul; + Point ur; + Point ll; + Point lr; +}; + struct Scumm { + uint32 _features; const char *_gameText; byte _gameId; - byte _majorScummVersion; - byte _middleScummVersion; - byte _minorScummVersion; +// byte _majorScummVersion; +// byte _middleScummVersion; +// byte _minorScummVersion; ScummDebugger *_debugger; void *_gui; /* actually a pointer to a Gui */ @@ -698,6 +939,9 @@ struct Scumm { const OpcodeProc *_opcodes; + int _xPos, _yPos; + int _dir; + byte _curActor; int _curVerb; int _curVerbSlot; @@ -706,6 +950,11 @@ struct Scumm { VirtScreen *_curVirtScreen; + + byte *_scriptPointer, *_scriptOrgPointer; + byte *_scriptPointerStart; + byte _opcode; + int _numVariables; int _numBitVariables; int _numLocalObjects; @@ -719,18 +968,17 @@ struct Scumm { int _numSounds; int _numCharsets; int _numCostumes; + int _numNewNames; + int _numGlobalScripts; byte *_msgPtrToAdd; uint8 *_roomFileIndexes; - byte *_objectFlagTable; + byte *_objectOwnerTable; + byte *_objectRoomTable; + byte *_objectStateTable; uint32 *_classData; - byte _numGlobalScripts; - byte *_scriptPointer, *_scriptOrgPointer; - byte *_scriptPointerStart; - byte _opcode; - byte _expire_counter; bool _noTalkAnims; @@ -804,7 +1052,7 @@ struct Scumm { int _numInMsgStack; - uint32 _localScriptList[0x39]; + uint32 _localScriptList[NUM_LOCALSCRIPT]; VirtScreen virtscr[4]; @@ -857,18 +1105,7 @@ struct Scumm { Actor actor[NUM_ACTORS]; - uint16 actorDrawBits[200]; - - struct { - int upperLeftX; - int upperRightX; - int lowerLeftX; - int lowerRightX; - int upperLeftY; - int upperRightY; - int lowerLeftY; - int lowerRightY; - } box; + uint32 gfxUsageBits[200]; CharsetRenderer charset; @@ -876,7 +1113,11 @@ struct Scumm { byte _resourceMapper[128]; + uint16 _extraBoxFlags[65]; + byte **_lastCodePtr; + + byte *_shadowPalette; int _numSoundTags; byte *_soundTagTable; @@ -890,14 +1131,11 @@ struct Scumm { uint32 _whereInResToRead; - int _xPos, _yPos; - byte _dir; - CameraData camera; int _resultVarNumber; - byte _sentenceIndex; + int _sentenceNum; SentenceTab sentence[6]; StringTab string[6]; @@ -991,12 +1229,10 @@ struct Scumm { void readResTypeList(int id, uint32 tag, const char *name); void allocResTypeData(int id, uint32 tag, int num, const char *name, int mode); - void initThingsV5(); - void initThingsV6(); - void initRandSeeds(); uint getRandomNumber(uint max); + uint getRandomNumberRng(uint min, uint max); void loadCharset(int i); void nukeCharset(int i); @@ -1035,7 +1271,7 @@ struct Scumm { void setActorWalkSpeed(Actor *a, uint speed1, uint speed2); int calcMovementFactor(Actor *a, int newx, int newy); int actorWalkStep(Actor *a); - int getProgrDirChange(Actor *a, int mode); + int remapDirection(Actor *a, int dir); bool checkXYInBoxBounds(int box, int x, int y); void setupActorScale(Actor *a); @@ -1051,13 +1287,14 @@ struct Scumm { void putState(int obj, int state); int getOwner(int obj); void putOwner(int obj, int owner); + int getObjectRoom(int obj); void main(); uint distanceFromPt(int x, int y, int ptx, int pty); Point closestPtOnLine(int ulx, int uly, int llx, int lly, int x, int y); bool getSideOfLine(int x1,int y1, int x2, int y2, int x, int y, int box); - void getBoxCoordinates(int box); + void getBoxCoordinates(int boxnum, BoxCoords *bc); byte getMaskFromBox(int box); Box *getBoxBaseAddr(int box); byte getBoxFlags(int box); @@ -1065,9 +1302,13 @@ struct Scumm { byte getNumBoxes(); byte *getBoxMatrixBaseAddr(); - void startAnimActor(Actor *a, int frame, byte direction); +// void startAnimActor(Actor *a, int frame); + void startAnimActor(Actor *a, int frame); + void startAnimActorEx(Actor *a, int frame, int direction); +// void startAnimActor(Actor *a, int frame, byte direction); + int getProgrDirChange(Actor *a, int mode); void initActorCostumeData(Actor *a); - void fixActorDirection(Actor *a, byte direction); + void fixActorDirection(Actor *a, int direction); void decodeCostData(Actor *a, int frame, uint mask); void scummInit(); @@ -1337,6 +1578,9 @@ struct Scumm { void o6_breakMaybe(); void o6_pickOneOf(); void o6_pickOneOfDefault(); + void o6_jumpToScript(); + void o6_isRoomScriptRunning(); + void o6_kernelFunction(); void soundKludge(int16 *list); @@ -1358,7 +1602,7 @@ struct Scumm { bool isScriptInUse(int script); int getActorXYPos(Actor *a); void getObjectXYPos(int object); - AdjustBoxResult adjustXYToBeInBox(Actor *a, int x, int y); + AdjustBoxResult adjustXYToBeInBox(Actor *a, int x, int y, int pathfrom); int getWordVararg(int16 *ptr); @@ -1410,7 +1654,7 @@ struct Scumm { int hasCharsetMask(int x, int y, int x2, int y2); void restoreBG(int left, int top, int right, int bottom); - void updateDirtyRect(int virt, int left, int right, int top, int bottom, uint16 dirtybits); + void updateDirtyRect(int virt, int left, int right, int top, int bottom, uint32 dirtybits); VirtScreen *findVirtScreen(int y); void unkScreenEffect1(); @@ -1454,8 +1698,8 @@ struct Scumm { int checkKeyHit(); - int getPathToDestBox(int from, int to); - int findPathTowards(Actor *a, int box, int box2, int box3); + int getPathToDestBox(byte from, byte to); + int findPathTowards(Actor *a, byte box, byte box2, byte box3); void setActorCostPalette(Actor *a); void drawActorCostume(Actor *a); @@ -1476,7 +1720,7 @@ struct Scumm { void walkActorTo(Actor *a, int x, int y, int direction); - void setCursorImg(uint cursor, uint img); + void setCursorImg(uint img, uint room, uint imgindex); void setCursorHotspot(int cursor, int x, int y); void initCharset(int charset); void addObjectToDrawQue(int object); @@ -1495,7 +1739,7 @@ struct Scumm { void unlock(int type, int i); void heapClear(int mode); void unkHeapProc2(int a, int b); - void loadFlObject(int a, int b); + void loadFlObject(uint object, uint room); void setPalColor(int index, int r, int g, int b); void darkenPalette(int a, int b, int c, int d, int e); void unkRoomFunc3(int a, int b, int c, int d, int e); @@ -1579,7 +1823,8 @@ struct Scumm { void faceActorToObj(int act, int obj); void animateActor(int act, int anim); - int getScriptRunning(int script); + bool isScriptRunning(int script); + bool isRoomScriptRunning(int script); int getObjX(int obj); int getObjY(int obj); int getObjDir(int obj); @@ -1597,7 +1842,7 @@ struct Scumm { void readArrayFromIndexFile(); void readMAXS(); - void readIndexFileV6(); + void readIndexFile(); int readArray(int array, int index, int base); void writeArray(int array, int index, int base, int value); @@ -1619,7 +1864,7 @@ struct Scumm { void grabCursor(int x, int y, int w, int h); void unkMiscOp9(); void startManiac(); - void readIndexFileV5(int i); + void grabCursor(byte *ptr, int width, int height); byte *getPalettePtr(); void setupSound(); @@ -1681,10 +1926,129 @@ struct Scumm { void stopSfxSound(); void mixWaves(int16 *sounds, int len); - + struct FindObjectInRoom { + CodeHeader *cdhd; + byte *obcd; + ImageHeader *imhd; + byte *obim; + byte *roomptr; + }; + + enum FindObjectWhat { + foCodeHeader = 1, + foImageHeader = 2, + foCheckAlreadyLoaded = 4, + }; + + void findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint object, uint room); + void setupRoomObject(ObjectData *od, byte *room); + int findFlObjectSlot(); + + void runTalkScript(int frame); + + int remapPaletteColor(byte r, byte g, byte b, uint threshold); + void remapActor(Actor *a, int b, int c, int d, int e); + + byte *findResourceData(uint32 tag, byte *ptr); + + void akos_decodeData(Actor *a, int frame, uint usemask); + int akos_frameToAnim(Actor *a, int frame); + bool akos_hasManyDirections(Actor *a); + void stopActorMoving(Actor *a) { a->moving = 0; } + + int newDirToOldDir(int dir); + int oldDirToNewDir(int dir); + void startWalkAnim(Actor *a, int cmd, int angle); + void setActorBox(Actor *a, int box); + int getAngleFromPos(int x, int y); + int updateActorDirection(Actor *a); + + bool akos_drawCostume(AkosRenderer *ar); + void akos_setPalette(AkosRenderer *ar, byte *palette); + void akos_setCostume(AkosRenderer *ar, int costume); + void akos_setFacing(AkosRenderer *ar, Actor *a); + bool akos_drawCostumeChannel(AkosRenderer *ar, int chan); + void akos_codec1(AkosRenderer *ar); + void akos_codec5(AkosRenderer *ar); + void akos_codec16(AkosRenderer *ar); + void akos_codec1_ignorePakCols(AkosRenderer *ar, int num); + void akos_c1_spec1(AkosRenderer *ar); + void akos_c1_spec2(AkosRenderer *ar); + void akos_c1_spec3(AkosRenderer *ar); + + void akos_c1_0_decode(AkosRenderer *ar); + void akos_c1_12_decode(AkosRenderer *ar); + void akos_c1_12y_decode(AkosRenderer *ar); + void akos_c1_3_decode(AkosRenderer *ar); + void akos_c1_4_decode(AkosRenderer *ar); + void akos_c1_4y_decode(AkosRenderer *ar); + void akos_c1_56_decode(AkosRenderer *ar); + void akos_c1_56y_decode(AkosRenderer *ar); + void akos_c1_7_decode(AkosRenderer *ar); + + bool akos_increaseAnims(byte *akos, Actor *a); + bool akos_increaseAnim(Actor *a, int i, byte *aksq, uint16 *akfo, int numakfo); + + int getAnimVar(Actor *a, byte var); + void setAnimVar(Actor *a, byte var, int value); + + void akos_queCommand(byte cmd, Actor *a, int param_1, int param_2); + bool akos_compare(int a, int b, byte cmd); + + static int normalizeAngle(int angle); + static int fromSimpleDir(int dir); + static int toSimpleDir(int dir); + + void doSentence(int c, int b, int a); + int cost_frameToAnim(Actor *a, int frame); + + void setupShadowPalette(int slot,int rfact,int gfact,int bfact,int from,int to); }; +enum AkosOpcodes{ + AKC_Return = 0xC001, + AKC_SetVar = 0xC010, + AKC_CmdQue3 = 0xC015, + AKC_ComplexChan = 0xC020, + AKC_Jump = 0xC030, + AKC_JumpIfSet = 0xC031, + AKC_AddVar = 0xC040, + AKC_Ignore = 0xC050, + AKC_IncVar = 0xC060, + AKC_CmdQue3Quick = 0xC061, + AKC_SkipStart = 0xC070, + AKC_SkipE = 0xC070, + AKC_SkipNE = 0xC071, + AKC_SkipL = 0xC072, + AKC_SkipLE = 0xC073, + AKC_SkipG = 0xC074, + AKC_SkipGE = 0xC075, + AKC_StartAnim = 0xC080, + AKC_StartVarAnim = 0xC081, + AKC_Random = 0xC082, + AKC_SetActorClip = 0xC083, + AKC_StartAnimInActor = 0xC084, + AKC_SetVarInActor = 0xC085, + AKC_HideActor = 0xC086, + AKC_SetDrawOffs = 0xC087, + AKC_JumpTable = 0xC088, + AKC_SoundStuff = 0xC089, + AKC_Flip = 0xC08A, + AKC_Cmd3 = 0xC08B, + AKC_Ignore3 = 0xC08C, + AKC_Ignore2 = 0xC08D, + AKC_JumpStart = 0xC090, + AKC_JumpE = 0xC090, + AKC_JumpNE = 0xC091, + AKC_JumpL = 0xC092, + AKC_JumpLE = 0xC093, + AKC_JumpG = 0xC094, + AKC_JumpGE = 0xC095, + AKC_ClearFlag = 0xC09F, +}; + + struct ScummDebugger { Scumm *_s; byte _command; @@ -1746,6 +2110,7 @@ struct Serializer { }; +extern const uint32 IMxx_tags[]; void outputdisplay2(Scumm *s, int disp); extern const byte revBitMask[8]; @@ -1765,7 +2130,8 @@ void updateScreen(Scumm *s); void drawMouse(Scumm *s, int x, int y, int color, byte *mask, bool visible); void drawMouse(Scumm *s, int x, int y, int w, int h, byte *buf, bool visible); void blit(byte *dst, byte *src, int w, int h); -byte *findResource(uint32 id, byte *searchin, int index); +byte *findResource(uint32 tag, byte *searchin, int index); +byte *findResource(uint32 tag, byte *searchin); void playSfxSound(void *sound, uint32 size, uint rate); bool isSfxFinished(); void waitForTimer(Scumm *s, int msec_delay); \ No newline at end of file diff --git a/scummvm.cpp b/scummvm.cpp index 7f08723fd4f..cfad282df99 100644 --- a/scummvm.cpp +++ b/scummvm.cpp @@ -23,31 +23,6 @@ #include "scumm.h" #include "gui.h" -void Scumm::initThingsV5() { - readIndexFileV5(1); - - _numVariables = 800; - _numBitVariables = 2048; - _numLocalObjects = 200; - _numVerbs = 100; - _numInventory = 80; - _numVerbs = 100; - _numArray = 0x32; - _numFlObject = 0x32; - - allocateArrays(); - - readIndexFileV5(2); - initRandSeeds(); - - setupOpcodes(); -} - -void Scumm::initThingsV6() { - setupOpcodes2(); - readIndexFileV6(); -} - void Scumm::initRandSeeds() { _randSeed1 = 0xA943DE35; _randSeed2 = 0x37A9ED27; @@ -60,12 +35,17 @@ uint Scumm::getRandomNumber(uint max) { return _randSeed1%max; } +uint Scumm::getRandomNumberRng(uint min, uint max) { + return getRandomNumber(max-min+1)+min; +} + + void Scumm::scummInit() { int i; Actor *a; debug(9, "scummInit"); -// readIndexFile(3); + loadCharset(1); initScreens(0, 16, 320, 144); @@ -107,9 +87,10 @@ void Scumm::scummInit() { virtscr[0].xstart = 0; +#if !defined(FULL_THROTTLE) _vars[VAR_V5_DRAWFLAGS] = 11; - _vars[VAR_59] = 3; +#endif mouse.x = 104; mouse.y = 56; @@ -118,7 +99,7 @@ void Scumm::scummInit() { _EXCD_offs = 0; _currentScript = 0xFF; - _sentenceIndex = 0xFF; + _sentenceNum = 0; _currentRoom = 0; _numObjectsInRoom = 0; @@ -157,7 +138,7 @@ void Scumm::scummInit() { initScummVars(); - if (_majorScummVersion==5) + if (!(_features&GF_AFTER_V6)) _vars[VAR_V5_TALK_STRING_Y] = -0x50; getGraphicsPerformance(); @@ -165,6 +146,7 @@ void Scumm::scummInit() { void Scumm::initScummVars() { +#if !defined(FULL_THROTTLE) _vars[VAR_CURRENTDRIVE] = _currentDrive; _vars[VAR_FIXEDDISK] = checkFixedDisk(); _vars[VAR_SOUNDCARD] = _soundCardType; @@ -174,8 +156,9 @@ void Scumm::initScummVars() { _vars[VAR_SOUNDPARAM] = _soundParam; _vars[VAR_SOUNDPARAM2] = _soundParam2; _vars[VAR_SOUNDPARAM3] = _soundParam3; - if (_majorScummVersion==6) + if (_features&GF_AFTER_V6) _vars[VAR_V6_EMSSPACE] = 10000; +#endif } void Scumm::checkRange(int max, int min, int no, const char *str) { @@ -206,7 +189,7 @@ void Scumm::scummMain(int argc, char **argv) { if (!detectGame()) { warning("Game detection failed. Using default settings"); - _majorScummVersion = 5; + _features = GF_DEFAULT; } if (_gameId==GID_INDY4 && _bootParam==0) { @@ -217,17 +200,22 @@ void Scumm::scummMain(int argc, char **argv) { _bootParam = 10001; } - initGraphics(this, _fullScreen); - if (_majorScummVersion==6) - initThingsV6(); + readIndexFile(); + + initRandSeeds(); + + if (_features & GF_NEW_OPCODES) + setupOpcodes2(); else - initThingsV5(); + setupOpcodes(); scummInit(); +#if !defined(FULL_THROTTLE) _vars[VAR_VERSION] = 21; +#endif _vars[VAR_DEBUGMODE] = _debugMode; if (_gameId==GID_MONKEY) { @@ -259,7 +247,7 @@ int Scumm::scummLoop(int delta) { processKbd(); - _vars[VAR_CAMERA_CUR_POS] = camera._curPos; + _vars[VAR_CAMERA_POS_X] = camera._curPos; _vars[VAR_HAVE_MSG] = _haveMsg; _vars[VAR_VIRT_MOUSE_X] = _virtual_mouse_x; _vars[VAR_VIRT_MOUSE_Y] = _virtual_mouse_y; @@ -318,11 +306,11 @@ int Scumm::scummLoop(int delta) { setActorRedrawFlags(); resetActorBgs(); - if (!(_vars[VAR_V5_DRAWFLAGS]&2) && _vars[VAR_V5_DRAWFLAGS]&4) { - error("Flashlight not implemented in this version"); - } +// if (!(_vars[VAR_V5_DRAWFLAGS]&2) && _vars[VAR_V5_DRAWFLAGS]&4) { +// error("Flashlight not implemented in this version"); +// } - processActors(); /* process actors makes the heap invalid */ + processActors(); clear_fullRedraw(); cyclePalette(); palManipulate(); @@ -343,7 +331,7 @@ int Scumm::scummLoop(int delta) { drawDirtyScreenParts(); removeEnqueuedObjects(); - if (_majorScummVersion==5) + if (!(_features&GF_AFTER_V6)) playActorSounds(); processSoundQues(); @@ -359,17 +347,6 @@ int Scumm::scummLoop(int delta) { } -#if 0 -void Scumm::scummMain(int argc, char **argv) { - - do { - updateScreen(this); - - - } while (1); -} -#endif - void Scumm::parseCommandLine(int argc, char **argv) { int i; char *s; @@ -415,17 +392,28 @@ struct VersionSettings { const char *filename; const char *gamename; byte id,major,middle,minor; + uint32 features; }; static const VersionSettings version_settings[] = { - {"monkey", "Monkey Island 1", GID_MONKEY, 5, 2, 2}, - {"monkey2", "Monkey Island 2: LeChuck's revenge", GID_MONKEY2, 5, 2, 2}, - {"atlantis", "Indiana Jones 4 and the Fate of Atlantis", GID_INDY4, 5, 5, 0}, - {"playfate", "Indiana Jones 4 and the Fate of Atlantis (Demo)", GID_INDY4, 5, 5, 0}, - {"tentacle", "Day Of The Tentacle", GID_TENTACLE, 6, 4, 2}, - {"dottdemo", "Day Of The Tentacle (Demo)", GID_TENTACLE, 6, 3, 2}, - {"samnmax", "Sam & Max", GID_SAMNMAX, 6, 4, 2}, - {"snmdemo", "Sam & Max (Demo)", GID_SAMNMAX, 6, 3, 0}, + {"monkey", "Monkey Island 1", GID_MONKEY, 5, 2, 2, + GF_USE_KEY}, + {"monkey2", "Monkey Island 2: LeChuck's revenge", GID_MONKEY2, 5, 2, 2, + GF_USE_KEY}, + {"atlantis", "Indiana Jones 4 and the Fate of Atlantis", GID_INDY4, 5, 5, 0, + GF_USE_KEY}, + {"playfate", "Indiana Jones 4 and the Fate of Atlantis (Demo)", GID_INDY4, 5, 5, 0, + GF_USE_KEY}, + {"tentacle", "Day Of The Tentacle", GID_TENTACLE, 6, 4, 2, + GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY}, + {"dottdemo", "Day Of The Tentacle (Demo)", GID_TENTACLE, 6, 3, 2, + GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY}, + {"samnmax", "Sam & Max", GID_SAMNMAX, 6, 4, 2, + GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY}, + {"snmdemo", "Sam & Max (Demo)", GID_SAMNMAX, 6, 3, 0, + GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY}, + {"ft", "Full Throttle", GID_SAMNMAX, 7, 3, 0, + GF_NEW_OPCODES|GF_AFTER_V6|GF_AFTER_V7}, {NULL,NULL} }; @@ -437,9 +425,10 @@ bool Scumm::detectGame() { do { if (!scumm_stricmp(_exe_name, gnl->filename)) { _gameId = gnl->id; - _majorScummVersion = gnl->major; - _middleScummVersion = gnl->middle; - _minorScummVersion = gnl->minor; +// _majorScummVersion = gnl->major; +// _middleScummVersion = gnl->middle; +// _minorScummVersion = gnl->minor; + _features = gnl->features; _gameText = gnl->gamename; debug(1, "Detected game '%s', version %d.%d.%d", gnl->gamename, gnl->major, gnl->middle, gnl->minor); @@ -535,7 +524,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) { camera._mode = CM_NORMAL; camera._curPos = camera._destPos = 160; - if (_majorScummVersion==6) { + if (_features&GF_AFTER_V6) { _vars[VAR_V6_SCREEN_WIDTH] = _scrWidthIn8Unit<<3; _vars[VAR_V6_SCREEN_HEIGHT] = _scrHeight; } @@ -543,10 +532,10 @@ void Scumm::startScene(int room, Actor *a, int objectNr) { if (_roomResource == 0) return; - _vars[VAR_CAMERA_MAX] = (_scrWidthIn8Unit<<3) - 160; - _vars[VAR_CAMERA_MIN] = 160; + _vars[VAR_CAMERA_MAX_X] = (_scrWidthIn8Unit<<3) - 160; + _vars[VAR_CAMERA_MIN_X] = 160; - memset(actorDrawBits, 0, sizeof(actorDrawBits)); + memset(gfxUsageBits, 0, sizeof(gfxUsageBits)); if (a) { where = whereIsObject(objectNr); @@ -554,7 +543,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) { error("startScene: Object %d is not in room %d", objectNr, _currentRoom); getObjectXYPos(objectNr); putActor(a, _xPos, _yPos, _currentRoom); - startAnimActor(a, 0x3E, _dir^1); + fixActorDirection(a, _dir + 180); a->moving = 0; } @@ -576,7 +565,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) { void Scumm::initRoomSubBlocks() { int i,offs; byte *ptr; - byte *roomptr; + byte *roomptr,*searchptr; _ENCD_offs = 0; _EXCD_offs = 0; @@ -591,14 +580,14 @@ void Scumm::initRoomSubBlocks() { roomptr = getResourceAddress(rtRoom, _roomResource); - ptr = findResource(MKID('RMHD'), roomptr, 0); + ptr = findResource(MKID('RMHD'), roomptr); _scrWidthIn8Unit = READ_LE_UINT16(&((RoomHeader*)ptr)->width) >> 3; _scrHeight = READ_LE_UINT16(&((RoomHeader*)ptr)->height); - _IM00_offs = findResource(MKID('IM00'), findResource(MKID('RMIM'), roomptr, 0), 0) - - roomptr; + _IM00_offs = findResource(MKID('IM00'), findResource(MKID('RMIM'), roomptr)) + - roomptr; - ptr = findResource(MKID('EXCD'), roomptr, 0); + ptr = findResource(MKID('EXCD'), roomptr); if (ptr) { _EXCD_offs = ptr - roomptr; #ifdef DUMP_SCRIPTS @@ -606,7 +595,7 @@ void Scumm::initRoomSubBlocks() { #endif } - ptr = findResource(MKID('ENCD'), roomptr, 0); + ptr = findResource(MKID('ENCD'), roomptr); if (ptr) { _ENCD_offs = ptr - roomptr; #ifdef DUMP_SCRIPTS @@ -614,25 +603,25 @@ void Scumm::initRoomSubBlocks() { #endif } - ptr = findResource(MKID('BOXD'), roomptr, 0); + ptr = findResource(MKID('BOXD'), roomptr); if (ptr) { int size = READ_BE_UINT32_UNALIGNED(ptr+4); createResource(rtMatrix, 2, size); roomptr = getResourceAddress(rtRoom, _roomResource); - ptr = findResource(MKID('BOXD'), roomptr, 0); + ptr = findResource(MKID('BOXD'), roomptr); memcpy(getResourceAddress(rtMatrix, 2), ptr, size); } - ptr = findResource(MKID('BOXM'), roomptr, 0); + ptr = findResource(MKID('BOXM'), roomptr); if (ptr) { int size = READ_BE_UINT32_UNALIGNED(ptr+4); createResource(rtMatrix, 1, size); roomptr = getResourceAddress(rtRoom, _roomResource); - ptr = findResource(MKID('BOXM'), roomptr, 0); + ptr = findResource(MKID('BOXM'), roomptr); memcpy(getResourceAddress(rtMatrix, 1), ptr, size); } - ptr = findResource(MKID('SCAL'), roomptr, 0); + ptr = findResource(MKID('SCAL'), roomptr); if (ptr) { offs = ptr - roomptr; for (i=1; i<_maxScaleTable; i++, offs+=8) { @@ -646,48 +635,59 @@ void Scumm::initRoomSubBlocks() { } } } - memset(_localScriptList, 0, (0x100 - _numGlobalScripts) * 4); + memset(_localScriptList, 0, sizeof(_localScriptList)); - roomptr = getResourceAddress(rtRoom, _roomResource); - for (i=0; ptr = findResource(MKID('LSCR'), roomptr, i++) ;) { - _localScriptList[ptr[8] - _numGlobalScripts] = ptr - roomptr; + searchptr = roomptr = getResourceAddress(rtRoom, _roomResource); + while( (ptr = findResource(MKID('LSCR'), searchptr)) != NULL ) { + int id; +#ifdef FULL_THROTTLE + id = READ_LE_UINT16(ptr + 8); + checkRange(2050, 2000, id, "Invalid local script %d"); + _localScriptList[id - _numGlobalScripts] = ptr + 10 - roomptr; +#else + id = ptr[8]; + _localScriptList[id - _numGlobalScripts] = ptr + 9 - roomptr; +#endif #ifdef DUMP_SCRIPTS do { char buf[32]; sprintf(buf,"room-%d-",_roomResource); - dumpResource(buf, ptr[8], ptr); + dumpResource(buf, id, ptr); } while (0); #endif + searchptr = NULL; } - ptr = findResource(MKID('EPAL'), roomptr, 0); + ptr = findResource(MKID('EPAL'), roomptr); if (ptr) _EPAL_offs = ptr - roomptr; - ptr = findResource(MKID('CLUT'), roomptr, 0); + ptr = findResource(MKID('CLUT'), roomptr); if (ptr) { _CLUT_offs = ptr - roomptr; setPaletteFromRes(); } - if (_majorScummVersion==6) { - ptr = findResource(MKID('PALS'), roomptr, 0); + if (_features&GF_AFTER_V6) { + ptr = findResource(MKID('PALS'), roomptr); if (ptr) { _PALS_offs = ptr - roomptr; setPalette(0); } } - initCycl(findResource(MKID('CYCL'), roomptr, 0) + 8); + initCycl(findResource(MKID('CYCL'), roomptr) + 8); - ptr = findResource(MKID('TRNS'), roomptr, 0); + ptr = findResource(MKID('TRNS'), roomptr); if (ptr) gdi._transparency = ptr[8]; else gdi._transparency = 255; initBGBuffers(); + + memset(_extraBoxFlags, 0, sizeof(_extraBoxFlags)); } void Scumm::setScaleItem(int slot, int a, int b, int c, int d) { @@ -883,7 +883,9 @@ void Scumm::startManiac() { void Scumm::destroy() { freeResources(); - free(_objectFlagTable); + free(_objectStateTable); + free(_objectRoomTable); + free(_objectOwnerTable); free(_inventory); free(_arrays); free(_verbs); @@ -894,6 +896,45 @@ void Scumm::destroy() { free(_classData); } +int Scumm::newDirToOldDir(int dir) { + if (dir>=71 && dir<=109) + return 1; + if (dir>=109 && dir<=251) + return 2; + if (dir>=251 && dir<=289) + return 0; + return 3; +} + +const int new_dir_table[4] = { + 270, + 90, + 180, + 0, +}; + +int Scumm::oldDirToNewDir(int dir) { + return new_dir_table[dir]; +} + +int Scumm::toSimpleDir(int dir) { + if (dir>=71 && dir<=109) + return 1; + if (dir>=109 && dir<=251) + return 2; + if (dir>=251 && dir<=289) + return 3; + return 0; +} + +int Scumm::fromSimpleDir(int dir) { + return dir * 90; +} + + +int Scumm::normalizeAngle(int angle) { + return (angle+360)%360; +} extern Scumm scumm; diff --git a/scummvm.dsp b/scummvm.dsp index 8b0963385e4..4049781556b 100644 --- a/scummvm.dsp +++ b/scummvm.dsp @@ -66,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "ALLOW_GDI" /Yu"stdafx.h" /FD /GZ /c # SUBTRACT CPP /Fr # ADD BASE RSC /l 0x41d /d "_DEBUG" # ADD RSC /l 0x41d /d "_DEBUG" @@ -101,6 +101,10 @@ SOURCE=.\actor.cpp # End Source File # Begin Source File +SOURCE=.\akos.cpp +# End Source File +# Begin Source File + SOURCE=.\boxes.cpp !IF "$(CFG)" == "scummvm - Win32 Release" @@ -115,15 +119,6 @@ SOURCE=.\boxes.cpp # Begin Source File SOURCE=.\costume.cpp - -!IF "$(CFG)" == "scummvm - Win32 Release" - -# ADD CPP /Gd - -!ELSEIF "$(CFG)" == "scummvm - Win32 Debug" - -!ENDIF - # End Source File # Begin Source File @@ -252,10 +247,6 @@ SOURCE=.\scummvm.cpp # End Source File # Begin Source File -SOURCE=.\sdl.cpp -# End Source File -# Begin Source File - SOURCE=.\sound.cpp !IF "$(CFG)" == "scummvm - Win32 Release" @@ -320,6 +311,10 @@ SOURCE=.\verbs.cpp !ENDIF +# End Source File +# Begin Source File + +SOURCE=.\windows.cpp # End Source File # End Group # Begin Group "Header Files" diff --git a/sound.cpp b/sound.cpp index 4c2cf92564b..533c275b44e 100644 --- a/sound.cpp +++ b/sound.cpp @@ -24,9 +24,11 @@ #include "sound.h" void Scumm::addSoundToQueue(int sound) { +#if !defined(FULL_THROTTLE) _vars[VAR_LAST_SOUND] = sound; ensureResourceLoaded(rtSound, sound); addSoundToQueue2(sound); +#endif } void Scumm::addSoundToQueue2(int sound) { @@ -77,8 +79,10 @@ void Scumm::processSoundQues() { data[7] ); #endif +#if !defined(FULL_THROTTLE) if (se) _vars[VAR_SOUNDRESULT] = se->do_command(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]); +#endif } } _soundQuePos = 0; @@ -114,7 +118,7 @@ void Scumm::processSfxQueues() { b = isMouthSyncOff(_curSoundPos); if (_mouthSyncMode != b) { _mouthSyncMode = b; - startAnimActor(a, b ? a->talkFrame2 : a->talkFrame1, a->facing); + startAnimActor(a, b ? a->talkFrame2 : a->talkFrame1); } } } @@ -134,6 +138,8 @@ void Scumm::startTalkSound(uint32 offset, uint32 b, int mode) { byte file_byte,file_byte_2; uint16 elem; + return; + if (!_sfxFile) { warning("startTalkSound: SFX file is not open"); return; diff --git a/string.cpp b/string.cpp index b93cba2d8d6..e6a223ac943 100644 --- a/string.cpp +++ b/string.cpp @@ -186,7 +186,7 @@ void Scumm::CHARSET_1() { a = derefActorSafe(_vars[VAR_TALK_ACTOR], "CHARSET_1"); if (a && string[0].overhead!=0) { - if (_majorScummVersion==5) { + if (!(_features & GF_AFTER_V6)) { string[0].xpos = a->x - camera._curPos + 160; if (_vars[VAR_V5_TALK_STRING_Y] < 0) { @@ -250,7 +250,7 @@ void Scumm::CHARSET_1() { } if (a && !string[0].no_talk_anim) { - startAnimActor(a, a->talkFrame1, a->facing); + startAnimActor(a, a->talkFrame1); _useTalkAnims = true; } @@ -306,7 +306,7 @@ newLine:; charset._left = charset._xpos2; charset._top = charset._ypos2; - if (_majorScummVersion==5) { + if (!(_features&GF_AFTER_V6)) { if (!_vars[VAR_V5_CHARFLAG]) { charset.printChar(c); } @@ -336,7 +336,7 @@ newLine:; frme = *buffer++; frme |= *buffer++<<8; if (a) - startAnimActor(a, frme, a->facing); + startAnimActor(a, frme); } else if (c==10) { uint32 a,b; @@ -456,7 +456,7 @@ void Scumm::drawString(int a) { break; } } else { - if (a==1 && _majorScummVersion==6) + if (a==1 && (_features&GF_AFTER_V6)) charset._blitAlso = true; charset.printChar(chr); charset._blitAlso = false; @@ -603,7 +603,7 @@ void Scumm::unkAddMsgToStack4(int var) { void Scumm::unkAddMsgToStack5(int var) { byte *ptr; - if (_majorScummVersion==6) + if (_features&GF_AFTER_V6) var = readVar(var); if (var) { diff --git a/verbs.cpp b/verbs.cpp index 72f530804b1..e921346c1b4 100644 --- a/verbs.cpp +++ b/verbs.cpp @@ -185,12 +185,12 @@ void Scumm::drawVerbBitmap(int vrb, int x, int y) { obim = getResourceAddress(rtVerb, vrb); - IMHD_ptr = findResource(MKID('IMHD'), obim, 0); + IMHD_ptr = findResource(MKID('IMHD'), obim); imgw = READ_LE_UINT16(IMHD_ptr+0x14) >> 3; imgh = READ_LE_UINT16(IMHD_ptr+0x16) >> 3; - imptr = findResource(MKID('IM01'), obim, 0); + imptr = findResource(MKID('IM01'), obim); if (!imptr) error("No image for verb %d", vrb); @@ -243,39 +243,16 @@ void Scumm::killVerb(int slot) { } void Scumm::setVerbObject(uint room, uint object, uint verb) { - int numobj, i; byte *obimptr; - uint32 imoffs,size; - byte *roomptr; - ImageHeader *imhd; - RoomHeader *roomhdr; + uint32 size; + FindObjectInRoom foir; if (whereIsObject(object) == WIO_FLOBJECT) error("Can't grab verb image from flobject"); - ensureResourceLoaded(rtRoom,room); - roomptr = getResourceAddress(rtRoom, room); - roomhdr = (RoomHeader*)findResource(MKID('RMHD'), roomptr, 0); - - numobj = READ_LE_UINT16(&roomhdr->numObjects); - if (numobj==0) - error("No images found in room %d", room); - if (numobj > _numLocalObjects) - error("More (%d) than %d objects in room %d", numobj, _numLocalObjects, room); - - for (i=0; iobj_id) == object) { - imoffs = obimptr - roomptr; - size = READ_BE_UINT32_UNALIGNED(obimptr+4); - createResource(rtVerb, verb, size); - obimptr = getResourceAddress(rtRoom, room) + imoffs; - memcpy(getResourceAddress(rtVerb, verb), obimptr, size); - return; - } - } - error("Image %d not found in room %d", object, room); + findObjectInRoom(&foir, foImageHeader, object, room); + size = READ_BE_UINT32_UNALIGNED(foir.obim+4); + createResource(rtVerb, verb, size); + obimptr = getResourceAddress(rtRoom, room) - foir.roomptr + foir.obim; + memcpy(getResourceAddress(rtVerb, verb), obimptr, size); } diff --git a/windows.cpp b/windows.cpp index 07330d89164..09070dd25fa 100644 --- a/windows.cpp +++ b/windows.cpp @@ -769,12 +769,12 @@ void outputdisplay2(Scumm *s, int disp) { case 0: wm->_vgabuf = buf; memcpy(buf, wm->_vgabuf, 64000); - memcpy(buf+320*144,s->getResourceAddress(rtBuffer, 7),320*56); + memcpy(buf,s->getResourceAddress(rtBuffer, 5),320*144); break; case 1: wm->_vgabuf = buf; memcpy(buf, wm->_vgabuf, 64000); - memcpy(buf+320*144,s->getResourceAddress(rtBuffer, 3),320*56); + memcpy(buf,s->getResourceAddress(rtBuffer, 1),320*144); break; case 2: wm->_vgabuf = NULL; @@ -782,15 +782,15 @@ void outputdisplay2(Scumm *s, int disp) { break; case 3: wm->_vgabuf = NULL; - decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+5920+s->_screenStartStrip); + decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160+s->_screenStartStrip); break; case 4: wm->_vgabuf = NULL; - decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+5920*2+s->_screenStartStrip); + decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160*2+s->_screenStartStrip); break; case 5: wm->_vgabuf = NULL; - decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+5920*3+s->_screenStartStrip); + decompressMask(wm->dib.buf, s->getResourceAddress(rtBuffer, 9)+8160*3+s->_screenStartStrip); break; } wm->writeToScreen(); @@ -828,6 +828,8 @@ void waitForTimer(Scumm *s, int delay) { wm->handleMessage(); if (!veryFastMode) { assert(delay<5000); + if (s->_fastMode) + delay=10; Sleep(delay); } } @@ -870,8 +872,8 @@ void WndMan::sound_init() { wfx.wBitsPerSample = BITS_PER_SAMPLE; wfx.nBlockAlign = BITS_PER_SAMPLE * 1 / 8; - CreateThread(NULL, 0, (unsigned long (__stdcall *)(void *))&sound_thread, this, 0, &_threadId); - SetThreadPriority((void*)_threadId, THREAD_PRIORITY_HIGHEST); +// CreateThread(NULL, 0, (unsigned long (__stdcall *)(void *))&sound_thread, this, 0, &_threadId); +// SetThreadPriority((void*)_threadId, THREAD_PRIORITY_HIGHEST); _event = CreateEvent(NULL, false, false, NULL); @@ -888,6 +890,8 @@ DWORD _stdcall WndMan::sound_thread(WndMan *wm) { bool signaled; int time = GetTickCount(), cur; + return 0; + while (1) { cur = GetTickCount(); while (time < cur) { @@ -913,7 +917,6 @@ DWORD _stdcall WndMan::sound_thread(WndMan *wm) { #undef main int main(int argc, char* argv[]) { int delta; - int tmp; wm->init(); wm->sound_init(); @@ -931,18 +934,13 @@ int main(int argc, char* argv[]) { do { updateScreen(&scumm); - waitForTimer(&scumm, tmp*10); + waitForTimer(&scumm, delta*15); if (gui._active) { gui.loop(); - tmp = 5; + delta = 3; } else { - tmp = delta = scumm.scummLoop(delta); - - tmp += tmp>>1; - - if (scumm._fastMode) - tmp=1; + delta = scumm.scummLoop(delta); } } while(1);