aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--actor.cpp599
-rw-r--r--akos.cpp1040
-rw-r--r--boxes.cpp498
-rw-r--r--costume.cpp112
-rw-r--r--debug.cpp2
-rw-r--r--gfx.cpp158
-rw-r--r--gui.cpp8
-rw-r--r--object.cpp490
-rw-r--r--resource.cpp323
-rw-r--r--saveload.cpp53
-rw-r--r--script.cpp181
-rw-r--r--script_v1.cpp63
-rw-r--r--script_v2.cpp282
-rw-r--r--scumm.h498
-rw-r--r--scummvm.cpp225
-rw-r--r--scummvm.dsp23
-rw-r--r--sound.cpp8
-rw-r--r--string.cpp12
-rw-r--r--verbs.cpp41
-rw-r--r--windows.cpp30
20 files changed, 3338 insertions, 1308 deletions
diff --git a/actor.cpp b/actor.cpp
index 6f6d75897e..1306db5f43 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::actorWalkStep(Actor *a) {
- int32 XYFactor, YXFactor;
- int actorX, actorY, newx, newy;
- int newXDist;
- int32 tmp,tmp2;
-
- byte direction;
-
- a->needRedraw = true;
- a->needBgReset = true;
+int Scumm::remapDirection(Actor *a, int dir) {
+ int specdir;
+ byte flags;
- XYFactor = a->walkdata.XYFactor;
- YXFactor = a->walkdata.YXFactor;
+ if (!a->ignoreBoxes) {
+ specdir = _extraBoxFlags[a->walkbox];
+ if (specdir) {
+ if (specdir & 0x8000) {
+ dir = specdir & 0x3FFF;
+ } else {
+ error("getProgrDirChange: special dir not implemented");
+ }
+ }
- direction = XYFactor>0 ? 1 : 0;
- if (abs(YXFactor) * 2 > abs(XYFactor))
- direction = YXFactor>0 ? 2 : 3;
- a->newDirection = direction;
+ flags = getBoxFlags(a->walkbox);
- direction = getProgrDirChange(a, 1);
+ if ((flags&8) || getClass(a->number, 0x1E)) {
+ dir = 360 - dir;
+ }
- if (!(a->moving&2) || a->facing!=direction) {
- if (a->walkFrame != a->animIndex || a->facing != direction) {
- startAnimActor(a, a->walkFrame, direction);
+ if ((flags&0x10) || getClass(a->number, 0x1D)) {
+ dir = 180 - dir;
}
- 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);
+
+ 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);
+}
- newXDist = abs(newx - actorX);
-
- if (newXDist <= abs(a->x - actorX) &&
- abs(newy - actorY) <= abs(a->y - actorY) ){
- a->moving&=~2;
- return 0;
+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--;
}
- XYFactor = (XYFactor>>8) * a->scalex;
- YXFactor = (YXFactor>>8) * a->scalex;
-
- tmp = ((a->x + 8000)<<16) + a->walkdata.xfrac + XYFactor;
- tmp2 = (a->y<<16) + a->walkdata.yfrac + YXFactor;
+ return fromSimpleDir(from&3);
+}
- a->x = (tmp>>16)-8000;
- a->y = tmp2>>16;
+void Scumm::setActorBox(Actor *a, int box) {
+ a->walkbox = box;
+ a->mask = getMaskFromBox(box);
+ setupActorScale(a);
+}
- if (abs(a->x - actorX) > newXDist) {
- a->x = newx;
+
+int Scumm::actorWalkStep(Actor *a) {
+ int tmpX, tmpY;
+ int actorX, actorY;
+ int distX, distY;
+ int direction;
+
+ a->needRedraw = true;
+ a->needBgReset = true;
+
+ 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;
}
- if (abs(a->y - actorY) > abs(newy - actorY)) {
- a->y = newy;
+ actorX = a->x;
+ actorY = a->y;
+
+ if (a->walkbox != a->walkdata.curbox &&
+ checkXYInBoxBounds(a->walkdata.curbox, actorX, actorY)) {
+ setActorBox(a, a->walkdata.curbox);
}
- a->walkdata.xfrac = tmp&0xFFFF;
- a->walkdata.yfrac = tmp2&0xFFFF;
+ distX = abs(a->walkdata.newx - a->walkdata.x);
+ distY = abs(a->walkdata.newy - a->walkdata.y);
- if (a->x == newx &&
- a->y == newy) {
- a->moving&=~2;
+ if (
+ abs(actorX - a->walkdata.x) >= distX &&
+ abs(actorY - a->walkdata.y) >= distY
+ ) {
+ a->moving &= ~MF_IN_LEG;
return 0;
}
+ 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);
+
+ if (abs(actorX - a->walkdata.x) > distX) {
+ actorX = a->walkdata.newx;
+ }
+
+ 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;
- mask = 0x8000;
- for (i=0; i<16; i++,mask>>=1) {
- vald = a->cost.d[i];
- if (vald==0xFFFF || (vald&3)==direction)
- continue;
- decodeCostData(a, (vald&0xFC)|direction, mask);
- }
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])
+ if (a->costume==0)
return;
- r = p + READ_LE_UINT16(p + frame*2 + cost._numColors + 42);
- if (r==p)
- return;
+#if !defined(FULL_THROTTLE)
+ cost.loadCostume(a->costume);
+#endif
- dataptr = p + READ_LE_UINT16(p + cost._numColors + 8);
+ mask = 0x8000;
+ for (i=0; i<16; i++,mask>>=1) {
+ vald = a->cost.frame[i];
+ if (vald==0xFFFF)
+ continue;
+#if !defined(FULL_THROTTLE)
+ decodeCostData(a, vald, mask);
+#else
+ akos_decodeData(a, vald, mask);
+#endif
+ }
- 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<<i);
- } else if (cmd==0x79) {
- a->cost.hdr |= (1<<i);
- } else {
- a->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);
+ setActorBox(a, a->walkdata.curbox);
+ a->moving &= 2;
+ }
- setupActorScale(a);
- a->moving = (a->moving&2)|1;
+#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; j<NUM_ACTORS; j++) {
- if ((bits&(1<<j)) && bits!=(1<<j)) {
+ if ((bits&(1<<j)) && bits!=(uint32)(1<<j)) {
Actor *a = derefActor(j);
a->needRedraw = 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; i<NUM_ACTORS; i++) {
Actor *a = derefActor(i);
@@ -865,7 +945,7 @@ void Scumm::actorTalk() {
stopTalk();
_vars[VAR_TALK_ACTOR] = a->number;
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 0000000000..8d429f143a
--- /dev/null
+++ b/akos.cpp
@@ -0,0 +1,1040 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+#include "stdafx.h"
+#include "scumm.h"
+
+#if defined(FULL_THROTTLE)
+
+bool Scumm::akos_hasManyDirections(Actor *a) {
+ byte *akos;
+ AkosHeader *akhd;
+
+ akos = getResourceAddress(rtCostume, a->costume);
+ assert(akos);
+ akhd = (AkosHeader*)findResource(MKID('AKHD'), akos);
+ return (akhd->flags&2) != 0;
+}
+
+
+int Scumm::akos_frameToAnim(Actor *a, int frame) {
+ if (akos_hasManyDirections(a)) {
+ error("akos_frameToAnim: hasManyDirections not supported");
+ } else {
+ return newDirToOldDir(a->facing) + frame * 4;
+ }
+}
+
+void Scumm::akos_decodeData(Actor *a, int frame, uint usemask) {
+ uint anim;
+ byte *akos,*r;
+ AkosHeader *akhd;
+ uint offs;
+ int i;
+ byte code;
+ uint32 start,len;
+ uint16 mask;
+
+ if (a->costume==0)
+ return;
+
+ anim = akos_frameToAnim(a, frame);
+
+ akos = getResourceAddress(rtCostume, a->costume);
+ assert(akos);
+
+ akhd = (AkosHeader*)findResource(MKID('AKHD'), akos);
+
+ if (anim>=READ_LE_UINT16(&akhd->num_anims))
+ return;
+
+ r = findResourceData(MKID('AKCH'), akos);
+ assert(r);
+
+ offs = READ_LE_UINT16(r + anim * sizeof(uint16));
+ if (offs==0)
+ return;
+ r += offs;
+
+ i = 0;
+ mask = READ_LE_UINT16(r);
+ r+=sizeof(uint16);
+ do {
+ if (mask&0x8000) {
+ code = *r++;
+ if (usemask&0x8000) {
+ switch(code) {
+ case 1:
+ a->cost.active[i] = 0;
+ a->cost.frame[i] = frame;
+ a->cost.end[i] = 0;
+ a->cost.start[i] = 0;
+ a->cost.curpos[i] = 0;
+ break;
+ case 4:
+ a->cost.stopped |= 1<<i;
+ break;
+ case 5:
+ a->cost.stopped &= ~(1<<i);
+ break;
+ default:
+ start = READ_LE_UINT16(r);
+ len = READ_LE_UINT16(r+sizeof(uint16));
+ r+=sizeof(uint16)*2;
+
+ a->cost.active[i] = code;
+ a->cost.frame[i] = frame;
+ a->cost.end[i] = start + len;
+ a->cost.start[i] = start;
+ a->cost.curpos[i] = start;
+ break;
+ }
+ } else {
+ if (code!=1 && code!=4 && code!=5)
+ r+=sizeof(uint16)*2;
+ }
+ }
+ i++;
+ mask<<=1;
+ usemask<<=1;
+ } while ((uint16)mask);
+}
+
+void Scumm::akos_setPalette(AkosRenderer *ar, byte *palette) {
+ byte *akos, *akpl;
+ uint size, i;
+
+ akpl = findResource(MKID('AKPL'), ar->akos);
+ size = READ_BE_UINT32(akpl+4) - 8;
+ akpl += 8;
+
+ if (size > 256)
+ error("akos_setPalette: %d is too many colors", size);
+
+ for(i=0; i<size; i++) {
+ ar->palette[i] = palette[i]!=0xFF ? palette[i] : akpl[i];
+ }
+}
+
+void Scumm::akos_setCostume(AkosRenderer *ar, int costume) {
+ ar->akos = getResourceAddress(rtCostume, costume);
+ assert(ar->akos);
+
+ ar->akhd = (AkosHeader*)findResource(MKID('AKHD'), ar->akos);
+ ar->akof = (AkosOffset*)(findResource(MKID('AKOF'), ar->akos)+8);
+ ar->akci = (findResource(MKID('AKCI'), ar->akos)+8);
+ ar->aksq = (findResource(MKID('AKSQ'), ar->akos)+8);
+ ar->akcd = (findResource(MKID('AKCD'), ar->akos)+8);
+ ar->akpl = (findResource(MKID('AKPL'), ar->akos)+8);
+ ar->codec = READ_LE_UINT16(&ar->akhd->codec);
+}
+
+void Scumm::akos_setFacing(AkosRenderer *ar, Actor *a) {
+ ar->mirror = (newDirToOldDir(a->facing)!=0 || ar->akhd->flags&1);
+ if (a->flip)
+ ar->mirror ^= 1;
+}
+
+bool Scumm::akos_drawCostume(AkosRenderer *ar) {
+ int i;
+ bool result = false;
+
+ ar->move_x = ar->move_y = 0;
+ for(i=0; i<16; i++)
+ result |= akos_drawCostumeChannel(ar, i);
+ return result;
+}
+
+bool Scumm::akos_drawCostumeChannel(AkosRenderer *ar, int chan) {
+ uint code;
+ byte *p;
+ AkosOffset *off;
+ AkosCI *akci;
+ uint i,extra;
+
+ if (!ar->cd->active[chan] || ar->cd->stopped&(1<<chan))
+ return false;
+
+ p = ar->aksq + ar->cd->curpos[chan];
+
+ code = p[0];
+ if (code & 0x80) code = (code<<8)|p[1];
+
+ if (code==AKC_Return)
+ return false;
+
+ if (code!=AKC_ComplexChan) {
+ off = ar->akof + (code & 0xFFF);
+
+ assert( (code & 0xFFF)*6 < READ_BE_UINT32((byte*)ar->akof - 4)-8 );
+
+ assert( (code&0x7000) == 0);
+
+ ar->srcptr = ar->akcd + READ_LE_UINT32(&off->akcd);
+ akci = (AkosCI*)ar->akci + READ_LE_UINT16(&off->akci);
+
+ ar->move_x_cur = ar->move_x + (int16)READ_LE_UINT16(&akci->rel_x);
+ ar->move_y_cur = ar->move_y + (int16)READ_LE_UINT16(&akci->rel_y);
+ ar->width = READ_LE_UINT16(&akci->width);
+ ar->height = READ_LE_UINT16(&akci->height);
+ ar->move_x += (int16)READ_LE_UINT16(&akci->move_x);
+ ar->move_y -= (int16)READ_LE_UINT16(&akci->move_y);
+
+ switch(ar->codec) {
+ case 1:
+ akos_codec1(ar);
+ break;
+ case 5:
+ akos_codec5(ar);
+ break;
+ case 16:
+ akos_codec16(ar);
+ break;
+ default:
+ error("akos_drawCostumeChannel: invalid codec %d", ar->codec);
+ }
+ } else {
+ extra = p[2];
+ p+=3;
+
+ for(i=0; i!=extra; i++) {
+ code = p[4];
+ if (code&0x80) code = ((code&0xF)<<8)|p[5];
+ off = ar->akof + code;
+
+ ar->srcptr = ar->akcd + READ_LE_UINT32(&off->akcd);
+ akci = (AkosCI*)(ar->akci + READ_LE_UINT16(&off->akci));
+
+ ar->move_x_cur = ar->move_x + (int16)READ_LE_UINT16(p+0);
+ ar->move_y_cur = ar->move_y + (int16)READ_LE_UINT16(p+2);
+
+ p += (p[4]&0x80) ? 6 : 5;
+
+ ar->width = READ_LE_UINT16(&akci->width);
+ ar->height = READ_LE_UINT16(&akci->height);
+
+ switch(ar->codec) {
+ case 1:
+ akos_codec1(ar);
+ break;
+ case 5:
+ akos_codec5(ar);
+ break;
+ case 16:
+ akos_codec16(ar);
+ break;
+ default:
+ error("akos_drawCostumeChannel: invalid codec %d", ar->codec);
+ }
+ }
+ }
+
+ return true;
+}
+
+void akos_c1_0y_decode(AkosRenderer *ar) {
+ byte len,color;
+ byte *src, *dst;
+ int height;
+ uint y;
+ uint scrheight;
+
+ len = ar->v1.replen;
+ src = ar->srcptr;
+ dst = ar->v1.destptr;
+ color = ar->v1.repcolor;
+ scrheight = ar->outheight;
+ height = ar->height;
+ y = ar->v1.y;
+
+ if (ar->v1.doContinue) goto StartPos;
+
+ do {
+ len = *src++;
+ color = len>>ar->v1.shl;
+ len &= ar->v1.mask;
+ if (!len) len = *src++;
+
+ do {
+ if (color && y < scrheight) {
+ *dst = ar->palette[color];
+ }
+
+ dst += ar->outwidth;
+ y++;
+ if (!--height) {
+ if (!--ar->v1.skip_width)
+ return;
+ dst -= ar->v1.y_pitch;
+ height = ar->height;
+ y = ar->v1.y;
+ }
+StartPos:;
+ } while (--len);
+ } while (1);
+}
+
+#if 0
+void akos_c1_spec1(AkosRenderer *ar) {
+ byte *mask,*src,*dst,*dstorg;
+ byte maskbit,len,height,pcolor,width;
+ uint y;
+ int color;
+ int t;
+
+ mask = _mask_ptr = ar->v1.mask_ptr_dest;
+ maskbit = revBitMask[ar_xpos&7];
+ y = _ypos;
+
+ dstorg = dst = _backbuff_ptr;
+ height = _height2;
+ width = _width2;
+ len = _replen;
+ color = _repcolor;
+ src = _srcptr;
+
+ if (_docontinue) goto StartPos;
+
+ do {
+ len = *src++;
+ color = len>>_shrval;
+ len &= _maskval;
+ if (!len) len = *src++;
+
+ do {
+ if (cost_scaleTable[_scaleIndexY++] < _scaleY) {
+ if (color && y < _vscreenheight) {
+ pcolor = _palette[color];
+ if (pcolor==13)
+ pcolor = _transEffect[*dst];
+ *dst = pcolor;
+ }
+ dst += 320;
+ y++;
+ }
+ if (!--height) {
+ if(!--width)
+ return;
+ height = _height;
+ y = _ypostop;
+ _scaleIndexY = _scaleIndexYTop;
+ t = _scaleIndexX;
+ _scaleIndexX = t + _scaleIndexXStep;
+ if (cost_scaleTable[t] < _scaleX) {
+ _xpos += _scaleIndexXStep;
+ if (_xpos >= 320)
+ return;
+ _backbuff_ptr += _scaleIndexXStep;
+ }
+ dst = _backbuff_ptr;
+ }
+StartPos:;
+ } while (--len);
+ } while(1);
+}
+#endif
+
+const byte default_scale_table[768] = {
+0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFE,
+0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFE,
+0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF,
+};
+
+
+void Scumm::akos_codec1(AkosRenderer *ar) {
+ int num_colors;
+ bool use_scaling;
+ int i,j;
+ int x,x_right,x_left,skip,tmp_x,tmp_y;
+ int y,y_top,y_bottom;
+ byte *stab;
+ bool y_clipping;
+ bool charsetmask;
+ bool masking;
+ int step;
+
+ /* implement custom scale table */
+ ar->v1.scaletable = default_scale_table;
+
+ /* Setup color decoding variables */
+ num_colors = READ_BE_UINT32(ar->akpl-4)-8;
+ if (num_colors == 32) {
+ ar->v1.mask = (1<<3)-1;
+ ar->v1.shl = 3;
+ } else if (num_colors == 64) {
+ ar->v1.mask = (1<<2)-1;
+ ar->v1.shl = 2;
+ } else {
+ ar->v1.mask = (1<<4)-1;
+ ar->v1.shl = 4;
+ }
+
+ use_scaling = (ar->scale_x!=0xFF) || (ar->scale_y!=0xFF);
+
+ use_scaling = false;
+
+ x = ar->x;
+ y = ar->y;
+
+ if (use_scaling) {
+
+ /* Scale direction */
+ ar->v1.scaleXstep = -1;
+ if (ar->move_x_cur < 0) {
+ ar->move_x_cur = -ar->move_x_cur;
+ ar->v1.scaleXstep = 1;
+ }
+
+ if (ar->mirror) {
+ /* Adjust X position */
+ tmp_x = 0x180 - ar->move_x_cur;
+ j = tmp_x;
+ for(i=0; i<ar->move_x_cur; i++) {
+ if (ar->v1.scaletable[j++] < ar->scale_x)
+ x -= ar->v1.scaleXstep;
+ }
+
+ x_left = x_right = x;
+
+ j = tmp_x;
+ for(i=0,skip=0; i<ar->width; i++) {
+ if (x_right < 0) {
+ skip++;
+ tmp_x = j;
+ }
+ if (ar->v1.scaletable[j++] < ar->scale_x)
+ x_right++;
+ }
+ } else {
+ /* No mirror */
+ /* Adjust X position */
+ tmp_x = 0x180 + ar->move_x_cur;
+ j = tmp_x;
+ for(i=0; i<ar->move_x_cur; i++) {
+ if (ar->v1.scaletable[j++] < ar->scale_x)
+ x += ar->v1.scaleXstep;
+ }
+
+ x_left = x_right = x;
+
+ j = tmp_x;
+ for(i=0,skip=0; i<ar->width; i++) {
+ if (x_left >= ar->outwidth) {
+ tmp_x = j;
+ skip++;
+
+ }
+ if (ar->v1.scaletable[j--] < ar->scale_x)
+ x_left--;
+ }
+ }
+
+ if (skip) skip--;
+
+ step = -1;
+ if (ar->move_y_cur < 0) {
+ ar->move_y_cur = -ar->move_y_cur;
+ step = -step;
+ }
+
+ tmp_y = 0x180 - ar->move_y_cur;
+ for(i=0; i<ar->move_y_cur; i++) {
+ if (ar->v1.scaletable[tmp_y++] < ar->scale_y)
+ y -= step;
+ }
+
+ y_top = y_bottom = y;
+ tmp_y = 0x180 - ar->move_y_cur;
+ for(i=0; i<ar->height; i++) {
+ if (ar->v1.scaletable[tmp_y++] < ar->scale_y)
+ y_bottom++;
+ }
+
+ tmp_y = 0x180 - ar->move_y_cur;
+ } else {
+ if (!ar->mirror)
+ ar->move_x_cur = -ar->move_x_cur;
+
+ x += ar->move_x_cur;
+ y += ar->move_y_cur;
+
+ if (ar->mirror) {
+ x_left = x;
+ x_right = x + ar->width;
+ } else {
+ x_right = x;
+ x_left = x - ar->width;
+ }
+
+ y_top = y;
+ y_bottom = y + ar->height;
+
+ tmp_x = 0x180;
+ tmp_y = 0x180;
+ }
+
+ ar->v1.tmp_x = tmp_x;
+ ar->v1.tmp_y = tmp_y;
+ ar->v1.skip_width = ar->width;
+
+ ar->v1.scaleXstep = -1;
+ if (ar->mirror)
+ ar->v1.scaleXstep = -ar->v1.scaleXstep;
+
+ if ((uint)y_top >= (uint)ar->outheight || y_bottom <= 0)
+ return;
+
+ if ((uint)x_left >= (uint)ar->outwidth || x_right <= 0)
+ return;
+
+ updateDirtyRect(0, x_left, x_right, y_top, y_bottom, 1<<ar->dirty_id);
+
+ ar->v1.doContinue = false;
+
+ ar->v1.y_pitch = ar->height * ar->outwidth;
+
+ if (ar->mirror) {
+ ar->v1.y_pitch--;
+ if (!use_scaling)
+ skip = -x;
+ if (skip > 0) {
+ ar->v1.skip_width -= skip;
+ akos_codec1_ignorePakCols(ar, skip);
+ x = 0;
+ ar->v1.doContinue = true;
+ } else {
+ skip = x_right - ar->outwidth;
+ if (skip > 0)
+ ar->v1.skip_width -= skip;
+ }
+ } else {
+ ar->v1.y_pitch++;
+ if (!use_scaling) {
+ skip = x_right - ar->outwidth + 1;
+ }
+ if (skip > 0) {
+ ar->v1.skip_width -= skip;
+ akos_codec1_ignorePakCols(ar, skip);
+ x = ar->outwidth - 1;
+ ar->v1.doContinue = true;
+ } else {
+ skip = -1 - x_left;
+ if (skip > 0)
+ ar->v1.skip_width -= skip;
+ }
+ }
+
+ ar->v1.x = x;
+ ar->v1.y = y;
+
+ if (ar->v1.skip_width <= 0 || ar->height<=0)
+ return;
+
+
+ y_clipping = (y_bottom > ar->outheight || y_top < 0);
+
+ if ( (uint)y_top > (uint)ar->outheight)
+ y_top = 0;
+
+ if ( (uint) y_bottom > (uint)ar->outheight)
+ y_bottom = ar->outheight;
+
+ if (y_top < ar->draw_top)
+ ar->draw_top = y_top;
+ if (y_bottom > ar->draw_bottom)
+ ar->draw_bottom = y_bottom;
+
+ if (x==-1) x=0; /* ?? */
+
+ ar->v1.destptr = ar->outptr + x + y * ar->outwidth;
+
+ charsetmask = false;
+
+ masking = false;
+ if (ar->clipping) {
+ masking = isMaskActiveAt(x_left, y_top, x_right, y_bottom,
+ getResourceAddress(rtBuffer, 9) + gdi._imgBufOffs[ar->clipping] + _screenStartStrip
+ ) != 0;
+ }
+
+ if (masking || charsetmask || ar->actor_unk1) {
+ ar->v1.mask_ptr = getResourceAddress(rtBuffer, 9) + y*40 + _screenStartStrip;
+ ar->v1.imgbufoffs = gdi._imgBufOffs[ar->clipping];
+ if (!charsetmask && masking) {
+ ar->v1.mask_ptr += ar->v1.imgbufoffs;
+ ar->v1.imgbufoffs = 0;
+ }
+ ar->v1.mask_ptr_dest = ar->v1.mask_ptr + (x >> 3);
+ }
+
+ ar->actor_unk1 = 0;
+
+ if(ar->actor_unk1==0)
+ akos_c1_0y_decode(ar);
+
+#if 0
+
+ switch(ar->actor_unk1) {
+ case 1:
+ akos_c1_spec1(ar);
+ return;
+ case 2:
+ akos_c1_spec2(ar);
+ return;
+ case 3:
+ akos_c1_spec3(ar);
+ return;
+ }
+
+ switch(((byte)y_clipping<<3) | ((byte)use_scaling<<2) | ((byte)masking<<1) | (byte)charsetmask) {
+ case 0: akos_c1_0_decode(ar); break;
+ case 0+8: akos_c1_0y_decode(ar); break;
+ case 2:
+ case 1: akos_c1_12_decode(ar); break;
+ case 2+8:
+ case 1+8: akos_c1_12y_decode(ar); break;
+ case 3+8:
+ case 3: akos_c1_3_decode(ar); break;
+ case 4: akos_c1_4_decode(ar); break;
+ case 4+8: akos_c1_4y_decode(ar); break;
+ case 6:
+ case 5: akos_c1_56_decode(ar); break;
+ case 6+8:
+ case 5+8: akos_c1_56y_decode(ar); break;
+ case 7:
+ case 7+8: akos_c1_7_decode(ar); break;
+ }
+#endif
+}
+
+
+void Scumm::akos_codec1_ignorePakCols(AkosRenderer *ar, int num) {
+ int n;
+ byte repcolor;
+ byte replen;
+ byte *src;
+
+ n = ar->height;
+ if (num>1) n *= num;
+ src = ar->srcptr;
+ do {
+ repcolor = *src++;
+ replen = repcolor & ar->v1.mask;
+ if (replen==0) {
+ replen = *src++;
+ }
+ do {
+ if (!--n) {
+ ar->v1.repcolor = repcolor>>ar->v1.shl;
+ ar->v1.replen = replen;
+ ar->srcptr = src;
+ return;
+ }
+ } while (--replen);
+ } while (1);
+}
+
+
+void Scumm::akos_codec5(AkosRenderer *ar) {
+ warning("akos_codec5: not implemented");
+}
+
+void Scumm::akos_codec16(AkosRenderer *ar) {
+ warning("akos_codec16: not implemented");
+}
+
+
+bool Scumm::akos_increaseAnims(byte *akos, Actor *a) {
+ byte *aksq, *akfo;
+ int i;
+ uint size;
+ bool result;
+
+ aksq = findResource(MKID('AKSQ'), akos) + 8;
+ akfo = findResource(MKID('AKFO'), akos);
+
+ size = 0;
+ if (akfo) {
+ size = (READ_BE_UINT32(akfo)-8)>>1;
+ akfo += 8;
+ }
+
+ result = false;
+ for(i=0;i!=0x10;i++) {
+ if (a->cost.active[i]!=0)
+ result|=akos_increaseAnim(a, i, aksq, (uint16*)akfo, size);
+ }
+ return result;
+}
+
+
+#define GW(o) ((int16)READ_LE_UINT16(aksq+curpos+(o)))
+#define GUW(o) READ_LE_UINT16(aksq+curpos+(o))
+#define GB(o) aksq[curpos+(o)]
+
+bool Scumm::akos_increaseAnim(Actor *a, int chan, byte *aksq, uint16 *akfo, int numakfo) {
+ byte active;
+ uint old_curpos, curpos,end;
+ uint code;
+ bool flag_value;
+ int tmp,tmp2;
+
+ active = a->cost.active[chan];
+ end = a->cost.end[chan];
+ old_curpos = curpos = a->cost.curpos[chan];
+ flag_value = false;
+
+ do {
+
+ code = aksq[curpos];
+ if (code & 0x80) code = (code<<8)|aksq[curpos+1];
+
+ switch(active) {
+ case 6:
+ switch(code) {
+ case AKC_JumpIfSet:
+ case AKC_AddVar:
+ case AKC_SetVar:
+ case AKC_SkipGE:
+ case AKC_SkipG:
+ case AKC_SkipLE:
+ case AKC_SkipL:
+ case AKC_SkipNE:
+ case AKC_SkipE:
+ curpos += 5;
+ break;
+ case AKC_JumpTable:
+ case AKC_SetActorClip:
+ case AKC_Ignore3:
+ case AKC_Ignore2:
+ case AKC_Ignore:
+ case AKC_StartAnim:
+ case AKC_CmdQue3:
+ curpos += 3;
+ break;
+ case AKC_SoundStuff:
+ curpos += 8;
+ break;
+ case AKC_Cmd3:
+ case AKC_SetVarInActor:
+ case AKC_SetDrawOffs:
+ curpos += 6;
+ break;
+ case AKC_ClearFlag:
+ case AKC_HideActor:
+ case AKC_CmdQue3Quick:
+ case AKC_Return:
+ curpos += 2;
+ break;
+ case AKC_JumpGE:
+ case AKC_JumpG:
+ case AKC_JumpLE:
+ case AKC_JumpL:
+ case AKC_JumpNE:
+ case AKC_JumpE:
+ case AKC_Random:
+ curpos += 7;
+ break;
+ case AKC_Flip:
+ case AKC_Jump:
+ curpos += 4;
+ break;
+ case AKC_ComplexChan:
+ curpos += 3;
+ tmp = aksq[curpos-1];
+ while (--tmp >= 0) {
+ curpos += 4;
+ curpos += (aksq[curpos]&0x80) ? 2 : 1;
+ }
+ break;
+ default:
+ if (code&0xC000)
+ error("akos_increaseAnim: invalid code %x", code);
+ curpos += (code&0x8000) ? 2 : 1;
+ }
+ break;
+ case 2:
+ curpos += (code&0x8000) ? 2 : 1;
+ if (curpos > end)
+ curpos = a->cost.start[chan];
+ break;
+ case 3:
+ if (curpos != end)
+ curpos += (code&0x8000) ? 2 : 1;
+ break;
+ }
+
+ code = aksq[curpos];
+ if (code & 0x80) code = (code<<8)|aksq[curpos+1];
+
+ if (flag_value && code!=AKC_ClearFlag)
+ continue;
+
+ switch(code) {
+ case AKC_StartAnimInActor:
+ akos_queCommand(4,
+ derefActorSafe(getAnimVar(a, GB(2)), "akos_increaseAnim:29"),
+ getAnimVar(a, GB(3)),
+ 0
+ );
+ continue;
+
+ case AKC_Random:
+ setAnimVar(a, GB(6), getRandomNumberRng(GW(2),GW(4)));
+ continue;
+ case AKC_SkipGE:
+ case AKC_SkipG:
+ case AKC_SkipLE:
+ case AKC_SkipL:
+ case AKC_SkipNE:
+ case AKC_SkipE:
+ if ( !akos_compare(getAnimVar(a, GB(4)),GW(2), code-AKC_SkipStart) )
+ flag_value = true;
+ continue;
+ case AKC_IncVar:
+ setAnimVar(a, 0, getAnimVar(a, 0)+1);
+ continue;
+ case AKC_SetVar:
+ setAnimVar(a, GB(4), GW(2));
+ continue;
+ case AKC_AddVar:
+ setAnimVar(a, GB(4), getAnimVar(a, GB(4)) + GW(2) );
+ continue;
+ case AKC_Flip:
+ a->flip = GW(2) != 0;
+ continue;
+ case AKC_CmdQue3:
+ tmp = GB(2);
+ if ((uint)tmp < 8)
+ akos_queCommand(3, a, a->sound[tmp], 0);
+ continue;
+ case AKC_CmdQue3Quick:
+ akos_queCommand(3, a, a->sound[1], 0);
+ continue;
+ case AKC_StartAnim:
+ akos_queCommand(4, a, GB(2), 0);
+ continue;
+ case AKC_StartVarAnim:
+ akos_queCommand(4, a, getAnimVar(a, GB(2)), 0);
+ continue;
+ case AKC_SetVarInActor:
+ setAnimVar(
+ derefActorSafe(getAnimVar(a, GB(2)),"akos_increaseAnim:9"),
+ GB(3), GW(4)
+ );
+ continue;
+ case AKC_HideActor:
+ akos_queCommand(1, a, 0, 0);
+ continue;
+ case AKC_SetActorClip:
+ akos_queCommand(5, a, GB(2), 0);
+ continue;
+ case AKC_SoundStuff:
+ tmp = GB(2);
+ if (tmp >= 8)
+ continue;
+ tmp2 = GB(4);
+ if (tmp2<1 || tmp2>3)
+ error("akos_increaseAnim:8 invalid code %d", tmp2);
+ akos_queCommand(tmp2+6, a, a->sound[tmp], GB(6));
+ continue;
+ case AKC_SetDrawOffs:
+ akos_queCommand(6, a, GW(2), GW(4));
+ continue;
+ case AKC_JumpTable:
+ if (akfo==NULL)
+ error("akos_increaseAnim: no AKFO table");
+ tmp = getAnimVar(a, GB(2)) - 1;
+ if (tmp<0 || tmp >= numakfo-1)
+ error("akos_increaseAnim: invalid jump value %d",tmp);
+ curpos = READ_LE_UINT16(&akfo[tmp]);
+ break;
+ case AKC_JumpIfSet:
+ if (!getAnimVar(a, GB(4)))
+ continue;
+ setAnimVar(a, GB(4), 0);
+ curpos = GUW(2);
+ break;
+
+ case AKC_ClearFlag:
+ flag_value = false;
+ continue;
+
+ case AKC_Jump:
+ curpos = GUW(2);
+ break;
+
+ case AKC_Return:
+ case AKC_ComplexChan:
+ break;
+
+ case AKC_Ignore:
+ case AKC_Ignore2:
+ case AKC_Ignore3:
+ continue;
+
+ case AKC_JumpE:
+ case AKC_JumpNE:
+ case AKC_JumpL:
+ case AKC_JumpLE:
+ case AKC_JumpG:
+ case AKC_JumpGE:
+ if ( !akos_compare(getAnimVar(a, GB(4)), GW(2), code - AKC_JumpStart) )
+ continue;
+ curpos = GUW(2);
+ break;
+
+ default:
+ if ((code&0xC000)==0xC000)
+ error("Undefined uSweat token %X", code);
+ }
+ break;
+ } while(1);
+
+ int code2 = aksq[curpos];
+ if (code2 & 0x80) code2 = (code2<<8)|aksq[curpos+1];
+ assert((code2&0xC000)!=0xC000 || code2==AKC_ComplexChan || code2==AKC_Return);
+
+ a->cost.curpos[chan] = curpos;
+
+ return curpos != old_curpos;
+}
+
+void Scumm::akos_queCommand(byte cmd, Actor *a, int param_1, int param_2) {
+// warning("akos_queCommand(%d,%d,%d,%d)", cmd, a->number, param_1, param_2);
+}
+
+
+bool Scumm::akos_compare(int a, int b, byte cmd) {
+ switch(cmd) {
+ case 0: return a==b;
+ case 1: return a!=b;
+ case 2: return a<b;
+ case 3: return a<=b;
+ case 4: return a>b;
+ default: return a>=b;
+ }
+}
+
+int Scumm::getAnimVar(Actor *a, byte var) {
+ assert(var>=0 && var<=15);
+ return a->animVariable[var];
+}
+
+void Scumm::setAnimVar(Actor *a, byte var, int value) {
+ assert(var>=0 && var<=15);
+ a->animVariable[var] = value;
+}
+
+
+#endif \ No newline at end of file
diff --git a/boxes.cpp b/boxes.cpp
index 96779c4f62..fc5038760e 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);
-
- 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);
+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;
+
+ 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 395cb1b9d3..ede1fb09db 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<<slot))
+ if (cd->curpos[slot]==0xFFFF || cd->stopped & (1<<slot))
return 0;
- i = cd->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<<i);
+ } else if (cmd==0x79) {
+ a->cost.stopped |= (1<<i);
+ } else {
+ a->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 fd18dcaf4b..169178d4d0 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 10c9430992..b56d6d6a90 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; i<numzbuf; i++) {
- zplane_list[i] = findResource(zplane_tags[i], ptr, 0);
+ zplane_list[i] = findResource(zplane_tags[i], ptr);
}
bottom = y + h;
@@ -633,25 +632,34 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, int stripnr
_bgbak_ptr = where_draw_ptr;
if (_vm->hasCharsetMask(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; i<numzbuf; i++) {
if (!zplane_list[i])
continue;
_z_plane_ptr = zplane_list[i] + READ_LE_UINT16(zplane_list[i] + stripnr*2 + 8);
_mask_ptr_dest = _vm->getResourceAddress(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<sizeof(actorDrawBits)/sizeof(actorDrawBits[0]));
+ assert(s>=0 && s<sizeof(gfxUsageBits)/sizeof(gfxUsageBits[0]));
_curVirtScreen = &virtscr[0];
- actorDrawBits[s]|=0x8000;
+ gfxUsageBits[s]|=0x80000000;
if (_curVirtScreen->height > _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 4b89bda31d..5f87ba1c8c 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 a661a2095f..f68e48e140 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<<OF_STATE_SHL);
+ checkRange(0xFF, 0, state, "State %d out of range in putState");
+ _objectStateTable[act] = state;
+}
+
+int Scumm::getObjectRoom(int obj) {
+ checkRange(_numGlobalObjects-1, 0, obj, "Object %d out of range in getObjectRoom");
+ return _objectRoomTable[obj];
}
int Scumm::getObjectIndex(int object) {
int i;
- if ((_objectFlagTable[object]&OF_OWNER_MASK)!=OF_OWNER_ROOM) {
+ /* OF_OWNER_ROOM should be 0xFF for full throttle, else 0xF */
+ if (_objectOwnerTable[object] != OF_OWNER_ROOM) {
for (i=0; i<_maxInventoryItems; i++)
if (_inventory[i] == object)
return i;
@@ -89,7 +94,7 @@ int Scumm::whereIsObject(int object) {
if (object >= _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 (a<NUM_ACTORS)
acta = derefActorSafe(a, "getObjActToObjActDist");
- if (b<=_vars[VAR_NUM_ACTOR])
+ if (b<NUM_ACTORS)
actb = derefActorSafe(b, "getObjActToObjActDist(2)");
if (acta && actb && acta->room==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;
-
- if (num==0)
- return;
+ byte a;
- 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);
+ setupRoomObject(od, room);
+ }
- 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)<<OF_STATE_SHL;
- }
- od->parent = cdhd->v6.parent;
- od->actordir = cdhd->v6.actordir;
+ 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->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)<<OF_STATE_SHL;
- }
- od->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->parentstate = (cdhd->v6.flags&0xF)<<OF_STATE_SHL;
+ }
+ od->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)<<OF_STATE_SHL;
}
- od->fl_object_index = 0;
+ od->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;
- CHECK_HEAP
+ 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);
-
- for (i=0; i<numobj; i++) {
- obcdptr = findResource(MKID('OBCD'), roomptr, i);
- if(obcdptr==NULL)
- error("addObjectToInventory: Not enough code blocks in room %d", room);
- cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcdptr, 0);
- if ( READ_LE_UINT16(&cdhd->obj_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;
+ error("findObjectInRoom: More (%d) than %d objects in room %d", numobj, _numLocalObjects, room);
+
+ 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));
+
+#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
- w = READ_LE_UINT16(&cdhd->v6.w)>>3;
- h = READ_LE_UINT16(&cdhd->v6.h)>>3;
+ dataptr = findResource(IMxx_tags[imgindex],foir.obim);
+ if (dataptr==NULL)
+ error("setCursorImg: No such image");
- size = READ_BE_UINT32(&cdhd->size);
+ 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 0128e699a0..4c71656532 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,108 +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);
-
- while (1) {
- blocktype = fileReadDword();
- if (fileReadFailed(_fileHandle))
- break;
- itemsize = fileReadDwordBE();
+ 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;
- numblock++;
+ case MKID('DSCR'):
+ _numScripts = fileReadWordLE();
+ itemsize-=2;
+ break;
- switch(blocktype) {
- case MKID('DCHR'):
- readResTypeList(rtCharset,MKID('CHAR'),"charset");
- break;
+ case MKID('DCOS'):
+ _numCostumes = fileReadWordLE();
+ itemsize-=2;
+ break;
- case MKID('DOBJ'):
- _numGlobalObjects = fileReadWordLE();
- _objectFlagTable = (byte*)alloc(_numGlobalObjects);
- if (mode==1) {
- fileSeek(_fileHandle, itemsize - 10, 1);
+ case MKID('DSOU'):
+ _numSounds = fileReadWordLE();
+ itemsize-=2;
break;
}
-
- _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;
+ fileSeek(_fileHandle, itemsize-8,SEEK_CUR);
}
+ clearFileReadFailed(_fileHandle);
+ fileSeek(_fileHandle, 0, SEEK_SET);
}
- 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();
@@ -263,24 +213,39 @@ void Scumm::readIndexFileV6() {
numblock++;
- switch(blocktype) {
+ switch(blocktype) {
case MKID('DCHR'):
readResTypeList(rtCharset,MKID('CHAR'),"charset");
break;
case MKID('DOBJ'):
- num = fileReadWordLE();
- assert(num == _numGlobalObjects);
- fileRead(_fileHandle, _objectFlagTable, num);
+ 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<num; i++) {
+ _objectStateTable[i] = _objectOwnerTable[i]>>OF_STATE_SHL;
+ _objectOwnerTable[i] &= OF_OWNER_MASK;
+ }
+ }
fileRead(_fileHandle, _classData, num * sizeof(uint32));
+
#if defined(SCUMM_BIG_ENDIAN)
- for (i=0; i<_numGlobalObjects; i++)
+ for (i=0; i<num; i++) {
_classData[i] = FROM_LE_32(_classData[i]);
+ }
#endif
break;
case MKID('RNAM'):
- fileSeek(_fileHandle, itemsize-8,1);
+ case MKID('ANAM'):
+ fileSeek(_fileHandle, itemsize-8,SEEK_CUR);
break;
case MKID('DROO'):
@@ -313,10 +278,8 @@ void Scumm::readIndexFileV6() {
}
}
- clearFileReadFailed(_fileHandle);
-
- if (numblock!=9)
- error("Not enough blocks read from directory");
+// if (numblock!=9)
+// error("Not enough blocks read from directory");
openRoom(-1);
}
@@ -345,7 +308,7 @@ void Scumm::readResTypeList(int id, uint32 tag, const char *name) {
num = fileReadWordLE();
- if (_majorScummVersion == 6) {
+ if (1 || _features&GF_AFTER_V6) {
if (num != res.num[id]) {
error("Invalid number of %ss (%d) in directory", name, num);
}
@@ -370,7 +333,7 @@ void Scumm::allocResTypeData(int id, uint32 tag, int num, const char *name, int
debug(9, "allocResTypeData(%d,%x,%d,%s,%d)",id,FROM_LE_32(tag),num,name,mode);
assert(id>=0 && id<sizeof(res.mode)/sizeof(res.mode[0]));
- if (num>=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 13d96e215c..199eea4594 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; j<res.num[i]; j++)
saveLoadResource(s,i,j);
- s->saveLoadArrayOf(_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 eec8d2b4d8..28f9f7f1c7 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--;
+
+ _sentenceNum--;
+
+#if !defined(FULL_THROTTLE)
+ if (sentence[_sentenceNum].unk2 &&
+ sentence[_sentenceNum].unk3==sentence[_sentenceNum].unk4)
return;
- }
+#endif
- _localParamList[0] = sentence[_sentenceIndex].unk5;
- _localParamList[1] = sentence[_sentenceIndex].unk4;
- _localParamList[2] = sentence[_sentenceIndex].unk3;
- _sentenceIndex--;
+ _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) {
- int shr,dir;
- bool inRoom;
+#if defined(FULL_THROTTLE)
+ int cmd,dir;
Actor *a;
a = derefActorSafe(act, "animateActor");
- shr = anim>>2;
- dir = anim&3;
+ if (anim==0xFF)
+ anim = 2000;
- inRoom = (a->room == _currentRoom);
+ cmd = anim / 1000;
+ dir = anim % 1000;
- if (shr == 0x3F) {
- if (inRoom) {
- startAnimActor(a, a->standFrame, a->facing);
- a->moving = 0;
- }
- return;
- }
+ /* temporary code */
+// dir = newDirToOldDir(dir);
- if (shr == 0x3E) {
- if (inRoom) {
- startAnimActor(a, 0x3E, dir);
- a->moving &= ~4;
- }
- a->facing = dir;
- return;
+ 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);
}
- if (shr == 0x3D) {
- if (inRoom) {
- turnToDirection(a, dir);
- } else {
- a->facing = dir;
- }
- return;
+
+#else
+ int shr,dir;
+ bool inRoom;
+ Actor *a;
+
+ a = derefActorSafe(act, "animateActor");
+
+ dir = anim&3;
+
+ 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);
}
- 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; i<NUM_SCRIPT_SLOT; i++,ss++)
if (ss->number==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; i<NUM_SCRIPT_SLOT; i++,ss++)
+ if (ss->number==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 c1cc62c096..828fcb2836 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 cb98b718eb..f4f2155d53 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 cca1a40402..cb577ec010 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 7f08723fd4..cfad282df9 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);
-
- roomptr = getResourceAddress(rtRoom, _roomResource);
- for (i=0; ptr = findResource(MKID('LSCR'), roomptr, i++) ;) {
- _localScriptList[ptr[8] - _numGlobalScripts] = ptr - roomptr;
+ memset(_localScriptList, 0, sizeof(_localScriptList));
+
+ 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 8b0963385e..4049781556 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"
@@ -321,6 +312,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 4c2cf92564..533c275b44 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 b93cba2d8d..e6a223ac94 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 72f530804b..e921346c1b 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; i<numobj; i++) {
- obimptr = findResource(MKID('OBIM'), roomptr, i);
- if (obimptr==NULL)
- error("Not enough image blocks in room %d", room);
- imhd = (ImageHeader*)findResource(MKID('IMHD'), obimptr, 0);
- if ( READ_LE_UINT16(&imhd->obj_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 07330d8916..09070dd25f 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);