very simple full throttle support, use the FULL_THROTTLE define. (will fix later)

modified some actor parts to work better with full throttle (most likely new bugs because of that).
directions are now stored as angles instead of left/right/up/down
implemented loadFlObject (flobjects are currently saved in the savestate, will fix that also)

svn-id: r3505
This commit is contained in:
Ludvig Strigeus 2001-11-26 19:57:57 +00:00
parent 7b959f6267
commit 38e2a886ce
20 changed files with 3354 additions and 1324 deletions

599
actor.cpp
View file

@ -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;
if (diffY != 0) {
XYFactor = YXFactor * diffX / diffY;
} else {
XYFactor = YXFactor * diffX;
if (diffY != 0) {
XYFactor /= diffY;
} else {
YXFactor = 0;
}
@ -108,10 +120,10 @@ int Scumm::calcMovementFactor(Actor *a, int newX, int newY) {
if (diffX < 0)
XYFactor = -XYFactor;
if (diffX != 0) {
YXFactor = XYFactor * diffY / diffX;
} else {
YXFactor = XYFactor * diffY;
if (diffX != 0) {
YXFactor /= diffX;
} else {
XYFactor = 0;
}
}
@ -125,87 +137,141 @@ int Scumm::calcMovementFactor(Actor *a, int newX, int newY) {
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;
int Scumm::remapDirection(Actor *a, int dir) {
int specdir;
byte flags;
byte direction;
if (!a->ignoreBoxes) {
specdir = _extraBoxFlags[a->walkbox];
if (specdir) {
if (specdir & 0x8000) {
dir = specdir & 0x3FFF;
} else {
error("getProgrDirChange: special dir not implemented");
}
}
flags = getBoxFlags(a->walkbox);
if ((flags&8) || getClass(a->number, 0x1E)) {
dir = 360 - dir;
}
if ((flags&0x10) || getClass(a->number, 0x1D)) {
dir = 180 - dir;
}
switch(flags & 7) {
case 1:
if (dir >= 180)
return 270;
return 90;
case 2:
if (dir <= 90 || dir>270)
return 0;
return 180;
case 3: return 270;
case 4: return 90;
case 5: return 0;
case 6: return 180;
}
}
return normalizeAngle(dir);
}
int Scumm::updateActorDirection(Actor *a) {
int from,to;
int diff;
from = toSimpleDir(a->facing);
to = toSimpleDir(remapDirection(a, a->newDirection));
diff = to - from;
if (abs(diff) > 2)
diff = -diff;
if (diff==0) {
} else if (diff>0) {
from++;
} else {
from--;
}
return fromSimpleDir(from&3);
}
void Scumm::setActorBox(Actor *a, int box) {
a->walkbox = box;
a->mask = getMaskFromBox(box);
setupActorScale(a);
}
int Scumm::actorWalkStep(Actor *a) {
int tmpX, tmpY;
int actorX, actorY;
int distX, distY;
int direction;
a->needRedraw = true;
a->needBgReset = true;
XYFactor = a->walkdata.XYFactor;
YXFactor = a->walkdata.YXFactor;
direction = XYFactor>0 ? 1 : 0;
if (abs(YXFactor) * 2 > abs(XYFactor))
direction = YXFactor>0 ? 2 : 3;
a->newDirection = direction;
direction = getProgrDirChange(a, 1);
if (!(a->moving&2) || a->facing!=direction) {
if (a->walkFrame != a->animIndex || a->facing != direction) {
startAnimActor(a, a->walkFrame, direction);
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|=2;
a->moving|=MF_IN_LEG;
}
actorX = a->walkdata.x;
actorY = a->walkdata.y;
newx = a->walkdata.newx;
newy = a->walkdata.newy;
actorX = a->x;
actorY = a->y;
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);
}
if (a->walkbox != a->walkdata.curbox &&
checkXYInBoxBounds(a->walkdata.curbox, actorX, actorY)) {
setActorBox(a, a->walkdata.curbox);
}
newXDist = abs(newx - actorX);
distX = abs(a->walkdata.newx - a->walkdata.x);
distY = abs(a->walkdata.newy - a->walkdata.y);
if (newXDist <= abs(a->x - actorX) &&
abs(newy - actorY) <= abs(a->y - actorY) ){
a->moving&=~2;
if (
abs(actorX - a->walkdata.x) >= distX &&
abs(actorY - a->walkdata.y) >= distY
) {
a->moving &= ~MF_IN_LEG;
return 0;
}
XYFactor = (XYFactor>>8) * a->scalex;
YXFactor = (YXFactor>>8) * a->scalex;
tmpX = ((actorX + 8000)<<16) + a->walkdata.xfrac +
(a->walkdata.XYFactor>>8) * a->scalex;
a->walkdata.xfrac = (uint16)tmpX;
actorX = (tmpX>>16) - 8000;
tmp = ((a->x + 8000)<<16) + a->walkdata.xfrac + XYFactor;
tmp2 = (a->y<<16) + a->walkdata.yfrac + YXFactor;
tmpY = (actorY<<16) + a->walkdata.yfrac +
(a->walkdata.YXFactor>>8) * a->scalex;
a->walkdata.yfrac = (uint16)tmpY;
actorY = (tmpY>>16);
a->x = (tmp>>16)-8000;
a->y = tmp2>>16;
if (abs(a->x - actorX) > newXDist) {
a->x = newx;
if (abs(actorX - a->walkdata.x) > distX) {
actorX = a->walkdata.newx;
}
if (abs(a->y - actorY) > abs(newy - actorY)) {
a->y = newy;
}
a->walkdata.xfrac = tmp&0xFFFF;
a->walkdata.yfrac = tmp2&0xFFFF;
if (a->x == newx &&
a->y == newy) {
a->moving&=~2;
return 0;
if (abs(actorY - a->walkdata.y) > distY) {
actorY = a->walkdata.newy;
}
a->x = actorX;
a->y = actorY;
return 1;
}
void Scumm::setupActorScale(Actor *a) {
uint16 scale;
byte *resptr;
@ -232,68 +298,27 @@ void Scumm::setupActorScale(Actor *a) {
a->scaley = (byte)scale;
}
int Scumm::getProgrDirChange(Actor *a, int mode) {
int flags;
byte facing, newdir;
byte XYflag, YXflag;
byte lookdir;
const byte direction_transtab[] = {
0,2,2,3,2,1,2,3,0,1,2,1,0,1,0,3
};
flags = 0;
if (!a->ignoreBoxes)
flags = getBoxFlags(a->walkbox);
facing = a->facing;
newdir = a->newDirection;
XYflag = a->walkdata.XYFactor>0 ? 1 : 0;
YXflag = a->walkdata.YXFactor>0 ? 1 : 0;
if ((flags&8) || getClass(a->number, 0x1E)) {
if (!(newdir&2))
newdir^=1;
XYflag = 1 - XYflag;
#if defined(FULL_THROTTLE)
void Scumm::startAnimActor(Actor *a, int frame) {
switch(frame) {
case 1001: frame = a->initFrame; break;
case 1002: frame = a->walkFrame; break;
case 1003: frame = a->standFrame; break;
case 1004: frame = a->talkFrame1; break;
case 1005: frame = a->talkFrame2; break;
}
if ((flags&0x10) || getClass(a->number, 0x1D)) {
if (newdir&2)
newdir^=1;
YXflag = 1 - YXflag;
if (a->costume != 0) {
a->animProgress = 0;
a->needRedraw = true;
a->needBgReset = true;
if (frame == a->initFrame)
initActorCostumeData(a);
akos_decodeData(a, frame, (uint)-1);
}
lookdir = direction_transtab[facing*4+newdir];
if (!(flags&=0x7))
return lookdir;
if (mode==0) {
lookdir = newdir;
if (flags==1 && newdir!=1)
lookdir = 0;
if (flags==2 && newdir!=3)
lookdir = 2;
} else {
if (flags==1)
lookdir = XYflag;
if (flags==2)
lookdir = 3 - YXflag;
}
if (flags==3)
lookdir=0;
if (flags==4)
lookdir=1;
if (flags==6)
lookdir=2;
if (flags==5)
lookdir = 3;
return lookdir;
}
void Scumm::startAnimActor(Actor *a, int frame, byte direction) {
#else
void Scumm::startAnimActor(Actor *a, int frame) {
if (frame==0x38)
frame = a->initFrame;
@ -320,27 +345,15 @@ void Scumm::startAnimActor(Actor *a, int frame, byte direction) {
initActorCostumeData(a);
if (frame!=0x3E) {
decodeCostData(a, frame*4 + direction, -1);
decodeCostData(a, frame, -1);
}
}
if (a->facing != direction)
fixActorDirection(a, direction);
}
a->facing = direction;
a->needBgReset = true;
}
#endif
void Scumm::initActorCostumeData(Actor *a) {
CostumeData *cd = &a->cost;
int i;
cd->hdr = 0;
for (i=0; i<16; i++)
cd->a[i] = cd->b[i] = cd->c[i] = cd->d[i] = 0xFFFF;
}
void Scumm::fixActorDirection(Actor *a, byte direction) {
void Scumm::fixActorDirection(Actor *a, int direction) {
uint mask;
int i;
uint16 vald;
@ -348,69 +361,29 @@ void Scumm::fixActorDirection(Actor *a, byte direction) {
if (a->facing == direction)
return;
a->facing = direction;
if (a->costume==0)
return;
#if !defined(FULL_THROTTLE)
cost.loadCostume(a->costume);
#endif
mask = 0x8000;
for (i=0; i<16; i++,mask>>=1) {
vald = a->cost.d[i];
if (vald==0xFFFF || (vald&3)==direction)
vald = a->cost.frame[i];
if (vald==0xFFFF)
continue;
decodeCostData(a, (vald&0xFC)|direction, mask);
#if !defined(FULL_THROTTLE)
decodeCostData(a, vald, mask);
#else
akos_decodeData(a, vald, mask);
#endif
}
a->facing = direction;
}
void Scumm::decodeCostData(Actor *a, int frame, uint usemask) {
byte *p,*r;
uint mask,j;
int i;
byte extra,cmd;
byte *dataptr;
p = cost._ptr;
if (frame > p[6])
return;
r = p + READ_LE_UINT16(p + frame*2 + cost._numColors + 42);
if (r==p)
return;
dataptr = p + READ_LE_UINT16(p + cost._numColors + 8);
mask = READ_LE_UINT16(r);
r+=2;
i = 0;
do {
if (mask&0x8000) {
j = READ_LE_UINT16(r);
r+=2;
if (usemask&0x8000) {
if (j==0xFFFF) {
a->cost.a[i] = 0xFFFF;
a->cost.b[i] = 0;
a->cost.d[i] = frame;
} else {
extra = *r++;
cmd = dataptr[j];
if (cmd==0x7A) {
a->cost.hdr &= ~(1<<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;
@ -476,6 +449,9 @@ AdjustBoxResult Scumm::adjustXYToBeInBox(Actor *a, int x, int y) {
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) {
if (newdir==-1)
return;
a->moving &= ~4;
if (newdir != a->facing) {
a->moving = 4;
a->newDirection = newdir;
}
}
void Scumm::showActor(Actor *a) {
@ -563,7 +546,7 @@ void Scumm::showActor(Actor *a) {
ensureResourceLoaded(rtCostume, a->costume);
if (a->costumeNeedsInit) {
startAnimActor(a, a->initFrame, a->facing);
startAnimActor(a, a->initFrame);
a->costumeNeedsInit = false;
}
a->moving = 0;
@ -594,7 +577,7 @@ void Scumm::stopTalk() {
if (act && act<0x80) {
Actor *a = derefActorSafe(act, "stopTalk");
if (_currentRoom == a->room && _useTalkAnims) {
startAnimActor(a, a->talkFrame2, a->facing);
startAnimActor(a, a->talkFrame2);
_useTalkAnims = false;
}
_vars[VAR_TALK_ACTOR] = 0xFF;
@ -637,6 +620,37 @@ void Scumm::playActorSounds() {
}
}
void Scumm::startWalkAnim(Actor *a, int cmd, int angle) {
int16 args[16];
if (angle == -1)
angle = a->facing;
if (a->walk_script != 0) {
args[2] = angle;
args[0] = a->number;
args[1] = cmd;
runScript(a->walk_script, 1, 0, args);
} else {
switch(cmd) {
case 1: /* start walk */
//a->facing = angle;
fixActorDirection(a, angle);
startAnimActor(a, a->walkFrame);
break;
case 2: /* change dir only */
fixActorDirection(a, angle);
break;
case 3: /* stop walk */
turnToDirection(a, angle);
startAnimActor(a, a->standFrame);
break;
}
}
}
void Scumm::walkActor(Actor *a) {
int j;
@ -649,41 +663,59 @@ void Scumm::walkActor(Actor *a) {
if (a->moving&8) {
a->moving = 0;
j = a->walkdata.destbox;
if (j) {
a->walkbox = j;
a->mask = getMaskFromBox(j);
}
startAnimActor(a, a->standFrame, a->facing);
if (a->walkdata.destdir==0xFF ||
a->walkdata.destdir==a->newDirection)
return;
a->newDirection = a->walkdata.destdir;
a->moving = 4;
setActorBox(a, a->walkdata.destbox);
startWalkAnim(a, 3, a->walkdata.destdir);
return;
}
if (a->moving&4) {
j = getProgrDirChange(a, 0);
j = updateActorDirection(a);
if (a->facing != j)
startAnimActor(a, 0x3E, j);
fixActorDirection(a,j);
else
a->moving = 0;
return;
}
a->walkbox = a->walkdata.curbox;
a->mask = getMaskFromBox(a->walkdata.curbox);
setupActorScale(a);
a->moving = (a->moving&2)|1;
setActorBox(a, a->walkdata.curbox);
a->moving &= 2;
}
#if OLD
a->moving &= ~1;
if (!a->walkbox) {
a->walkbox = a->walkdata.destbox;
a->walkdata.curbox = a->walkdata.destbox;
a->moving |= 8;
calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty);
return;
}
if (a->ignoreBoxes || a->walkbox==a->walkdata.destbox) {
a->walkdata.curbox = a->walkbox;
a->moving |= 8;
calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty);
return;
}
j = getPathToDestBox(a->walkbox,a->walkdata.destbox);
if (j==0) {
error("walkActor: no path found between %d and %d", a->walkbox, a->walkdata.destbox);
}
a->walkdata.curbox = j;
if (findPathTowards(a, a->walkbox, j, a->walkdata.destbox)) {
a->moving |= 8;
calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty);
return;
}
calcMovementFactor(a, _foundPathX, _foundPathY);
#endif
#if 1
do {
a->moving&=~1;
if (!a->walkbox) {
a->walkbox = a->walkdata.destbox;
setActorBox(a, a->walkdata.destbox);
a->walkdata.curbox = a->walkdata.destbox;
break;
}
@ -701,12 +733,11 @@ void Scumm::walkActor(Actor *a) {
if (calcMovementFactor(a, _foundPathX, _foundPathY))
return;
a->walkbox = a->walkdata.curbox;
a->mask = getMaskFromBox(a->walkdata.curbox);
setupActorScale(a);
setActorBox(a, a->walkdata.curbox);
} while (1);
a->moving |= 8;
calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty);
#endif
}
void Scumm::processActors() {
@ -741,9 +772,6 @@ void Scumm::processActors() {
do {
a = *ac;
if (a->costume) {
setupActorScale(a);
setupCostumeRenderer(&cost, a);
setActorCostPalette(a);
CHECK_HEAP
drawActorCostume(a);
CHECK_HEAP
@ -779,31 +807,83 @@ void Scumm::setActorCostPalette(Actor *a) {
}
}
#if !defined(FULL_THROTTLE)
void Scumm::drawActorCostume(Actor *a) {
if (a==NULL || !a->needRedraw)
return;
setupActorScale(a);
setupCostumeRenderer(&cost, a);
setActorCostPalette(a);
a->top = 0xFF;
a->needRedraw = 0;
a->bottom = 0;
cost.loadCostume(a->costume);
cost._mirror = a->facing!=0 || (cost._ptr[7]&0x80);
cost._mirror = newDirToOldDir(a->facing)!=0 || (cost._ptr[7]&0x80);
if (cost.drawCostume(a)) {
a->needRedraw = true;
a->needBgReset = true;;
}
cost.drawCostume(a);
}
#else
void Scumm::drawActorCostume(Actor *a) {
AkosRenderer ar;
if (a==NULL || !a->needRedraw)
return;
a->needRedraw = false;
setupActorScale(a);
ar.x = a->x - virtscr->xstart;
ar.y = a->y - a->elevation;
ar.scale_x = a->scalex;
ar.scale_y = a->scaley;
ar.clipping = a->neverZClip;
if (ar.clipping == 100) {
ar.clipping = a->mask;
if (ar.clipping > (byte)gdi._numZBuffer)
ar.clipping = gdi._numZBuffer;
}
ar.outptr = getResourceAddress(rtBuffer, 1) + virtscr->xstart;
ar.outwidth = virtscr->width;
ar.outheight = virtscr->height;
akos_setCostume(&ar, a->costume);
akos_setPalette(&ar, a->palette);
akos_setFacing(&ar, a);
ar.dirty_id = a->number;
ar.cd = &a->cost;
ar.draw_top = a->top = 0x7fffffff;
ar.draw_bottom = a->bottom = 0;
akos_drawCostume(&ar);
a->top = ar.draw_top;
a->bottom = ar.draw_bottom;
}
#endif
void Scumm::actorAnimate(Actor *a) {
if (a==NULL)
byte *akos;
if (a==NULL || a->costume == 0)
return;
a->animProgress++;
if (a->animProgress >= a->animSpeed) {
a->animProgress = 0;
#if defined(FULL_THROTTLE)
akos = getResourceAddress(rtCostume, a->costume);
assert(akos);
if (akos_increaseAnims(akos, a)) {
#else
cost.loadCostume(a->costume);
if (cost.animate(a)) {
#endif
a->needRedraw = true;
a->needBgReset = true;
}
@ -811,14 +891,14 @@ void Scumm::actorAnimate(Actor *a) {
}
void Scumm::setActorRedrawFlags() {
int i,j;
int bits;
uint i,j;
uint32 bits;
for (i=0; i<40; i++) {
bits = actorDrawBits[_screenStartStrip+i];
if (bits&0x3FFF) {
bits = gfxUsageBits[_screenStartStrip+i];
if (bits&0x3FFFFFFF) {
for(j=0; 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) {
@ -977,3 +1046,7 @@ bool Scumm::isCostumeInUse(int cost) {
return false;
}
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);
}

1040
akos.cpp Normal file

File diff suppressed because it is too large Load diff

494
boxes.cpp
View file

@ -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;
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(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,&box1);
getBoxCoordinates(box2nr,&box2);
i = 0;
do {
if (i >= 4) goto ExitPos;
for (j=0; j<4; j++) {
if (upperRightX==upperLeftX &&
box.upperLeftX==upperLeftX &&
box.upperRightX==upperRightX) {
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;
}
ExitPos:;
n = m = 0;
if (upperRightY < upperLeftY) {
m = 1;
SWAP(upperRightY, upperLeftY);
if (box2.ul.y > box2.ur.y) {
SWAP(box2.ul.y, box2.ur.y);
flag |= 2;
}
if (box.upperRightY < box.upperLeftY) {
n = 1;
SWAP(box.upperRightY, box.upperLeftY);
}
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;
}
}
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 (box2.ul.x > box2.ur.x) {
SWAP(box2.ul.x, box2.ur.x);
flag |= 2;
}
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 (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 (box.upperRightX < box.upperLeftX) {
n = 1;
SWAP(box.upperRightX, box.upperLeftX);
}
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 (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 = box1.ul;
box1.ul = box1.ur;
box1.ur = box1.ll;
box1.ll = box1.lr;
box1.lr = tmp;
}
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 = box2.ul;
box2.ul = box2.ur;
box2.ur = box2.ll;
box2.ll = box2.lr;
box2.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);
error("findPathTowards: default");
}
void Scumm::setBoxFlags(int box, int 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;

View file

@ -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);
}

View file

@ -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");

156
gfx.cpp
View file

@ -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,8 +382,7 @@ 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) {
@ -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) {
}

View file

@ -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) {

View file

@ -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;
byte a;
if (num==0)
return;
do {
od = &_objs[num];
if (!od->obj_nr || !(od->ownerstate&OF_STATE_MASK))
for(i=1; i<=_numObjectsInRoom; i++) {
od = &_objs[i];
if (!od->obj_nr || !od->state || od->fl_object_index)
continue;
do {
a = od->parentstate;
if (!od->parent) {
drawObject(num, arg);
drawObject(i, arg);
break;
}
od = &_objs[od->parent];
} while ((od->ownerstate & OF_STATE_MASK)==a);
} while (--num);
} while (od->state==a);
}
}
const uint32 state_tags[] = {
const uint32 IMxx_tags[] = {
MKID('IM00'),
MKID('IM01'),
MKID('IM02'),
@ -272,9 +278,9 @@ void Scumm::drawObject(int obj, int arg) {
od = &_objs[obj];
xpos = od->x_pos;
xpos = od->x_pos>>3;
ypos = od->y_pos;
width = od->numstrips;
width = od->width>>3;
height = od->height;
if (width==0 || xpos > _screenEndStrip || xpos + width < _screenStartStrip)
@ -282,13 +288,13 @@ void Scumm::drawObject(int obj, int arg) {
if (od->fl_object_index) {
ptr = getResourceAddress(rtFlObject, od->fl_object_index);
ptr = findResource(MKID('OBIM'), ptr, 0);
ptr = findResource(MKID('OBIM'), ptr);
} else {
ptr = getResourceAddress(rtRoom, _roomResource);
ptr = ptr + od->offs_obim_to_room;
}
ptr = findResource(state_tags[getState(od->obj_nr)], ptr, 0);
ptr = findResource(IMxx_tags[getState(od->obj_nr)], ptr);
if (!ptr)
return;
@ -302,19 +308,18 @@ void Scumm::drawObject(int obj, int arg) {
continue;
if (tmp < _screenStartStrip || tmp > _screenEndStrip)
continue;
actorDrawBits[tmp] |= 0x8000;
gfxUsageBits[tmp] |= 0x80000000;
if (tmp < x)
x = tmp;
numstrip++;
}
if (numstrip!=0)
gdi.drawBitmap(ptr, _curVirtScreen, x, ypos<<3, height<<3, x-xpos, numstrip, true);
// _drawBmpY = ypos << 3;
// gdi._numLinesToProcess = height << 3;
// _drawBmpX = x;
// drawBmp(ptr, x - xpos, b, 1, "Object", od->obj_nr);
if (numstrip!=0) {
byte flags = Gdi::dbAllowMaskOr;
if (getClass(od->obj_nr, 22))
flags |= Gdi::dbDrawMaskOnBoth;
gdi.drawBitmap(ptr, _curVirtScreen, x, ypos, height, x-xpos, numstrip, flags);
}
}
void Scumm::loadRoomObjects() {
@ -322,7 +327,7 @@ void Scumm::loadRoomObjects() {
ObjectData *od;
byte *ptr;
uint16 obim_id;
byte *room;
byte *room,*searchptr;
ImageHeader *imhd;
RoomHeader *roomhdr;
@ -331,7 +336,7 @@ void Scumm::loadRoomObjects() {
CHECK_HEAP
room = getResourceAddress(rtRoom, _roomResource);
roomhdr = (RoomHeader*)findResource(MKID('RMHD'), room, 0);
roomhdr = (RoomHeader*)findResource(MKID('RMHD'), room);
_numObjectsInRoom = READ_LE_UINT16(&roomhdr->numObjects);
@ -342,8 +347,9 @@ void Scumm::loadRoomObjects() {
error("More than %d objects in room %d", _numLocalObjects, _roomResource);
od = &_objs[1];
searchptr = room;
for (i=0; i<_numObjectsInRoom; i++,od++) {
ptr = findResource(MKID('OBCD'), room, i);
ptr = findResource(MKID('OBCD'), searchptr);
if (ptr==NULL)
error("Room %d missing object code block(s)", _roomResource);
@ -358,10 +364,12 @@ void Scumm::loadRoomObjects() {
dumpResource(buf, od->obj_nr, ptr);
} while (0);
#endif
searchptr = NULL;
}
searchptr = room;
for (i=0; i<_numObjectsInRoom; i++) {
ptr = findResource(MKID('OBIM'), room, i);
ptr = findResource(MKID('OBIM'), searchptr);
if (ptr==NULL)
error("Room %d missing image blocks(s)", _roomResource);
@ -372,19 +380,32 @@ 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);
setupRoomObject(od, room);
}
CHECK_HEAP
}
void Scumm::setupRoomObject(ObjectData *od, byte *room) {
byte *obcd;
CodeHeader *cdhd;
ImageHeader *imhd;
cdhd = (CodeHeader*)findResource(MKID('CDHD'), room + od->offs_obcd_to_room);
od->obj_nr = READ_LE_UINT16(&cdhd->obj_id);
if (_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 !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 {
@ -393,10 +414,10 @@ void Scumm::loadRoomObjects() {
od->parent = cdhd->v6.parent;
od->actordir = cdhd->v6.actordir;
} else {
od->numstrips = cdhd->v5.w;
od->height = cdhd->v5.h;
od->x_pos = cdhd->v5.x;
od->y_pos = cdhd->v5.y;
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 {
@ -407,17 +428,26 @@ void Scumm::loadRoomObjects() {
od->walk_y = READ_LE_UINT16(&cdhd->v5.walk_y);
od->actordir = cdhd->v5.actordir;
}
od->fl_object_index = 0;
}
#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
return;
}
// ensureResourceLoaded(rtRoom, room);
roomptr = getResourceAddress(rtRoom, room);
roomhdr = (RoomHeader*)findResource(MKID('RMHD'), roomptr, 0);
numobj = READ_LE_UINT16(&roomhdr->numObjects);
if (numobj==0)
error("addObjectToInventory: 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);
} 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) + cdoffs;
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;
}
fo->roomptr = roomptr = getResourceAddress(rtRoom, room);
roomhdr = (RoomHeader*)findResource(MKID('RMHD'), roomptr);
numobj = READ_LE_UINT16(&roomhdr->numObjects);
if (numobj==0)
error("findObjectInRoom: No object found in room %d", room);
if (numobj > _numLocalObjects)
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 (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);
if (room==(uint)-1)
room = getObjectRoom(img);
numobj = READ_LE_UINT16(&rmhd->numObjects);
for(i=0; ;i++) {
if (i>=numobj)
error("setCursorImg: object %d code not found in room %d", img, room);
obcd = findResource(MKID('OBCD'), roomptr, i);
if (obcd==NULL)
error("setCursorImg: not enough code blocks in room %d", room);
cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcd, 0);
if (READ_LE_UINT16(&cdhd->obj_id) == img)
break;
}
for(i=0; ;i++) {
if (i>=numobj)
error("setCursorImg: object %d image not found in room %d", img, room);
obim = findResource(MKID('OBIM'), roomptr, i);
if (obim==NULL)
error("setCursorImg: not enough image blocks in room %d", room);
imhd = (ImageHeader*)findResource(MKID('IMHD'), obim, 0);
if (READ_LE_UINT16(&imhd->obj_id) == img)
break;
}
}
findObjectInRoom(&foir, foCodeHeader | foImageHeader | foCheckAlreadyLoaded, img, room);
setCursorHotspot2(
READ_LE_UINT16(&imhd->hotspot[0].x),
READ_LE_UINT16(&imhd->hotspot[0].y));
READ_LE_UINT16(&foir.imhd->hotspot[0].x),
READ_LE_UINT16(&foir.imhd->hotspot[0].y));
w = READ_LE_UINT16(&cdhd->v6.w)>>3;
h = READ_LE_UINT16(&cdhd->v6.h)>>3;
#if !defined(FULL_THROTTLE)
w = READ_LE_UINT16(&foir.cdhd->v6.w)>>3;
h = READ_LE_UINT16(&foir.cdhd->v6.h)>>3;
#else
w = READ_LE_UINT16(&foir.imhd->width)>>3;
h = READ_LE_UINT16(&foir.imhd->height)>>3;
#endif
size = READ_BE_UINT32(&cdhd->size);
dataptr = findResource(IMxx_tags[imgindex],foir.obim);
if (dataptr==NULL)
error("setCursorImg: No such image");
size = READ_BE_UINT32(dataptr+4);
if (size > sizeof(_grabbedCursor))
error("setCursorImg: Cursor image too large");
dataptr = findResource(MKID('IM01'),obim, 0);
if ((bomp = findResource(MKID('BOMP'), dataptr, 0)) != NULL)
if ((bomp = findResource(MKID('BOMP'), dataptr)) != NULL)
useBompCursor(bomp, w, h);
else
useIm01Cursor(dataptr, w, h);
@ -838,13 +883,13 @@ void Scumm::enqueueObject(int a, int b, int c, int d, int e, int f, int g, int h
eo->y = c;
if (d==0) {
od = &_objs[getObjectIndex(a)];
eo->width = od->numstrips<<3;
eo->width = od->width;
} else {
eo->width = d;
}
if (e==0) {
od = &_objs[getObjectIndex(a)];
eo->height = od->height<<3;
eo->height = od->height;
} else {
eo->height = e;
}
@ -887,14 +932,14 @@ void Scumm::drawEnqueuedObject(EnqueuedObject *eo) {
} else if (eo->a!=0) {
od = &_objs[getObjectIndex(eo->a)];
ptr = getResourceAddress(rtFlObject, od->fl_object_index);
ptr = findResource(MKID('OBIM'), ptr, 0);
ptr = findResource(MKID('OBIM'), ptr);
} else {
warning("drawEnqueuedObject: invalid");
return;
}
ptr = findResource(MKID('IM01'), ptr, 0);
bomp = findResource(MKID('BOMP'), ptr, 0);
ptr = findResource(MKID('IM01'), ptr);
bomp = findResource(MKID('BOMP'), ptr);
width = READ_LE_UINT16(&((BompHeader*)bomp)->width);
height = READ_LE_UINT16(&((BompHeader*)bomp)->height);
@ -906,9 +951,11 @@ void Scumm::drawEnqueuedObject(EnqueuedObject *eo) {
if (eo->a) {
dataptr = bomp + 18;
}
// debug(1, "drawEnqueuedObject(%d,%d,%d,%d,%d, %d,%d,%d,%d,%d,%d,%d)",
// eo->x, eo->y, eo->width, eo->height, eo->a, eo->b, eo->c, eo->d, eo->e, eo->j, eo->k, eo->l);
updateDirtyRect(vs->number, x, x+width,y,y+height,0);
}
@ -928,3 +975,58 @@ void Scumm::removeEnqueuedObject(EnqueuedObject *eo) {
restoreBG(eo->x, eo->y, eo->x + eo->width, eo->y + eo->height);
}
int Scumm::findFlObjectSlot() {
int i;
for(i=1; i<_maxFLObject; i++) {
if (_baseFLObject[i] == NULL)
return i;
}
error("findFlObjectSlot: Out of FLObject slots");
}
void Scumm::loadFlObject(uint object, uint room) {
FindObjectInRoom foir;
int slot;
ObjectData *od;
byte *flob,*roomptr;
uint32 obcd_size, obim_size, flob_size;
/* Don't load an already loaded object */
if (whereIsObject(object) != WIO_NOT_FOUND)
return;
if (room==(uint)-1)
room = getObjectRoom(object);
/* Locate the object in the room resource */
findObjectInRoom(&foir, foImageHeader | foCodeHeader, object, room);
/* Add an entry for the new floating object in the local object table */
if (++_numObjectsInRoom > _numLocalObjects)
error("loadFlObject: Local Object Table overflow");
od = &_objs[_numObjectsInRoom];
/* Setup sizes */
obcd_size = READ_BE_UINT32(foir.obcd + 4);
od->offs_obcd_to_room = 8;
od->offs_obim_to_room = obcd_size + 8;
obim_size = READ_BE_UINT32(foir.obim + 4);
flob_size = obcd_size + obim_size + 8;
/* Allocate slot & memory for floating object */
slot = findFlObjectSlot();
createResource(rtFlObject, slot, flob_size);
/* Copy object code + object image to floating object */
roomptr = getResourceAddress(rtRoom, room);
flob = getResourceAddress(rtFlObject, slot);
((uint32*)flob)[0] = MKID('FLOB');
((uint32*)flob)[1] = TO_BE_32(flob_size);
memcpy(flob + 8, roomptr - foir.roomptr + foir.obcd, obcd_size);
memcpy(flob + 8 + obcd_size, roomptr - foir.roomptr + foir.obim, obim_size);
/* Setup local object flags */
setupRoomObject(od, flob);
od->fl_object_index = slot;
}

View file

@ -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,99 +156,7 @@ void Scumm::askForDisk(const char *filename) {
error("Cannot find '%s'", filename);
}
void Scumm::readIndexFileV5(int mode) {
uint32 blocktype,itemsize;
int numblock = 0;
#if defined(SCUMM_BIG_ENDIAN)
int i;
#endif
debug(9, "readIndexFile(%d)",mode);
openRoom(-1);
openRoom(0);
while (1) {
blocktype = fileReadDword();
if (fileReadFailed(_fileHandle))
break;
itemsize = fileReadDwordBE();
numblock++;
switch(blocktype) {
case MKID('DCHR'):
readResTypeList(rtCharset,MKID('CHAR'),"charset");
break;
case MKID('DOBJ'):
_numGlobalObjects = fileReadWordLE();
_objectFlagTable = (byte*)alloc(_numGlobalObjects);
if (mode==1) {
fileSeek(_fileHandle, itemsize - 10, 1);
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;
}
}
clearFileReadFailed(_fileHandle);
if (numblock!=8)
error("Not enough blocks read from directory");
openRoom(-1);
_numGlobalScripts = _maxScripts;
_dynamicRoomOffsets = true;
}
void Scumm::readIndexFileV6() {
void Scumm::readIndexFile() {
uint32 blocktype,itemsize;
int numblock = 0;
int num, i;
@ -254,6 +166,44 @@ void Scumm::readIndexFileV6() {
openRoom(-1);
openRoom(0);
if (!(_features & GF_AFTER_V6)) {
/* Figure out the sizes of various resources */
while (!fileEof(_fileHandle)) {
blocktype = fileReadDword();
itemsize = fileReadDwordBE();
if (fileReadFailed(_fileHandle))
break;
switch(blocktype) {
case MKID('DOBJ'):
_numGlobalObjects = fileReadWordLE();
itemsize-=2;
break;
case MKID('DROO'):
_numRooms = fileReadWordLE();
itemsize-=2;
break;
case MKID('DSCR'):
_numScripts = fileReadWordLE();
itemsize-=2;
break;
case MKID('DCOS'):
_numCostumes = fileReadWordLE();
itemsize-=2;
break;
case MKID('DSOU'):
_numSounds = fileReadWordLE();
itemsize-=2;
break;
}
fileSeek(_fileHandle, itemsize-8,SEEK_CUR);
}
clearFileReadFailed(_fileHandle);
fileSeek(_fileHandle, 0, SEEK_SET);
}
while (1) {
blocktype = fileReadDword();
@ -271,16 +221,31 @@ void Scumm::readIndexFileV6() {
case MKID('DOBJ'):
num = fileReadWordLE();
assert(num == _numGlobalObjects);
fileRead(_fileHandle, _objectFlagTable, num);
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,11 +825,28 @@ 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() {
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();
@ -837,32 +862,56 @@ void Scumm::readMAXS() {
_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);

View file

@ -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()) {

View file

@ -50,7 +50,6 @@ void Scumm::runScript(int script, int a, int b, int16 *lvarptr) {
scriptOffs = _localScriptList[script - _numGlobalScripts];
if (scriptOffs == 0)
error("Local script %d is not in room %d", script, _roomResource);
scriptOffs += 9;
scriptType = WIO_LOCAL;
}
@ -298,7 +297,7 @@ int Scumm::readVar(uint var) {
return _vars[var];
}
if (var&0x2000 && _majorScummVersion==5) {
if (var&0x2000 && !(_features&GF_NEW_OPCODES)) {
a = fetchScriptWord();
if (a&0x2000)
var = (var+readVar(a&~0x2000))&~0x2000;
@ -451,6 +450,7 @@ bool Scumm::isScriptInUse(int script) {
return false;
}
void Scumm::runHook(int i) {
int16 tmp[16];
tmp[0] = i;
@ -575,9 +575,9 @@ void Scumm::killScriptsAndResources() {
/* Nuke local object names */
if (_newNames) {
for (i=0; i<50; i++) {
for (i=0; i<_numNewNames; i++) {
int j = _newNames[i];
if (j && (getOwner(j)&OF_OWNER_MASK) == 0) {
if (j && getOwner(j) == 0) {
_newNames[i] = 0;
nukeResource(rtObjectName, i);
}
@ -597,31 +597,33 @@ void Scumm::checkAndRunVar33() {
return;
}
if (_sentenceIndex > 0x7F || sentence[_sentenceIndex].unk)
if (!_sentenceNum || sentence[_sentenceNum-1].unk)
return;
if (sentence[_sentenceIndex].unk2 &&
sentence[_sentenceIndex].unk3==sentence[_sentenceIndex].unk4) {
_sentenceIndex--;
return;
}
_sentenceNum--;
_localParamList[0] = sentence[_sentenceIndex].unk5;
_localParamList[1] = sentence[_sentenceIndex].unk4;
_localParamList[2] = sentence[_sentenceIndex].unk3;
_sentenceIndex--;
#if !defined(FULL_THROTTLE)
if (sentence[_sentenceNum].unk2 &&
sentence[_sentenceNum].unk3==sentence[_sentenceNum].unk4)
return;
#endif
_localParamList[0] = sentence[_sentenceNum].unk5;
_localParamList[1] = sentence[_sentenceNum].unk4;
_localParamList[2] = sentence[_sentenceNum].unk3;
_currentScript = 0xFF;
if (_vars[VAR_SENTENCE_SCRIPT])
runScript(_vars[VAR_SENTENCE_SCRIPT], 0, 0, _localParamList);
}
void Scumm::runInputScript(int a, int cmd, int mode) {
memset(_localParamList, 0, sizeof(_localParamList));
_localParamList[0] = a;
_localParamList[1] = cmd;
_localParamList[2] = mode;
int16 args[16];
memset(args, 0, sizeof(args));
args[0] = a;
args[1] = cmd;
args[2] = mode;
if (_vars[VAR_VERB_SCRIPT])
runScript(_vars[VAR_VERB_SCRIPT], 0, 0, _localParamList);
runScript(_vars[VAR_VERB_SCRIPT], 0, 0, args);
}
void Scumm::decreaseScriptDelay(int amount) {
@ -695,7 +697,7 @@ int Scumm::getVerbEntrypoint(int obj, int entry) {
objptr = getObjectAddress(obj);
assert(objptr);
verbptr = findResource(MKID('VERB'), objptr, 0);
verbptr = findResource(MKID('VERB'), objptr);
if (verbptr==NULL)
error("No verb block in object %d", obj);
@ -777,61 +779,93 @@ void Scumm::faceActorToObj(int act, int obj) {
if (getObjectOrActorXY(obj)==-1)
return;
dir = (_xPos > x) ? 1 : 0;
dir = (_xPos > x) ? 90 : 270;
turnToDirection(derefActorSafe(act, "faceActorToObj"), dir);
}
void Scumm::animateActor(int act, int anim) {
#if defined(FULL_THROTTLE)
int cmd,dir;
Actor *a;
a = derefActorSafe(act, "animateActor");
if (anim==0xFF)
anim = 2000;
cmd = anim / 1000;
dir = anim % 1000;
/* temporary code */
// dir = newDirToOldDir(dir);
switch(cmd) {
case 2:
stopActorMoving(a);
startAnimActor(a, a->standFrame);
break;
case 3:
a->moving &= ~4;
fixActorDirection(a, dir);
break;
case 4:
turnToDirection(a, dir);
break;
default:
startAnimActor(a, anim);
}
#else
int shr,dir;
bool inRoom;
Actor *a;
a = derefActorSafe(act, "animateActor");
shr = anim>>2;
dir = anim&3;
inRoom = (a->room == _currentRoom);
if (shr == 0x3F) {
if (inRoom) {
startAnimActor(a, a->standFrame, a->facing);
a->moving = 0;
}
return;
}
if (shr == 0x3E) {
if (inRoom) {
startAnimActor(a, 0x3E, dir);
switch(anim>>2) {
case 0x3F:
stopActorMoving(a);
startAnimActor(a, a->standFrame);
break;
case 0x3E:
a->moving &= ~4;
}
a->facing = dir;
return;
fixActorDirection(a, oldDirToNewDir(dir));
break;
case 0x3D:
turnToDirection(a, oldDirToNewDir(dir));
break;
default:
startAnimActor(a, anim);
}
if (shr == 0x3D) {
if (inRoom) {
turnToDirection(a, dir);
} else {
a->facing = dir;
}
return;
}
startAnimActor(a, anim, a->facing);
#endif
}
int Scumm::getScriptRunning(int script) {
bool Scumm::isScriptRunning(int script) {
int i;
ScriptSlot *ss = vm.slot;
for (i=0; 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;
@ -971,3 +1005,46 @@ void Scumm::exitCutscene() {
vm.cutScenePtr[vm.cutSceneStackPointer] = 0;
}
}
#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

View file

@ -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() {

View file

@ -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;
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;
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;
}
}
addObjectToInventory(obj, room);
putOwner(obj, _vars[VAR_EGO]);
putClass(obj, 32, 1);
@ -987,8 +1017,14 @@ void Scumm::o6_loadRoomWithEgo() {
y = pop();
x = pop();
if (_features & GF_HAS_ROOMTABLE) {
obj = pop();
room = getObjectRoom(obj);
} else {
room = pop();
obj = pop();
}
a = derefActorSafe(_vars[VAR_EGO], "o_loadRoomWithEgo");
@ -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();
@ -1464,8 +1512,21 @@ FixRooms:;
case 217:
initActor(a, 2);
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,6 +2360,7 @@ void Scumm::decodeParseString2(int m, int n) {
switch(m) {
case 0: actorTalk(); break;
case 1: drawString(1); break;
case 2: unkMessage1(); break;
case 3: unkMessage2(); break;
}

496
scumm.h
View file

@ -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,8 +1113,12 @@ 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();
@ -1682,9 +1927,128 @@ struct Scumm {
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);

View file

@ -23,31 +23,6 @@
#include "scumm.h"
#include "gui.h"
void Scumm::initThingsV5() {
readIndexFileV5(1);
_numVariables = 800;
_numBitVariables = 2048;
_numLocalObjects = 200;
_numVerbs = 100;
_numInventory = 80;
_numVerbs = 100;
_numArray = 0x32;
_numFlObject = 0x32;
allocateArrays();
readIndexFileV5(2);
initRandSeeds();
setupOpcodes();
}
void Scumm::initThingsV6() {
setupOpcodes2();
readIndexFileV6();
}
void Scumm::initRandSeeds() {
_randSeed1 = 0xA943DE35;
_randSeed2 = 0x37A9ED27;
@ -60,12 +35,17 @@ uint Scumm::getRandomNumber(uint max) {
return _randSeed1%max;
}
uint Scumm::getRandomNumberRng(uint min, uint max) {
return getRandomNumber(max-min+1)+min;
}
void Scumm::scummInit() {
int i;
Actor *a;
debug(9, "scummInit");
// readIndexFile(3);
loadCharset(1);
initScreens(0, 16, 320, 144);
@ -107,9 +87,10 @@ void Scumm::scummInit() {
virtscr[0].xstart = 0;
#if !defined(FULL_THROTTLE)
_vars[VAR_V5_DRAWFLAGS] = 11;
_vars[VAR_59] = 3;
#endif
mouse.x = 104;
mouse.y = 56;
@ -118,7 +99,7 @@ void Scumm::scummInit() {
_EXCD_offs = 0;
_currentScript = 0xFF;
_sentenceIndex = 0xFF;
_sentenceNum = 0;
_currentRoom = 0;
_numObjectsInRoom = 0;
@ -157,7 +138,7 @@ void Scumm::scummInit() {
initScummVars();
if (_majorScummVersion==5)
if (!(_features&GF_AFTER_V6))
_vars[VAR_V5_TALK_STRING_Y] = -0x50;
getGraphicsPerformance();
@ -165,6 +146,7 @@ void Scumm::scummInit() {
void Scumm::initScummVars() {
#if !defined(FULL_THROTTLE)
_vars[VAR_CURRENTDRIVE] = _currentDrive;
_vars[VAR_FIXEDDISK] = checkFixedDisk();
_vars[VAR_SOUNDCARD] = _soundCardType;
@ -174,8 +156,9 @@ void Scumm::initScummVars() {
_vars[VAR_SOUNDPARAM] = _soundParam;
_vars[VAR_SOUNDPARAM2] = _soundParam2;
_vars[VAR_SOUNDPARAM3] = _soundParam3;
if (_majorScummVersion==6)
if (_features&GF_AFTER_V6)
_vars[VAR_V6_EMSSPACE] = 10000;
#endif
}
void Scumm::checkRange(int max, int min, int no, const char *str) {
@ -206,7 +189,7 @@ void Scumm::scummMain(int argc, char **argv) {
if (!detectGame()) {
warning("Game detection failed. Using default settings");
_majorScummVersion = 5;
_features = GF_DEFAULT;
}
if (_gameId==GID_INDY4 && _bootParam==0) {
@ -217,17 +200,22 @@ void Scumm::scummMain(int argc, char **argv) {
_bootParam = 10001;
}
initGraphics(this, _fullScreen);
if (_majorScummVersion==6)
initThingsV6();
readIndexFile();
initRandSeeds();
if (_features & GF_NEW_OPCODES)
setupOpcodes2();
else
initThingsV5();
setupOpcodes();
scummInit();
#if !defined(FULL_THROTTLE)
_vars[VAR_VERSION] = 21;
#endif
_vars[VAR_DEBUGMODE] = _debugMode;
if (_gameId==GID_MONKEY) {
@ -259,7 +247,7 @@ int Scumm::scummLoop(int delta) {
processKbd();
_vars[VAR_CAMERA_CUR_POS] = camera._curPos;
_vars[VAR_CAMERA_POS_X] = camera._curPos;
_vars[VAR_HAVE_MSG] = _haveMsg;
_vars[VAR_VIRT_MOUSE_X] = _virtual_mouse_x;
_vars[VAR_VIRT_MOUSE_Y] = _virtual_mouse_y;
@ -318,11 +306,11 @@ int Scumm::scummLoop(int delta) {
setActorRedrawFlags();
resetActorBgs();
if (!(_vars[VAR_V5_DRAWFLAGS]&2) && _vars[VAR_V5_DRAWFLAGS]&4) {
error("Flashlight not implemented in this version");
}
// if (!(_vars[VAR_V5_DRAWFLAGS]&2) && _vars[VAR_V5_DRAWFLAGS]&4) {
// error("Flashlight not implemented in this version");
// }
processActors(); /* process actors makes the heap invalid */
processActors();
clear_fullRedraw();
cyclePalette();
palManipulate();
@ -343,7 +331,7 @@ int Scumm::scummLoop(int delta) {
drawDirtyScreenParts();
removeEnqueuedObjects();
if (_majorScummVersion==5)
if (!(_features&GF_AFTER_V6))
playActorSounds();
processSoundQues();
@ -359,17 +347,6 @@ int Scumm::scummLoop(int delta) {
}
#if 0
void Scumm::scummMain(int argc, char **argv) {
do {
updateScreen(this);
} while (1);
}
#endif
void Scumm::parseCommandLine(int argc, char **argv) {
int i;
char *s;
@ -415,17 +392,28 @@ struct VersionSettings {
const char *filename;
const char *gamename;
byte id,major,middle,minor;
uint32 features;
};
static const VersionSettings version_settings[] = {
{"monkey", "Monkey Island 1", GID_MONKEY, 5, 2, 2},
{"monkey2", "Monkey Island 2: LeChuck's revenge", GID_MONKEY2, 5, 2, 2},
{"atlantis", "Indiana Jones 4 and the Fate of Atlantis", GID_INDY4, 5, 5, 0},
{"playfate", "Indiana Jones 4 and the Fate of Atlantis (Demo)", GID_INDY4, 5, 5, 0},
{"tentacle", "Day Of The Tentacle", GID_TENTACLE, 6, 4, 2},
{"dottdemo", "Day Of The Tentacle (Demo)", GID_TENTACLE, 6, 3, 2},
{"samnmax", "Sam & Max", GID_SAMNMAX, 6, 4, 2},
{"snmdemo", "Sam & Max (Demo)", GID_SAMNMAX, 6, 3, 0},
{"monkey", "Monkey Island 1", GID_MONKEY, 5, 2, 2,
GF_USE_KEY},
{"monkey2", "Monkey Island 2: LeChuck's revenge", GID_MONKEY2, 5, 2, 2,
GF_USE_KEY},
{"atlantis", "Indiana Jones 4 and the Fate of Atlantis", GID_INDY4, 5, 5, 0,
GF_USE_KEY},
{"playfate", "Indiana Jones 4 and the Fate of Atlantis (Demo)", GID_INDY4, 5, 5, 0,
GF_USE_KEY},
{"tentacle", "Day Of The Tentacle", GID_TENTACLE, 6, 4, 2,
GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY},
{"dottdemo", "Day Of The Tentacle (Demo)", GID_TENTACLE, 6, 3, 2,
GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY},
{"samnmax", "Sam & Max", GID_SAMNMAX, 6, 4, 2,
GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY},
{"snmdemo", "Sam & Max (Demo)", GID_SAMNMAX, 6, 3, 0,
GF_NEW_OPCODES|GF_AFTER_V6|GF_USE_KEY},
{"ft", "Full Throttle", GID_SAMNMAX, 7, 3, 0,
GF_NEW_OPCODES|GF_AFTER_V6|GF_AFTER_V7},
{NULL,NULL}
};
@ -437,9 +425,10 @@ bool Scumm::detectGame() {
do {
if (!scumm_stricmp(_exe_name, gnl->filename)) {
_gameId = gnl->id;
_majorScummVersion = gnl->major;
_middleScummVersion = gnl->middle;
_minorScummVersion = gnl->minor;
// _majorScummVersion = gnl->major;
// _middleScummVersion = gnl->middle;
// _minorScummVersion = gnl->minor;
_features = gnl->features;
_gameText = gnl->gamename;
debug(1, "Detected game '%s', version %d.%d.%d",
gnl->gamename, gnl->major, gnl->middle, gnl->minor);
@ -535,7 +524,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) {
camera._mode = CM_NORMAL;
camera._curPos = camera._destPos = 160;
if (_majorScummVersion==6) {
if (_features&GF_AFTER_V6) {
_vars[VAR_V6_SCREEN_WIDTH] = _scrWidthIn8Unit<<3;
_vars[VAR_V6_SCREEN_HEIGHT] = _scrHeight;
}
@ -543,10 +532,10 @@ void Scumm::startScene(int room, Actor *a, int objectNr) {
if (_roomResource == 0)
return;
_vars[VAR_CAMERA_MAX] = (_scrWidthIn8Unit<<3) - 160;
_vars[VAR_CAMERA_MIN] = 160;
_vars[VAR_CAMERA_MAX_X] = (_scrWidthIn8Unit<<3) - 160;
_vars[VAR_CAMERA_MIN_X] = 160;
memset(actorDrawBits, 0, sizeof(actorDrawBits));
memset(gfxUsageBits, 0, sizeof(gfxUsageBits));
if (a) {
where = whereIsObject(objectNr);
@ -554,7 +543,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) {
error("startScene: Object %d is not in room %d", objectNr, _currentRoom);
getObjectXYPos(objectNr);
putActor(a, _xPos, _yPos, _currentRoom);
startAnimActor(a, 0x3E, _dir^1);
fixActorDirection(a, _dir + 180);
a->moving = 0;
}
@ -576,7 +565,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) {
void Scumm::initRoomSubBlocks() {
int i,offs;
byte *ptr;
byte *roomptr;
byte *roomptr,*searchptr;
_ENCD_offs = 0;
_EXCD_offs = 0;
@ -591,14 +580,14 @@ void Scumm::initRoomSubBlocks() {
roomptr = getResourceAddress(rtRoom, _roomResource);
ptr = findResource(MKID('RMHD'), roomptr, 0);
ptr = findResource(MKID('RMHD'), roomptr);
_scrWidthIn8Unit = READ_LE_UINT16(&((RoomHeader*)ptr)->width) >> 3;
_scrHeight = READ_LE_UINT16(&((RoomHeader*)ptr)->height);
_IM00_offs = findResource(MKID('IM00'), findResource(MKID('RMIM'), roomptr, 0), 0) -
roomptr;
_IM00_offs = findResource(MKID('IM00'), findResource(MKID('RMIM'), roomptr))
- roomptr;
ptr = findResource(MKID('EXCD'), roomptr, 0);
ptr = findResource(MKID('EXCD'), roomptr);
if (ptr) {
_EXCD_offs = ptr - roomptr;
#ifdef DUMP_SCRIPTS
@ -606,7 +595,7 @@ void Scumm::initRoomSubBlocks() {
#endif
}
ptr = findResource(MKID('ENCD'), roomptr, 0);
ptr = findResource(MKID('ENCD'), roomptr);
if (ptr) {
_ENCD_offs = ptr - roomptr;
#ifdef DUMP_SCRIPTS
@ -614,25 +603,25 @@ void Scumm::initRoomSubBlocks() {
#endif
}
ptr = findResource(MKID('BOXD'), roomptr, 0);
ptr = findResource(MKID('BOXD'), roomptr);
if (ptr) {
int size = READ_BE_UINT32_UNALIGNED(ptr+4);
createResource(rtMatrix, 2, size);
roomptr = getResourceAddress(rtRoom, _roomResource);
ptr = findResource(MKID('BOXD'), roomptr, 0);
ptr = findResource(MKID('BOXD'), roomptr);
memcpy(getResourceAddress(rtMatrix, 2), ptr, size);
}
ptr = findResource(MKID('BOXM'), roomptr, 0);
ptr = findResource(MKID('BOXM'), roomptr);
if (ptr) {
int size = READ_BE_UINT32_UNALIGNED(ptr+4);
createResource(rtMatrix, 1, size);
roomptr = getResourceAddress(rtRoom, _roomResource);
ptr = findResource(MKID('BOXM'), roomptr, 0);
ptr = findResource(MKID('BOXM'), roomptr);
memcpy(getResourceAddress(rtMatrix, 1), ptr, size);
}
ptr = findResource(MKID('SCAL'), roomptr, 0);
ptr = findResource(MKID('SCAL'), roomptr);
if (ptr) {
offs = ptr - roomptr;
for (i=1; i<_maxScaleTable; i++, offs+=8) {
@ -646,48 +635,59 @@ void Scumm::initRoomSubBlocks() {
}
}
}
memset(_localScriptList, 0, (0x100 - _numGlobalScripts) * 4);
memset(_localScriptList, 0, sizeof(_localScriptList));
roomptr = getResourceAddress(rtRoom, _roomResource);
for (i=0; ptr = findResource(MKID('LSCR'), roomptr, i++) ;) {
_localScriptList[ptr[8] - _numGlobalScripts] = ptr - roomptr;
searchptr = roomptr = getResourceAddress(rtRoom, _roomResource);
while( (ptr = findResource(MKID('LSCR'), searchptr)) != NULL ) {
int id;
#ifdef FULL_THROTTLE
id = READ_LE_UINT16(ptr + 8);
checkRange(2050, 2000, id, "Invalid local script %d");
_localScriptList[id - _numGlobalScripts] = ptr + 10 - roomptr;
#else
id = ptr[8];
_localScriptList[id - _numGlobalScripts] = ptr + 9 - roomptr;
#endif
#ifdef DUMP_SCRIPTS
do {
char buf[32];
sprintf(buf,"room-%d-",_roomResource);
dumpResource(buf, ptr[8], ptr);
dumpResource(buf, id, ptr);
} while (0);
#endif
searchptr = NULL;
}
ptr = findResource(MKID('EPAL'), roomptr, 0);
ptr = findResource(MKID('EPAL'), roomptr);
if (ptr)
_EPAL_offs = ptr - roomptr;
ptr = findResource(MKID('CLUT'), roomptr, 0);
ptr = findResource(MKID('CLUT'), roomptr);
if (ptr) {
_CLUT_offs = ptr - roomptr;
setPaletteFromRes();
}
if (_majorScummVersion==6) {
ptr = findResource(MKID('PALS'), roomptr, 0);
if (_features&GF_AFTER_V6) {
ptr = findResource(MKID('PALS'), roomptr);
if (ptr) {
_PALS_offs = ptr - roomptr;
setPalette(0);
}
}
initCycl(findResource(MKID('CYCL'), roomptr, 0) + 8);
initCycl(findResource(MKID('CYCL'), roomptr) + 8);
ptr = findResource(MKID('TRNS'), roomptr, 0);
ptr = findResource(MKID('TRNS'), roomptr);
if (ptr)
gdi._transparency = ptr[8];
else
gdi._transparency = 255;
initBGBuffers();
memset(_extraBoxFlags, 0, sizeof(_extraBoxFlags));
}
void Scumm::setScaleItem(int slot, int a, int b, int c, int d) {
@ -883,7 +883,9 @@ void Scumm::startManiac() {
void Scumm::destroy() {
freeResources();
free(_objectFlagTable);
free(_objectStateTable);
free(_objectRoomTable);
free(_objectOwnerTable);
free(_inventory);
free(_arrays);
free(_verbs);
@ -894,6 +896,45 @@ void Scumm::destroy() {
free(_classData);
}
int Scumm::newDirToOldDir(int dir) {
if (dir>=71 && dir<=109)
return 1;
if (dir>=109 && dir<=251)
return 2;
if (dir>=251 && dir<=289)
return 0;
return 3;
}
const int new_dir_table[4] = {
270,
90,
180,
0,
};
int Scumm::oldDirToNewDir(int dir) {
return new_dir_table[dir];
}
int Scumm::toSimpleDir(int dir) {
if (dir>=71 && dir<=109)
return 1;
if (dir>=109 && dir<=251)
return 2;
if (dir>=251 && dir<=289)
return 3;
return 0;
}
int Scumm::fromSimpleDir(int dir) {
return dir * 90;
}
int Scumm::normalizeAngle(int angle) {
return (angle+360)%360;
}
extern Scumm scumm;

View file

@ -66,7 +66,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "ALLOW_GDI" /Yu"stdafx.h" /FD /GZ /c
# SUBTRACT CPP /Fr
# ADD BASE RSC /l 0x41d /d "_DEBUG"
# ADD RSC /l 0x41d /d "_DEBUG"
@ -101,6 +101,10 @@ SOURCE=.\actor.cpp
# End Source File
# Begin Source File
SOURCE=.\akos.cpp
# End Source File
# Begin Source File
SOURCE=.\boxes.cpp
!IF "$(CFG)" == "scummvm - Win32 Release"
@ -115,15 +119,6 @@ SOURCE=.\boxes.cpp
# Begin Source File
SOURCE=.\costume.cpp
!IF "$(CFG)" == "scummvm - Win32 Release"
# ADD CPP /Gd
!ELSEIF "$(CFG)" == "scummvm - Win32 Debug"
!ENDIF
# End Source File
# Begin Source File
@ -252,10 +247,6 @@ SOURCE=.\scummvm.cpp
# End Source File
# Begin Source File
SOURCE=.\sdl.cpp
# End Source File
# Begin Source File
SOURCE=.\sound.cpp
!IF "$(CFG)" == "scummvm - Win32 Release"
@ -320,6 +311,10 @@ SOURCE=.\verbs.cpp
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\windows.cpp
# End Source File
# End Group
# Begin Group "Header Files"

View file

@ -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;

View file

@ -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) {

View file

@ -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);
findObjectInRoom(&foir, foImageHeader, object, room);
size = READ_BE_UINT32_UNALIGNED(foir.obim+4);
createResource(rtVerb, verb, size);
obimptr = getResourceAddress(rtRoom, room) + imoffs;
obimptr = getResourceAddress(rtRoom, room) - foir.roomptr + foir.obim;
memcpy(getResourceAddress(rtVerb, verb), obimptr, size);
return;
}
}
error("Image %d not found in room %d", object, room);
}

View file

@ -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);