Initial revision
svn-id: r3408
This commit is contained in:
commit
c30932afbe
25 changed files with 13405 additions and 0 deletions
26
Makefile
Normal file
26
Makefile
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -g -O2 -Wno-multichar
|
||||||
|
DEFINES = -DUNIX -DSCUMM_BIG_ENDIAN -DSCUMM_NEED_ALIGNMENT
|
||||||
|
LDFLAGS = `sdl-config --libs`
|
||||||
|
INCLUDES= `sdl-config --cflags`
|
||||||
|
CPPFLAGS= $(DEFINES) $(INCLUDES)
|
||||||
|
|
||||||
|
INCS = scumm.h scummsys.h stdafx.h
|
||||||
|
|
||||||
|
OBJS = actor.o boxes.o costume.o gfx.o object.o resource.o \
|
||||||
|
saveload.o script.o scummvm.o sound.o string.o \
|
||||||
|
sys.o verbs.o sdl.o
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(<)
|
||||||
|
|
||||||
|
all: scummvm
|
||||||
|
|
||||||
|
scummvm: $(OBJS)
|
||||||
|
$(CC) $(LDFLAGS) -o $(@) $(OBJS) $(LIBS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJS) scummvm
|
||||||
|
|
||||||
|
check:
|
||||||
|
$(OBJS): $(INCS)
|
953
actor.cpp
Normal file
953
actor.cpp
Normal file
|
@ -0,0 +1,953 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:14 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
void Scumm::initActor(Actor *a, int mode) {
|
||||||
|
if (mode) {
|
||||||
|
a->facing = 2;
|
||||||
|
a->costume = 0;
|
||||||
|
a->room = 0;
|
||||||
|
a->x = 0;
|
||||||
|
a->y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->elevation = 0;
|
||||||
|
a->width = 0x18;
|
||||||
|
a->talkColor = 0xF;
|
||||||
|
a->scaley = a->scalex = 0xFF;
|
||||||
|
a->charset = 0;
|
||||||
|
a->sound = 0;
|
||||||
|
a->moving = 0;
|
||||||
|
|
||||||
|
setActorWalkSpeed(a, 8, 2);
|
||||||
|
|
||||||
|
a->ignoreBoxes = 0;
|
||||||
|
a->neverZClip = 0;
|
||||||
|
a->initFrame = 1;
|
||||||
|
a->walkFrame = 2;
|
||||||
|
a->standFrame = 3;
|
||||||
|
a->talkFrame1 = 4;
|
||||||
|
a->talkFrame2 = 5;
|
||||||
|
|
||||||
|
_classData[a->number] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::setActorWalkSpeed(Actor *a, int speedx, int speedy) {
|
||||||
|
if (speedx == a->speedx && speedy == a->speedy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
a->speedx = speedx;
|
||||||
|
a->speedy = speedy;
|
||||||
|
|
||||||
|
if (a->moving) {
|
||||||
|
calcMovementFactor(a, a->walkdata.newx, a->walkdata.newy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::calcMovementFactor(Actor *a, int newX, int newY) {
|
||||||
|
int actorX, actorY;
|
||||||
|
int diffX, diffY;
|
||||||
|
int32 XYFactor, YXFactor;
|
||||||
|
int32 tmp;
|
||||||
|
|
||||||
|
actorX = a->x;
|
||||||
|
actorY = a->y;
|
||||||
|
|
||||||
|
if (actorX == newX && actorY == newY)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
diffX = newX - actorX;
|
||||||
|
diffY = newY - actorY;
|
||||||
|
YXFactor = a->speedy<<16;
|
||||||
|
|
||||||
|
if (diffY < 0)
|
||||||
|
YXFactor = -YXFactor;
|
||||||
|
|
||||||
|
if (diffY != 0) {
|
||||||
|
XYFactor = YXFactor * diffX / diffY;
|
||||||
|
} else {
|
||||||
|
XYFactor = YXFactor * diffX;
|
||||||
|
YXFactor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = XYFactor >> 16;
|
||||||
|
if (tmp<0)
|
||||||
|
tmp = -tmp;
|
||||||
|
|
||||||
|
if (tmp > a->speedx) {
|
||||||
|
XYFactor = a->speedx<<16;
|
||||||
|
if (diffX < 0)
|
||||||
|
XYFactor = -XYFactor;
|
||||||
|
|
||||||
|
if (diffX != 0) {
|
||||||
|
YXFactor = XYFactor * diffY / diffX;
|
||||||
|
} else {
|
||||||
|
YXFactor = XYFactor * diffY;
|
||||||
|
XYFactor = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a->walkdata.x = actorX;
|
||||||
|
a->walkdata.y = actorY;
|
||||||
|
a->walkdata.newx = newX;
|
||||||
|
a->walkdata.newy = newY;
|
||||||
|
a->walkdata.XYFactor = XYFactor;
|
||||||
|
a->walkdata.YXFactor = YXFactor;
|
||||||
|
a->walkdata.xfrac = 0;
|
||||||
|
a->walkdata.yfrac = 0;
|
||||||
|
|
||||||
|
return actorWalkStep(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::actorWalkStep(Actor *a) {
|
||||||
|
int32 XYFactor, YXFactor;
|
||||||
|
int actorX, actorY, newx, newy;
|
||||||
|
int newXDist;
|
||||||
|
int32 tmp,tmp2;
|
||||||
|
|
||||||
|
byte direction;
|
||||||
|
|
||||||
|
a->needRedraw = true;
|
||||||
|
a->needBgReset = true;
|
||||||
|
|
||||||
|
XYFactor = a->walkdata.XYFactor;
|
||||||
|
YXFactor = a->walkdata.YXFactor;
|
||||||
|
|
||||||
|
direction = XYFactor>0 ? 1 : 0;
|
||||||
|
if (abs(YXFactor) * 3 > abs(XYFactor))
|
||||||
|
direction = YXFactor>0 ? 2 : 3;
|
||||||
|
a->newDirection = direction;
|
||||||
|
|
||||||
|
direction = getProgrDirChange(a, 1);
|
||||||
|
|
||||||
|
if (!(a->moving&2) || a->facing!=direction) {
|
||||||
|
if (a->walkFrame != a->animIndex || a->facing != direction) {
|
||||||
|
startAnimActor(a, a->walkFrame, direction);
|
||||||
|
}
|
||||||
|
a->moving|=2;
|
||||||
|
}
|
||||||
|
|
||||||
|
actorX = a->walkdata.x;
|
||||||
|
actorY = a->walkdata.y;
|
||||||
|
newx = a->walkdata.newx;
|
||||||
|
newy = a->walkdata.newy;
|
||||||
|
|
||||||
|
if (a->walkbox != a->walkdata.curbox) {
|
||||||
|
if (checkXYInBoxBounds(a->walkdata.curbox, a->x, a->y)) {
|
||||||
|
a->walkbox = a->walkdata.curbox;
|
||||||
|
a->mask = getMaskFromBox(a->walkdata.curbox);
|
||||||
|
setupActorScale(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newXDist = abs(newx - actorX);
|
||||||
|
|
||||||
|
if (newXDist <= abs(a->x - actorX) &&
|
||||||
|
abs(newy - actorY) <= abs(a->y - actorY) ){
|
||||||
|
a->moving&=~2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
XYFactor = (XYFactor>>8) * a->scalex;
|
||||||
|
YXFactor = (YXFactor>>8) * a->scalex;
|
||||||
|
|
||||||
|
tmp = ((a->x + 8000)<<16) + a->walkdata.xfrac + XYFactor;
|
||||||
|
tmp2 = (a->y<<16) + a->walkdata.yfrac + YXFactor;
|
||||||
|
|
||||||
|
a->x = (tmp>>16)-8000;
|
||||||
|
a->y = tmp2>>16;
|
||||||
|
|
||||||
|
if (abs(a->x - actorX) > newXDist) {
|
||||||
|
a->x = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::setupActorScale(Actor *a) {
|
||||||
|
uint16 scale;
|
||||||
|
byte *resptr;
|
||||||
|
|
||||||
|
if (a->ignoreBoxes != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scale = getBoxScale(a->walkbox);
|
||||||
|
|
||||||
|
if (scale & 0x8000) {
|
||||||
|
scale = (scale&0x7FFF)+1;
|
||||||
|
resptr = getResourceAddress(0xB, scale);
|
||||||
|
if (resptr==NULL)
|
||||||
|
error("Scale table %d not defined",scale);
|
||||||
|
if (a->y >= 0)
|
||||||
|
resptr += a->y;
|
||||||
|
scale = *resptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scale>255)
|
||||||
|
error("Actor %d at %d, scale %d out of range", a->number, a->y, scale);
|
||||||
|
|
||||||
|
a->scalex = (byte)scale;
|
||||||
|
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 ((flags&0x10) || getClass(a->number, 0x1D)) {
|
||||||
|
if (newdir&2)
|
||||||
|
newdir^=1;
|
||||||
|
YXflag = 1 - YXflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (frame==0x38)
|
||||||
|
frame = a->initFrame;
|
||||||
|
|
||||||
|
if (frame==0x39)
|
||||||
|
frame = a->walkFrame;
|
||||||
|
|
||||||
|
if (frame==0x3A)
|
||||||
|
frame = a->standFrame;
|
||||||
|
|
||||||
|
if (frame==0x3B)
|
||||||
|
frame = a->talkFrame1;
|
||||||
|
|
||||||
|
if (frame==0x3C)
|
||||||
|
frame = a->talkFrame2;
|
||||||
|
|
||||||
|
if (a->room == _currentRoom && a->costume) {
|
||||||
|
a->animProgress = 0;
|
||||||
|
a->cost.animCounter1 = 0;
|
||||||
|
a->needRedraw = true;
|
||||||
|
|
||||||
|
cost.loadCostume(a->costume);
|
||||||
|
|
||||||
|
if (a->initFrame==frame)
|
||||||
|
initActorCostumeData(a);
|
||||||
|
|
||||||
|
if (frame!=0x3E) {
|
||||||
|
decodeCostData(a, frame*4 + direction, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->facing != direction)
|
||||||
|
fixActorDirection(a, direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
a->facing = direction;
|
||||||
|
a->needBgReset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
uint mask;
|
||||||
|
int i;
|
||||||
|
uint16 vald;
|
||||||
|
|
||||||
|
if (a->facing == direction)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mask = 0x8000;
|
||||||
|
for (i=0; i<16; i++,mask>>=1) {
|
||||||
|
vald = a->cost.d[i];
|
||||||
|
if (vald==0xFFFF || (vald&3)==direction)
|
||||||
|
continue;
|
||||||
|
decodeCostData(a, (vald&0xFC)|direction, mask);
|
||||||
|
}
|
||||||
|
a->facing = direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::decodeCostData(Actor *a, int frame, uint usemask) {
|
||||||
|
byte *p,*r;
|
||||||
|
uint mask,j;
|
||||||
|
int i;
|
||||||
|
byte extra,cmd;
|
||||||
|
byte *dataptr;
|
||||||
|
|
||||||
|
p = cost._ptr;
|
||||||
|
if (frame > p[6])
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::putActor(Actor *a, int x, int y, byte room) {
|
||||||
|
if (a->visible && _currentRoom!=room && vm.vars[VAR_TALK_ACTOR]==a->number) {
|
||||||
|
clearMsgQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
a->x = x;
|
||||||
|
a->y = y;
|
||||||
|
a->room = room;
|
||||||
|
a->needRedraw = true;
|
||||||
|
a->needBgReset = true;
|
||||||
|
|
||||||
|
if (vm.vars[VAR_UNK_ACTOR]==a->number) {
|
||||||
|
dseg_3A76 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->visible) {
|
||||||
|
if (_currentRoom == room) {
|
||||||
|
if (a->moving) {
|
||||||
|
startAnimActor(a, a->standFrame, a->facing);
|
||||||
|
a->moving = 0;
|
||||||
|
}
|
||||||
|
adjustActorPos(a);
|
||||||
|
} else {
|
||||||
|
hideActor(a);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_currentRoom == room)
|
||||||
|
showActor(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getActorXYPos(Actor *a) {
|
||||||
|
if (a->room != _currentRoom)
|
||||||
|
return -1;
|
||||||
|
_xPos = a->x;
|
||||||
|
_yPos = a->y;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdjustBoxResult Scumm::adjustXYToBeInBox(Actor *a, int x, int y) {
|
||||||
|
AdjustBoxResult abr,tmp;
|
||||||
|
int threshold;
|
||||||
|
uint best;
|
||||||
|
int box;
|
||||||
|
byte flags, b;
|
||||||
|
|
||||||
|
if (a && a->ignoreBoxes==0) {
|
||||||
|
threshold = 30;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
box = getNumBoxes() - 1;
|
||||||
|
best = (uint)0xFFFF;
|
||||||
|
b = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
flags = getBoxFlags(box);
|
||||||
|
if (flags&0x80 && (!(flags&0x20) || getClass(a->number, 0x1F)) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!inBoxQuickReject(box, x, y, threshold))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (checkXYInBoxBounds(box, x, y)) {
|
||||||
|
abr.x = x;
|
||||||
|
abr.y = y;
|
||||||
|
abr.dist = box;
|
||||||
|
return abr;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = getClosestPtOnBox(box, x, y);
|
||||||
|
|
||||||
|
if (tmp.dist >= best)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
abr.x = tmp.x;
|
||||||
|
abr.y = tmp.y;
|
||||||
|
|
||||||
|
if (tmp.dist==0) {
|
||||||
|
abr.dist = box;
|
||||||
|
return abr;
|
||||||
|
}
|
||||||
|
best = tmp.dist;
|
||||||
|
b = box;
|
||||||
|
} while (--box);
|
||||||
|
|
||||||
|
if (threshold==0 || threshold * threshold >= best) {
|
||||||
|
abr.dist = b;
|
||||||
|
return abr;
|
||||||
|
}
|
||||||
|
threshold = (threshold==30) ? 80 : 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
abr.x = x;
|
||||||
|
abr.y = y;
|
||||||
|
abr.dist = 0;
|
||||||
|
}
|
||||||
|
return abr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::adjustActorPos(Actor *a) {
|
||||||
|
AdjustBoxResult abr;
|
||||||
|
byte flags;
|
||||||
|
|
||||||
|
abr = adjustXYToBeInBox(a, a->x, a->y);
|
||||||
|
|
||||||
|
a->x = abr.x;
|
||||||
|
a->y = abr.y;
|
||||||
|
a->walkbox = abr.dist; /* not a dist */
|
||||||
|
a->walkdata.destbox = abr.dist;
|
||||||
|
a->mask = getMaskFromBox(abr.dist);
|
||||||
|
a->walkdata.destx = -1;
|
||||||
|
setupActorScale(a);
|
||||||
|
|
||||||
|
a->moving = 0;
|
||||||
|
a->cost.animCounter2 = 0;
|
||||||
|
|
||||||
|
flags = getBoxFlags(a->walkbox);
|
||||||
|
if (flags&7) {
|
||||||
|
turnToDirection(a, a->facing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::hideActor(Actor *a) {
|
||||||
|
if (!a->visible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (a->moving) {
|
||||||
|
startAnimActor(a, a->standFrame, a->facing);
|
||||||
|
a->moving = 0;
|
||||||
|
}
|
||||||
|
a->visible = false;
|
||||||
|
a->cost.animCounter2 = 0;
|
||||||
|
a->needRedraw = false;
|
||||||
|
a->needBgReset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::turnToDirection(Actor *a, int newdir) {
|
||||||
|
a->moving = 4;
|
||||||
|
a->newDirection = newdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::showActor(Actor *a) {
|
||||||
|
if (_currentRoom == 0 || a->visible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
adjustActorPos(a);
|
||||||
|
|
||||||
|
ensureResourceLoaded(3, a->costume);
|
||||||
|
|
||||||
|
if (a->costumeNeedsInit) {
|
||||||
|
startAnimActor(a, a->initFrame, a->facing);
|
||||||
|
a->costumeNeedsInit = false;
|
||||||
|
}
|
||||||
|
a->moving = 0;
|
||||||
|
a->visible = true;
|
||||||
|
a->needRedraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::showActors() {
|
||||||
|
int i;
|
||||||
|
Actor *a;
|
||||||
|
|
||||||
|
for (i=1; i<13; i++) {
|
||||||
|
a = derefActor(i);
|
||||||
|
if (a->room == _currentRoom)
|
||||||
|
showActor(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::stopTalk() {
|
||||||
|
int act;
|
||||||
|
|
||||||
|
_haveMsg = 0;
|
||||||
|
_talkDelay = 0;
|
||||||
|
|
||||||
|
act = vm.vars[VAR_TALK_ACTOR];
|
||||||
|
if (act && act<0x80) {
|
||||||
|
Actor *a = derefActorSafe(act, "stopTalk");
|
||||||
|
if (_currentRoom == a->room) {
|
||||||
|
startAnimActor(a, a->talkFrame2, a->facing);
|
||||||
|
}
|
||||||
|
vm.vars[VAR_TALK_ACTOR] = 0xFF;
|
||||||
|
}
|
||||||
|
_keepText = false;
|
||||||
|
restoreCharsetBg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::clearMsgQueue() {
|
||||||
|
_messagePtr = (byte*)" ";
|
||||||
|
stopTalk();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::walkActors() {
|
||||||
|
int i;
|
||||||
|
Actor *a;
|
||||||
|
for (i=1; i<13; i++) {
|
||||||
|
a = derefActor(i);
|
||||||
|
if (a->room==_currentRoom)
|
||||||
|
walkActor(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::playActorSounds() {
|
||||||
|
int i;
|
||||||
|
Actor *a;
|
||||||
|
|
||||||
|
for (i=1; i<13; i++) {
|
||||||
|
a = derefActor(i);
|
||||||
|
if (a->cost.animCounter2 && a->room==_currentRoom && a->sound) {
|
||||||
|
_currentScript = 0xFF;
|
||||||
|
addSoundToQueue(a->sound);
|
||||||
|
for (i=1; i<13; i++) {
|
||||||
|
a = derefActor(i);
|
||||||
|
a->cost.animCounter2 = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::walkActor(Actor *a) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if (!a->moving)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(a->moving&1)) {
|
||||||
|
if (a->moving&2 && actorWalkStep(a))
|
||||||
|
return;
|
||||||
|
|
||||||
|
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;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->moving&4) {
|
||||||
|
j = getProgrDirChange(a, 0);
|
||||||
|
if (a->facing != j)
|
||||||
|
startAnimActor(a, 0x3E, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
a->moving&=~1;
|
||||||
|
if (!a->walkbox) {
|
||||||
|
a->walkbox = a->walkdata.destbox;
|
||||||
|
a->walkdata.curbox = a->walkdata.destbox;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (a->walkbox == a->walkdata.destbox)
|
||||||
|
break;
|
||||||
|
j = getPathToDestBox(a->walkbox,a->walkdata.destbox);
|
||||||
|
if (j==0) {
|
||||||
|
a->walkdata.destbox = a->walkbox;
|
||||||
|
a->moving |= 8;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
a->walkdata.curbox = j;
|
||||||
|
if (findPathTowards(a, a->walkbox, j, a->walkdata.destbox))
|
||||||
|
break;
|
||||||
|
if (calcMovementFactor(a, _foundPathX, _foundPathY))
|
||||||
|
return;
|
||||||
|
|
||||||
|
a->walkbox = a->walkdata.curbox;
|
||||||
|
a->mask = getMaskFromBox(a->walkdata.curbox);
|
||||||
|
setupActorScale(a);
|
||||||
|
} while (1);
|
||||||
|
a->moving |= 8;
|
||||||
|
calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::processActors() {
|
||||||
|
int i;
|
||||||
|
Actor *actors[13],*a,**ac,**ac2,*tmp;
|
||||||
|
int numactors = 0, cnt,cnt2;
|
||||||
|
|
||||||
|
for (i=1; i<13; i++) {
|
||||||
|
a = derefActor(i);
|
||||||
|
if (a->room == _currentRoom)
|
||||||
|
actors[numactors++] = a;
|
||||||
|
}
|
||||||
|
if (!numactors)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ac = actors;
|
||||||
|
cnt = numactors;
|
||||||
|
do {
|
||||||
|
ac2 = actors;
|
||||||
|
cnt2 = numactors;
|
||||||
|
do {
|
||||||
|
if ( (*ac2)->y > (*ac)->y ) {
|
||||||
|
tmp = *ac;
|
||||||
|
*ac = *ac2;
|
||||||
|
*ac2 = tmp;
|
||||||
|
}
|
||||||
|
} while (ac2++, --cnt2);
|
||||||
|
} while (ac++,--cnt);
|
||||||
|
|
||||||
|
ac = actors;
|
||||||
|
cnt = numactors;
|
||||||
|
do {
|
||||||
|
a = *ac;
|
||||||
|
if (a->costume) {
|
||||||
|
setupActorScale(a);
|
||||||
|
setupCostumeRenderer(&cost, a);
|
||||||
|
setActorCostPalette(a);
|
||||||
|
checkHeap();
|
||||||
|
drawActorCostume(a);
|
||||||
|
checkHeap();
|
||||||
|
actorAnimate(a);
|
||||||
|
}
|
||||||
|
} while (ac++,--cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::setupCostumeRenderer(CostumeRenderer *c, Actor *a) {
|
||||||
|
c->_actorX = a->x - virtscr->xstart;
|
||||||
|
c->_actorY = a->y - a->elevation;
|
||||||
|
c->_zbuf = a->mask;
|
||||||
|
if (c->_zbuf > _numZBuffer)
|
||||||
|
c->_zbuf = _numZBuffer;
|
||||||
|
if (a->neverZClip)
|
||||||
|
c->_zbuf = a->neverZClip;
|
||||||
|
|
||||||
|
c->_scaleX = a->scalex;
|
||||||
|
c->_scaleY = a->scaley;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::setActorCostPalette(Actor *a) {
|
||||||
|
int i;
|
||||||
|
byte color;
|
||||||
|
|
||||||
|
cost.loadCostume(a->costume);
|
||||||
|
|
||||||
|
for (i=0; i<cost._numColors; i++) {
|
||||||
|
color = a->palette[i];
|
||||||
|
if (color==255)
|
||||||
|
color = cost._ptr[8+i];
|
||||||
|
cost._palette[i] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::drawActorCostume(Actor *a) {
|
||||||
|
if (a==NULL || !a->needRedraw)
|
||||||
|
return;
|
||||||
|
|
||||||
|
a->top = 0xFF;
|
||||||
|
a->needRedraw = 0;
|
||||||
|
a->bottom = 0;
|
||||||
|
cost.loadCostume(a->costume);
|
||||||
|
cost._mirror = a->facing!=0 || (cost._ptr[7]&0x80);
|
||||||
|
|
||||||
|
if (cost.drawCostume(a)) {
|
||||||
|
a->needRedraw = true;
|
||||||
|
a->needBgReset = true;;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::actorAnimate(Actor *a) {
|
||||||
|
if (a==NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
a->animProgress++;
|
||||||
|
if (a->animProgress >= a->animSpeed) {
|
||||||
|
a->animProgress = 0;
|
||||||
|
cost.loadCostume(a->costume);
|
||||||
|
if (cost.animate(&a->cost)) {
|
||||||
|
a->needRedraw = true;
|
||||||
|
a->needBgReset = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::setActorRedrawFlags() {
|
||||||
|
int i,j;
|
||||||
|
int bits;
|
||||||
|
|
||||||
|
for (i=0; i<40; i++) {
|
||||||
|
bits = actorDrawBits[_screenStartStrip+i];
|
||||||
|
if (bits&0x3FFF) {
|
||||||
|
for(j=0; j<13; j++) {
|
||||||
|
if ((bits&(1<<j)) && bits!=(1<<j)) {
|
||||||
|
Actor *a = derefActor(j);
|
||||||
|
a->needRedraw = true;
|
||||||
|
a->needBgReset = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getActorFromPos(int x, int y) {
|
||||||
|
uint16 drawbits;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
drawbits = actorDrawBits[x>>3];
|
||||||
|
if (!(drawbits & 0x3FFF))
|
||||||
|
return 0;
|
||||||
|
for (i=1; i<13; i++) {
|
||||||
|
Actor *a = derefActor(i);
|
||||||
|
if (drawbits&(1<<i) && !getClass(i, 32) && y >= a->top && y <= a->bottom) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::actorTalk() {
|
||||||
|
int oldact;
|
||||||
|
Actor *a;
|
||||||
|
|
||||||
|
_msgPtrToAdd = charset._buffer;
|
||||||
|
_messagePtr = addMessageToStack(_messagePtr);
|
||||||
|
|
||||||
|
if (_actorToPrintStrFor==0xFF) {
|
||||||
|
if (!_keepText)
|
||||||
|
stopTalk();
|
||||||
|
vm.vars[VAR_TALK_ACTOR] = 0xFF;
|
||||||
|
oldact = 0;
|
||||||
|
} else {
|
||||||
|
a = derefActorSafe(_actorToPrintStrFor, "actorTalk");
|
||||||
|
if (a->room!=_currentRoom) {
|
||||||
|
oldact = 0xFF;
|
||||||
|
} else {
|
||||||
|
if (!_keepText)
|
||||||
|
stopTalk();
|
||||||
|
vm.vars[VAR_TALK_ACTOR] = a->number;
|
||||||
|
startAnimActor(a,a->talkFrame1,a->facing);
|
||||||
|
oldact = vm.vars[VAR_TALK_ACTOR];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (oldact>=0x80)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vm.vars[VAR_TALK_ACTOR]>0x7F) {
|
||||||
|
_charsetColor = _stringColor[0];
|
||||||
|
} else {
|
||||||
|
a = derefActorSafe(vm.vars[VAR_TALK_ACTOR], "actorTalk(2)");
|
||||||
|
_charsetColor = a->talkColor;
|
||||||
|
}
|
||||||
|
charset._bufPos = 0;
|
||||||
|
_talkDelay = 0;
|
||||||
|
_haveMsg = 0xFF;
|
||||||
|
vm.vars[VAR_HAVE_MSG] = 0xFF;
|
||||||
|
CHARSET_1();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::setActorCostume(Actor *a, int c) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
a->costumeNeedsInit = true;
|
||||||
|
|
||||||
|
if (a->visible) {
|
||||||
|
hideActor(a);
|
||||||
|
initActorCostumeData(a);
|
||||||
|
a->costume = c;
|
||||||
|
showActor(a);
|
||||||
|
} else {
|
||||||
|
a->costume = c;
|
||||||
|
initActorCostumeData(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<32; i++)
|
||||||
|
a->palette[i] = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::startWalkActor(Actor *a, int x, int y, int dir) {
|
||||||
|
AdjustBoxResult abr;
|
||||||
|
|
||||||
|
abr = adjustXYToBeInBox(a, x, y);
|
||||||
|
|
||||||
|
_xPos = abr.x;
|
||||||
|
_yPos = abr.y;
|
||||||
|
|
||||||
|
if (a->room != _currentRoom) {
|
||||||
|
a->x = _xPos;
|
||||||
|
a->y = _yPos;
|
||||||
|
if (dir != 0xFF)
|
||||||
|
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;
|
||||||
|
abr.dist = a->walkdata.destbox;
|
||||||
|
} else {
|
||||||
|
abr = adjustXYToBeInBox(a, _xPos, _yPos);
|
||||||
|
}
|
||||||
|
if (a->moving && a->walkdata.destdir == dir
|
||||||
|
&& a->walkdata.destx == abr.x
|
||||||
|
&& a->walkdata.desty == abr.y)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->x==abr.x && a->y==abr.y) {
|
||||||
|
if (dir!=0xFF && dir!=a->facing) {
|
||||||
|
a->newDirection = dir;
|
||||||
|
a->moving = 4;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->walkdata.destx = abr.x;
|
||||||
|
a->walkdata.desty = abr.y;
|
||||||
|
a->walkdata.destbox = abr.dist; /* a box */
|
||||||
|
a->walkdata.destdir = dir;
|
||||||
|
a->moving = (a->moving&2)|1;
|
||||||
|
a->walkdata.curbox = a->walkbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *Scumm::getActorName(Actor *a) {
|
||||||
|
byte *ptr = getResourceAddress(9, a->number);
|
||||||
|
if(ptr==NULL)
|
||||||
|
return (byte*)" ";
|
||||||
|
return ptr;
|
||||||
|
}
|
839
boxes.cpp
Normal file
839
boxes.cpp
Normal file
|
@ -0,0 +1,839 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:14 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
byte Scumm::getMaskFromBox(int box) {
|
||||||
|
Box *ptr = getBoxBaseAddr(box);
|
||||||
|
return ptr->mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte Scumm::getBoxFlags(int box) {
|
||||||
|
Box *ptr = getBoxBaseAddr(box);
|
||||||
|
return ptr->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getBoxScale(int box) {
|
||||||
|
Box *ptr = getBoxBaseAddr(box);
|
||||||
|
return FROM_LE_16(ptr->scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte Scumm::getNumBoxes() {
|
||||||
|
byte *ptr = getResourceAddress(0xE, 2);
|
||||||
|
return ptr[8];
|
||||||
|
}
|
||||||
|
|
||||||
|
Box *Scumm::getBoxBaseAddr(int box) {
|
||||||
|
byte *ptr = getResourceAddress(0xE, 2);
|
||||||
|
checkRange(ptr[8]-1, 0, box, "Illegal box %d");
|
||||||
|
return (Box*)(ptr + box*SIZEOF_BOX + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scumm::checkXYInBoxBounds(int b, int x, int y) {
|
||||||
|
if (b==0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
getBoxCoordinates(b);
|
||||||
|
|
||||||
|
if (x < box.upperLeftX && x < box.upperRightX &&
|
||||||
|
x < box.lowerLeftX && x < box.lowerRightX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (x > box.upperLeftX && x > box.upperRightX &&
|
||||||
|
x > box.lowerLeftX && x > box.lowerRightX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (y < box.upperLeftY && y < box.upperRightY &&
|
||||||
|
y < box.lowerLeftY && y < box.lowerRightY)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (y > box.upperLeftY && y > box.upperRightY &&
|
||||||
|
y > box.lowerLeftY && y > box.lowerRightY)
|
||||||
|
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) {
|
||||||
|
|
||||||
|
Point pt;
|
||||||
|
pt = closestPtOnLine(box.upperLeftX, box.upperLeftY, box.lowerLeftX, box.lowerLeftY, 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))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!getSideOfLine(
|
||||||
|
box.upperRightX, box.upperRightY, box.lowerLeftX, box.lowerLeftY, x,y,b))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!getSideOfLine(
|
||||||
|
box.lowerLeftX, box.lowerLeftY, box.lowerRightX, box.lowerRightY, x,y,b))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!getSideOfLine(
|
||||||
|
box.lowerRightX, box.lowerRightY, box.upperLeftX, box.upperLeftY, x,y,b))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::getBoxCoordinates(int b) {
|
||||||
|
Box *bp = getBoxBaseAddr(b);
|
||||||
|
box.upperLeftX = FROM_LE_16(bp->ulx);
|
||||||
|
box.upperRightX = FROM_LE_16(bp->urx);
|
||||||
|
box.lowerLeftX = FROM_LE_16(bp->llx);
|
||||||
|
box.lowerRightX = FROM_LE_16(bp->lrx);
|
||||||
|
box.upperLeftY = FROM_LE_16(bp->uly);
|
||||||
|
box.upperRightY = FROM_LE_16(bp->ury);
|
||||||
|
box.lowerLeftY = FROM_LE_16(bp->lly);
|
||||||
|
box.lowerRightY = FROM_LE_16(bp->lry);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Scumm::distanceFromPt(int x, int y, int ptx, int pty) {
|
||||||
|
int diffx, diffy;
|
||||||
|
|
||||||
|
diffx = ptx - x;
|
||||||
|
if (ptx < x) diffx = x - ptx;
|
||||||
|
|
||||||
|
if (diffx >= 0x100)
|
||||||
|
return 0xFFFF;
|
||||||
|
|
||||||
|
diffy = pty - y;
|
||||||
|
if (pty < y) diffy = y - pty;
|
||||||
|
|
||||||
|
if (diffy >= 0x100)
|
||||||
|
return 0xFFFF;
|
||||||
|
diffx *= diffx;
|
||||||
|
diffy *= diffy;
|
||||||
|
return diffx + diffy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scumm::getSideOfLine(int x1,int y1, int x2, int y2, int x, int y, int box) {
|
||||||
|
return (x-x1)*(y2-y1) <= (y-y1)*(x2-x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point Scumm::closestPtOnLine(int ulx, int uly, int llx, int lly, int x, int y) {
|
||||||
|
int lydiff,lxdiff;
|
||||||
|
int32 dist,a,b,c;
|
||||||
|
int x2,y2;
|
||||||
|
Point pt;
|
||||||
|
|
||||||
|
if (llx==ulx) {
|
||||||
|
x2 = ulx;
|
||||||
|
y2 = y;
|
||||||
|
} else if (lly==uly) {
|
||||||
|
x2 = x;
|
||||||
|
y2 = uly;
|
||||||
|
} else {
|
||||||
|
lydiff = lly - uly;
|
||||||
|
|
||||||
|
lxdiff = llx - ulx;
|
||||||
|
|
||||||
|
if (abs(lxdiff) > abs(lydiff)) {
|
||||||
|
dist = lxdiff * lxdiff + lydiff * lydiff;
|
||||||
|
|
||||||
|
a = ulx * lydiff / lxdiff;
|
||||||
|
b = x * lxdiff / lydiff;
|
||||||
|
|
||||||
|
c = (a + b - uly + y) * lydiff * lxdiff / dist;
|
||||||
|
|
||||||
|
x2 = c;
|
||||||
|
y2 = c * lydiff / lxdiff - a + uly;
|
||||||
|
} else {
|
||||||
|
dist = lydiff * lydiff + lxdiff * lxdiff;
|
||||||
|
|
||||||
|
a = uly * lxdiff / lydiff;
|
||||||
|
b = y * lydiff / lxdiff;
|
||||||
|
|
||||||
|
c = (a + b - ulx + x) * lydiff * lxdiff / dist;
|
||||||
|
|
||||||
|
y2 = c;
|
||||||
|
x2 = c * lxdiff / lydiff - a + ulx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lxdiff = llx - ulx;
|
||||||
|
lydiff = lly - uly;
|
||||||
|
|
||||||
|
if (abs(lydiff) < abs(lxdiff)) {
|
||||||
|
if (lxdiff > 0) {
|
||||||
|
if (x2 < ulx) {
|
||||||
|
type1:;
|
||||||
|
x2 = ulx;
|
||||||
|
y2 = uly;
|
||||||
|
} else if (x2 > llx) {
|
||||||
|
type2:;
|
||||||
|
x2 = llx;
|
||||||
|
y2 = lly;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (x2 > ulx) goto type1;
|
||||||
|
if (x2 < llx) goto type2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (lydiff > 0) {
|
||||||
|
if (y2 < uly) goto type1;
|
||||||
|
if (y2 > lly) goto type2;
|
||||||
|
} else {
|
||||||
|
if (y2 > uly) goto type1;
|
||||||
|
if (y2 < lly) goto type2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pt.x = x2;
|
||||||
|
pt.y = y2;
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scumm::inBoxQuickReject(int b, int x, int y, int threshold) {
|
||||||
|
int t;
|
||||||
|
|
||||||
|
getBoxCoordinates(b);
|
||||||
|
|
||||||
|
if (threshold==0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
t = x - threshold;
|
||||||
|
if (t > box.upperLeftX && t > box.upperRightX &&
|
||||||
|
t > box.lowerLeftX && t > box.lowerRightX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
t = x + threshold;
|
||||||
|
if (t < box.upperLeftX && t < box.upperRightX &&
|
||||||
|
t < box.lowerLeftX && t < box.lowerRightX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
t = y - threshold;
|
||||||
|
if (t > box.upperLeftY && t > box.upperRightY &&
|
||||||
|
t > box.lowerLeftY && t > box.lowerRightY)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
t = y + threshold;
|
||||||
|
if (t < box.upperLeftY && t < box.upperRightY &&
|
||||||
|
t < box.lowerLeftY && t < box.lowerRightY)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdjustBoxResult Scumm::getClosestPtOnBox(int b, int x, int y) {
|
||||||
|
Point pt;
|
||||||
|
AdjustBoxResult best;
|
||||||
|
uint dist;
|
||||||
|
uint bestdist = (uint)0xFFFF;
|
||||||
|
|
||||||
|
getBoxCoordinates(b);
|
||||||
|
|
||||||
|
pt = closestPtOnLine(box.upperLeftX,box.upperLeftY,box.upperRightX,box.upperRightY,x,y);
|
||||||
|
dist = distanceFromPt(x, y, pt.x, pt.y);
|
||||||
|
if (dist < bestdist) {
|
||||||
|
bestdist = dist;
|
||||||
|
best.x = pt.x;
|
||||||
|
best.y = pt.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
pt = closestPtOnLine(box.upperRightX,box.upperRightY,box.lowerLeftX,box.lowerLeftY,x,y);
|
||||||
|
dist = distanceFromPt(x, y, pt.x, pt.y);
|
||||||
|
if (dist < bestdist) {
|
||||||
|
bestdist = dist;
|
||||||
|
best.x = pt.x;
|
||||||
|
best.y = pt.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
pt = closestPtOnLine(box.lowerLeftX,box.lowerLeftY,box.lowerRightX,box.lowerRightY,x,y);
|
||||||
|
dist = distanceFromPt(x, y, pt.x, pt.y);
|
||||||
|
if (dist < bestdist) {
|
||||||
|
bestdist = dist;
|
||||||
|
best.x = pt.x;
|
||||||
|
best.y = pt.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
pt = closestPtOnLine(box.lowerRightX,box.lowerRightY,box.upperLeftX,box.upperLeftY,x,y);
|
||||||
|
dist = distanceFromPt(x, y, pt.x, pt.y);
|
||||||
|
if (dist < bestdist) {
|
||||||
|
bestdist = dist;
|
||||||
|
best.x = pt.x;
|
||||||
|
best.y = pt.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
best.dist = bestdist;
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *Scumm::getBoxMatrixBaseAddr() {
|
||||||
|
byte *ptr = getResourceAddress(0xE, 1) + 8;
|
||||||
|
if (*ptr==0xFF) ptr++;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getPathToDestBox(int from, int to) {
|
||||||
|
byte *boxm;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (from==to)
|
||||||
|
return to;
|
||||||
|
|
||||||
|
boxm = getBoxMatrixBaseAddr();
|
||||||
|
|
||||||
|
i=0;
|
||||||
|
while (i != from) {
|
||||||
|
while (*boxm != 0xFF)
|
||||||
|
boxm += 3;
|
||||||
|
i++;
|
||||||
|
boxm++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (boxm[0]!=0xFF) {
|
||||||
|
if (boxm[0] <= to && boxm[1]>=to)
|
||||||
|
return boxm[2];
|
||||||
|
boxm+=3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::findPathTowards(Actor *a, int box1, int box2, int box3) {
|
||||||
|
int upperLeftX, upperLeftY;
|
||||||
|
int upperRightX, upperRightY;
|
||||||
|
int lowerLeftX, lowerLeftY;
|
||||||
|
int lowerRightX, lowerRightY;
|
||||||
|
int i,j,m,n,p,q,r;
|
||||||
|
int tmp_x, tmp_y;
|
||||||
|
int tmp;
|
||||||
|
|
||||||
|
getBoxCoordinates(box1);
|
||||||
|
upperLeftX = box.upperLeftX;
|
||||||
|
upperLeftY = box.upperLeftY;
|
||||||
|
upperRightX = box.upperRightX;
|
||||||
|
upperRightY = box.upperRightY;
|
||||||
|
lowerLeftX = box.lowerLeftX;
|
||||||
|
lowerLeftY = box.lowerLeftY;
|
||||||
|
lowerRightX = box.lowerRightX;
|
||||||
|
lowerRightY = box.lowerRightY;
|
||||||
|
getBoxCoordinates(box2);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
if (i >= 4) goto ExitPos;
|
||||||
|
for (j=0; j<4; j++) {
|
||||||
|
if (upperRightX==upperLeftX &&
|
||||||
|
box.upperLeftX==upperLeftX &&
|
||||||
|
box.upperRightX==upperRightX) {
|
||||||
|
|
||||||
|
ExitPos:;
|
||||||
|
n = m = 0;
|
||||||
|
if (upperRightY < upperLeftY) {
|
||||||
|
m = 1;
|
||||||
|
SWAP(upperRightY, upperLeftY);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i = 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)
|
||||||
|
return 1;
|
||||||
|
_foundPathX = upperLeftX;
|
||||||
|
_foundPathY = q;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
if (m) {
|
||||||
|
SWAP(upperRightY, upperLeftY);
|
||||||
|
}
|
||||||
|
if (n) {
|
||||||
|
SWAP(box.upperRightY, box.upperLeftY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (upperLeftY==upperRightY &&
|
||||||
|
box.upperLeftY==upperLeftY &&
|
||||||
|
box.upperRightY==upperRightY) {
|
||||||
|
n = m = 0;
|
||||||
|
if(upperRightX < upperLeftX) {
|
||||||
|
m = 1;
|
||||||
|
SWAP(upperRightX, upperLeftX);
|
||||||
|
}
|
||||||
|
if (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;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tmp = 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)
|
||||||
|
return 1;
|
||||||
|
_foundPathX = q;
|
||||||
|
_foundPathY = upperLeftY;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
if (m != 0) {
|
||||||
|
SWAP(upperRightX, upperLeftX);
|
||||||
|
}
|
||||||
|
if (n != 0) {
|
||||||
|
SWAP(box.upperRightX, box.upperLeftX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp_x = upperLeftX;
|
||||||
|
tmp_y = upperLeftY;
|
||||||
|
upperLeftX = upperRightX;
|
||||||
|
upperLeftY = upperRightY;
|
||||||
|
upperRightX = lowerLeftX;
|
||||||
|
upperRightY = lowerLeftY;
|
||||||
|
lowerLeftX = lowerRightX;
|
||||||
|
lowerLeftY = lowerRightY;
|
||||||
|
lowerRightX = tmp_x;
|
||||||
|
lowerRightY = tmp_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scumm::setBoxFlags(int box, int val) {
|
||||||
|
Box *b = getBoxBaseAddr(box);
|
||||||
|
b->flags = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::setBoxScale(int box, int scale) {
|
||||||
|
Box *b = getBoxBaseAddr(box);
|
||||||
|
b->scale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BOX_MATRIX_SIZE 2000
|
||||||
|
|
||||||
|
void Scumm::createBoxMatrix() {
|
||||||
|
byte *matrix_ptr;
|
||||||
|
int num,i,j;
|
||||||
|
byte flags;
|
||||||
|
int table_1[66],table_2[66];
|
||||||
|
int counter,val;
|
||||||
|
int code;
|
||||||
|
|
||||||
|
PathVertex *vtx;
|
||||||
|
PathNode *node, *node2;
|
||||||
|
|
||||||
|
_maxBoxVertexHeap = 1000;
|
||||||
|
|
||||||
|
createResource(0xE, 4, 1000);
|
||||||
|
createResource(0xE, 3, 4160); //65 items of something of size 64
|
||||||
|
createResource(0xE, 1, BOX_MATRIX_SIZE+8);
|
||||||
|
|
||||||
|
matrix_ptr = getResourceAddress(0xE, 1);
|
||||||
|
|
||||||
|
/* endian & alignment safe */
|
||||||
|
((uint32*)matrix_ptr)[1] = TO_BE_32(BOX_MATRIX_SIZE+8);
|
||||||
|
((uint32*)matrix_ptr)[0] = MKID('BOXM');
|
||||||
|
|
||||||
|
_boxMatrixPtr4 = getResourceAddress(0xE, 4);
|
||||||
|
_boxMatrixPtr1 = getResourceAddress(0xE, 1) + 8;
|
||||||
|
_boxMatrixPtr3 = getResourceAddress(0xE, 3);
|
||||||
|
|
||||||
|
_boxPathVertexHeapIndex = _boxMatrixItem = 0;
|
||||||
|
|
||||||
|
num = getNumBoxes();
|
||||||
|
|
||||||
|
for (i=0; i<num; i++) {
|
||||||
|
for (j=0; j<num; j++) {
|
||||||
|
if (i==j) {
|
||||||
|
_boxMatrixPtr3[i*64+j] = 0;
|
||||||
|
} else if (areBoxesNeighbours(i, j)) {
|
||||||
|
_boxMatrixPtr3[i*64+j] = 1;
|
||||||
|
} else {
|
||||||
|
_boxMatrixPtr3[i*64+j] = 250;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j=0; j<num; j++) {
|
||||||
|
flags = getBoxFlags(j);
|
||||||
|
if (flags & 0x80) {
|
||||||
|
addToBoxMatrix(0xFF);
|
||||||
|
addToBoxMatrix(j);
|
||||||
|
addToBoxMatrix(j);
|
||||||
|
addToBoxMatrix(j);
|
||||||
|
} else {
|
||||||
|
vtx = addPathVertex();
|
||||||
|
for (i=0; i<num; i++) {
|
||||||
|
flags = getBoxFlags(j);
|
||||||
|
if (!(flags&0x80)) {
|
||||||
|
node = unkMatrixProc2(vtx, i);
|
||||||
|
if (i==j)
|
||||||
|
node2 = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table_1[j] = 0;
|
||||||
|
table_2[j] = j;
|
||||||
|
vtx = unkMatrixProc1(vtx, node2);
|
||||||
|
node = vtx ? vtx->left : NULL;
|
||||||
|
|
||||||
|
counter = 250;
|
||||||
|
while (node) {
|
||||||
|
val = _boxMatrixPtr3[j*64 + node->index];
|
||||||
|
table_1[node->index] = val;
|
||||||
|
if (val<counter) counter=val;
|
||||||
|
|
||||||
|
if (table_1[node->index]!=250)
|
||||||
|
table_2[node->index] = node->index;
|
||||||
|
else
|
||||||
|
table_2[node->index] = -1;
|
||||||
|
|
||||||
|
node = node->left;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (vtx) {
|
||||||
|
counter = 250;
|
||||||
|
node2 = node = vtx->left;
|
||||||
|
|
||||||
|
while (node) {
|
||||||
|
if ( table_1[node->index] < counter ) {
|
||||||
|
counter = table_1[node->index];
|
||||||
|
node2 = node;
|
||||||
|
}
|
||||||
|
node = node->left;
|
||||||
|
}
|
||||||
|
vtx = unkMatrixProc1(vtx, node2);
|
||||||
|
node = vtx ? vtx->left : NULL;
|
||||||
|
while (node) {
|
||||||
|
code = _boxMatrixPtr3[node2->index * 64 + node->index];
|
||||||
|
code += table_1[node2->index];
|
||||||
|
if (code < table_1[node->index]) {
|
||||||
|
table_1[node->index] = code;
|
||||||
|
table_2[node->index] = table_2[node2->index];
|
||||||
|
}
|
||||||
|
node = node->left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addToBoxMatrix(0xFF);
|
||||||
|
for (i=1; i<num;) {
|
||||||
|
if (table_2[i-1]!=-1) {
|
||||||
|
addToBoxMatrix(i-1); /* lo */
|
||||||
|
if (table_2[i-1] != table_2[i]) {
|
||||||
|
addToBoxMatrix(i-1); /* hi */
|
||||||
|
addToBoxMatrix(table_2[i-1]); /* dst */
|
||||||
|
} else {
|
||||||
|
while (table_2[i-1] == table_2[i]) {
|
||||||
|
if (++i==num)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
addToBoxMatrix(i-1); /* hi */
|
||||||
|
addToBoxMatrix(table_2[i-1]); /* dst */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (++i==num && table_2[i-1]!=-1) {
|
||||||
|
addToBoxMatrix(i-1); /* lo */
|
||||||
|
addToBoxMatrix(i-1); /* hi */
|
||||||
|
addToBoxMatrix(table_2[i-1]); /* dest */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addToBoxMatrix(0xFF);
|
||||||
|
nukeResource(0xE, 4);
|
||||||
|
nukeResource(0xE, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
PathVertex *Scumm::unkMatrixProc1(PathVertex *vtx, PathNode *node) {
|
||||||
|
if (node==NULL || vtx==NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!node->right) {
|
||||||
|
vtx->left = node->left;
|
||||||
|
} else {
|
||||||
|
node->right->left = node->left;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node->left) {
|
||||||
|
vtx->right = node->right;
|
||||||
|
} else {
|
||||||
|
node->left->right = node->right;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vtx->left)
|
||||||
|
return vtx;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PathNode *Scumm::unkMatrixProc2(PathVertex *vtx, int i) {
|
||||||
|
PathNode *node;
|
||||||
|
|
||||||
|
if (vtx==NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!vtx->right) {
|
||||||
|
node = (PathNode*)addToBoxVertexHeap(sizeof(PathNode));
|
||||||
|
vtx->left = vtx->right = node;
|
||||||
|
|
||||||
|
node->index = i;
|
||||||
|
node->left = 0;
|
||||||
|
node->right = 0;
|
||||||
|
} else {
|
||||||
|
node = (PathNode*)addToBoxVertexHeap(sizeof(PathNode));
|
||||||
|
vtx->right->left = node;
|
||||||
|
|
||||||
|
node->right = vtx->right;
|
||||||
|
node->index = i;
|
||||||
|
node->left = 0;
|
||||||
|
|
||||||
|
vtx->right = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vtx->right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
int j,k,m,n;
|
||||||
|
int tmp_x, tmp_y;
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
if (getBoxFlags(box1)&0x80 || getBoxFlags(box2)&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);
|
||||||
|
|
||||||
|
result = false;
|
||||||
|
j = 4;
|
||||||
|
|
||||||
|
do {
|
||||||
|
k = 4;
|
||||||
|
do {
|
||||||
|
if (upperRightX == upperLeftX &&
|
||||||
|
box.upperLeftX == upperLeftX &&
|
||||||
|
box.upperRightX == upperRightX) {
|
||||||
|
/* 5b74 */
|
||||||
|
n = m = 0;
|
||||||
|
if (upperRightY < upperLeftY) {
|
||||||
|
n = 1;
|
||||||
|
SWAP(upperRightY, upperLeftY);
|
||||||
|
}
|
||||||
|
if (box.upperRightY < box.upperLeftY) {
|
||||||
|
m = 1;
|
||||||
|
SWAP(box.upperRightY, box.upperLeftY);
|
||||||
|
}
|
||||||
|
if (box.upperRightY < upperLeftY ||
|
||||||
|
box.upperLeftY > upperRightY ||
|
||||||
|
(box.upperLeftY == upperRightY ||
|
||||||
|
box.upperRightY==upperLeftY) &&
|
||||||
|
upperRightY != upperLeftY &&
|
||||||
|
box.upperLeftY!=box.upperRightY) {
|
||||||
|
/* if_1_if */
|
||||||
|
if (n) {
|
||||||
|
SWAP(upperRightY, upperLeftY);
|
||||||
|
}
|
||||||
|
if (m) {
|
||||||
|
SWAP(box.upperRightY, box.upperLeftY);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* if_1_else */
|
||||||
|
if (n) {
|
||||||
|
SWAP(upperRightY, upperLeftY);
|
||||||
|
}
|
||||||
|
if (m) {
|
||||||
|
SWAP(box.upperRightY, box.upperLeftY);
|
||||||
|
}
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do_it_for_y */
|
||||||
|
if (upperRightY == upperLeftY &&
|
||||||
|
box.upperLeftY == upperLeftY &&
|
||||||
|
box.upperRightY == upperRightY) {
|
||||||
|
n = m = 0;
|
||||||
|
if (upperRightX < upperLeftX) {
|
||||||
|
n = 1;
|
||||||
|
SWAP(upperRightX, upperLeftX);
|
||||||
|
}
|
||||||
|
if (box.upperRightX < box.upperLeftX) {
|
||||||
|
m = 1;
|
||||||
|
SWAP(box.upperRightX, box.upperLeftX);
|
||||||
|
}
|
||||||
|
if (box.upperRightX < upperLeftX ||
|
||||||
|
box.upperLeftX > upperRightX ||
|
||||||
|
(box.upperLeftX == upperRightX ||
|
||||||
|
box.upperRightX==upperLeftX) &&
|
||||||
|
upperRightX != upperLeftX &&
|
||||||
|
box.upperLeftX!=box.upperRightX) {
|
||||||
|
|
||||||
|
/* if_2_if */
|
||||||
|
if (n) {
|
||||||
|
SWAP(upperRightX, upperLeftX);
|
||||||
|
}
|
||||||
|
if (m) {
|
||||||
|
SWAP(box.upperRightX, box.upperLeftX);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* if_2_else */
|
||||||
|
if (n) {
|
||||||
|
SWAP(upperRightX, upperLeftX);
|
||||||
|
}
|
||||||
|
if (m) {
|
||||||
|
SWAP(box.upperRightX, box.upperLeftX);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
} 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;
|
||||||
|
} while (--j);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::addToBoxMatrix(byte b) {
|
||||||
|
if (++_boxMatrixItem > BOX_MATRIX_SIZE)
|
||||||
|
error("Box matrix overflow");
|
||||||
|
*_boxMatrixPtr1++ = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Scumm::addToBoxVertexHeap(int size) {
|
||||||
|
byte *ptr = _boxMatrixPtr4;
|
||||||
|
|
||||||
|
_boxMatrixPtr4 += size;
|
||||||
|
_boxPathVertexHeapIndex += size;
|
||||||
|
|
||||||
|
if (_boxPathVertexHeapIndex >= _maxBoxVertexHeap)
|
||||||
|
error("Box path vertex heap overflow");
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PathVertex *Scumm::addPathVertex() {
|
||||||
|
_boxMatrixPtr4 = getResourceAddress(0xE, 4);
|
||||||
|
_boxPathVertexHeapIndex = 0;
|
||||||
|
return (PathVertex*)addToBoxVertexHeap(sizeof(PathVertex));
|
||||||
|
}
|
341
copying.txt
Normal file
341
copying.txt
Normal file
|
@ -0,0 +1,341 @@
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) 19yy <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
701
costume.cpp
Normal file
701
costume.cpp
Normal file
|
@ -0,0 +1,701 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:14 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
const byte revBitMask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
|
||||||
|
|
||||||
|
void CostumeRenderer::ignorePakCols(int a) {
|
||||||
|
int n;
|
||||||
|
n = _height;
|
||||||
|
if (a>1) n *= a;
|
||||||
|
do {
|
||||||
|
_repcolor = *_srcptr++;
|
||||||
|
_replen = _repcolor&_maskval;
|
||||||
|
if (_replen==0) {
|
||||||
|
_replen = *_srcptr++;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
if (!--n) {
|
||||||
|
_repcolor >>= _shrval;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (--_replen);
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte cost_scaleTable[256] = {
|
||||||
|
255, 253, 125, 189, 61, 221, 93, 157, 29, 237,
|
||||||
|
109, 173, 45, 205, 77, 141, 13, 245, 117, 181,
|
||||||
|
53, 213, 85, 149, 21, 229, 101, 165, 37, 197, 69,
|
||||||
|
133, 5, 249, 121, 185, 57, 217, 89, 153, 25, 233,
|
||||||
|
105, 169, 41, 201, 73, 137, 9, 241, 113, 177, 49,
|
||||||
|
209, 81, 145, 17, 225, 97, 161, 33, 193, 65, 129,
|
||||||
|
1, 251, 123, 187, 59, 219, 91, 155, 27, 235, 107,
|
||||||
|
171, 43, 203, 75, 139, 11, 243, 115, 179, 51, 211,
|
||||||
|
83, 147, 19, 227, 99, 163, 35, 195, 67, 131, 3,
|
||||||
|
247, 119, 183, 55, 215, 87, 151, 23, 231, 103,
|
||||||
|
167, 39, 199, 71, 135, 7, 239, 111, 175, 47, 207,
|
||||||
|
79, 143, 15, 223, 95, 159, 31, 191, 63, 127, 0,
|
||||||
|
128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208,
|
||||||
|
48, 176, 112, 240, 8, 136, 72, 200, 40, 168, 104,
|
||||||
|
232, 24, 152, 88, 216, 56, 184, 120, 248, 4, 132,
|
||||||
|
68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52,
|
||||||
|
180, 116, 244, 12, 140, 76, 204, 44, 172, 108,
|
||||||
|
236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130,
|
||||||
|
66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50,
|
||||||
|
178, 114, 242, 10, 138, 74, 202, 42, 170, 106,
|
||||||
|
234, 26, 154, 90, 218, 58, 186, 122, 250, 6, 134,
|
||||||
|
70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54,
|
||||||
|
182, 118, 246, 14, 142, 78, 206, 46, 174, 110,
|
||||||
|
238, 30, 158, 94, 222, 62, 190, 126, 254
|
||||||
|
};
|
||||||
|
|
||||||
|
byte CostumeRenderer::mainRoutine(Actor *a, int slot, int frame) {
|
||||||
|
int xmove, ymove, i,b,s;
|
||||||
|
uint scal;
|
||||||
|
byte scaling;
|
||||||
|
byte charsetmask, masking;
|
||||||
|
byte unk19;
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
|
||||||
|
_maskval = 0xF;
|
||||||
|
_shrval = 4;
|
||||||
|
if (_numColors == 32) {
|
||||||
|
_maskval = 7;
|
||||||
|
_shrval = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
_width2 = _srcptr[0];
|
||||||
|
_width = _width2;
|
||||||
|
_height2 = _srcptr[2];
|
||||||
|
_height = _height2;
|
||||||
|
xmove = (int16)READ_LE_UINT16(_srcptr+4) + _xmove;
|
||||||
|
ymove = (int16)READ_LE_UINT16(_srcptr+6) + _ymove;
|
||||||
|
_xmove += (int16)READ_LE_UINT16(_srcptr+8);
|
||||||
|
_ymove -= (int16)READ_LE_UINT16(_srcptr+10);
|
||||||
|
_srcptr += 12;
|
||||||
|
|
||||||
|
_xpos = _actorX;
|
||||||
|
_ypos = _actorY;
|
||||||
|
|
||||||
|
scaling = _scaleX==255 && _scaleY==255 ? 0 : 1;
|
||||||
|
s = 0;
|
||||||
|
|
||||||
|
if (scaling) {
|
||||||
|
_scaleIndexXStep = -1;
|
||||||
|
if (xmove < 0) {
|
||||||
|
xmove = -xmove;
|
||||||
|
_scaleIndexXStep = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_mirror) {
|
||||||
|
unk19 = _scaleIndexX = 128 - xmove;
|
||||||
|
for (i=0; i<xmove; i++) {
|
||||||
|
scal = cost_scaleTable[_scaleIndexX++];
|
||||||
|
if (scal < _scaleX)
|
||||||
|
_xpos -= _scaleIndexXStep;
|
||||||
|
}
|
||||||
|
_right = _left = _xpos;
|
||||||
|
_scaleIndexX = unk19;
|
||||||
|
for (i=0; i<_width; i++) {
|
||||||
|
if (_right < 0) {
|
||||||
|
s++;
|
||||||
|
unk19 = _scaleIndexX;
|
||||||
|
}
|
||||||
|
scal = cost_scaleTable[_scaleIndexX++];
|
||||||
|
if (scal < _scaleX)
|
||||||
|
_right++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unk19 = _scaleIndexX = xmove + 128;
|
||||||
|
for (i=0; i<xmove; i++) {
|
||||||
|
scal = cost_scaleTable[_scaleIndexX--];
|
||||||
|
if (scal < _scaleX)
|
||||||
|
_xpos += _scaleIndexXStep;
|
||||||
|
}
|
||||||
|
_right = _left = _xpos;
|
||||||
|
_scaleIndexX = unk19;
|
||||||
|
for (i=0; i<_width; i++) {
|
||||||
|
if (_left > 319) {
|
||||||
|
s++;
|
||||||
|
unk19 = _scaleIndexX;
|
||||||
|
}
|
||||||
|
scal = cost_scaleTable[_scaleIndexX--];
|
||||||
|
if(scal < _scaleX)
|
||||||
|
_left--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_scaleIndexX = unk19;
|
||||||
|
if (s)
|
||||||
|
s--;
|
||||||
|
_scaleIndexYStep = -1;
|
||||||
|
if (ymove < 0) {
|
||||||
|
ymove = -ymove;
|
||||||
|
_scaleIndexYStep = 1;
|
||||||
|
}
|
||||||
|
_scaleIndexY = 128 - ymove;
|
||||||
|
for (i=0; i<ymove; i++) {
|
||||||
|
scal = cost_scaleTable[_scaleIndexY++];
|
||||||
|
if (scal < _scaleY)
|
||||||
|
_ypos -= _scaleIndexYStep;
|
||||||
|
}
|
||||||
|
_top = _bottom = _ypos;
|
||||||
|
_scaleIndexY = 128 - ymove;
|
||||||
|
for (i=0; i<_height; i++) {
|
||||||
|
scal = cost_scaleTable[_scaleIndexY++];
|
||||||
|
if (scal < _scaleY)
|
||||||
|
_bottom++;
|
||||||
|
}
|
||||||
|
_scaleIndexY = _scaleIndexYTop = 128 - ymove;
|
||||||
|
} else {
|
||||||
|
if(_mirror==0)
|
||||||
|
xmove = -xmove;
|
||||||
|
_xpos += xmove;
|
||||||
|
_ypos += ymove;
|
||||||
|
if (_mirror) {
|
||||||
|
_left = _xpos;
|
||||||
|
_right = _xpos + _width;
|
||||||
|
} else {
|
||||||
|
_left = _xpos - _width;
|
||||||
|
_right = _xpos;
|
||||||
|
}
|
||||||
|
_top = _ypos;
|
||||||
|
_bottom = _top + _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
_scaleIndexXStep = -1;
|
||||||
|
if (_mirror)
|
||||||
|
_scaleIndexXStep = 1;
|
||||||
|
_ypostop = _ypos;
|
||||||
|
_vscreenheight = _vm->virtscr[0].height;
|
||||||
|
_vm->updateDirtyRect(0, _left, _right+1,_top,_bottom,1<<a->number);
|
||||||
|
|
||||||
|
if ((int)_top >= (int)_vscreenheight || _bottom <= 0) {
|
||||||
|
checkHeap();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ypitch = _height * 320;
|
||||||
|
_docontinue = 0;
|
||||||
|
b = 1;
|
||||||
|
if (_left > 319 || _right <= 0)
|
||||||
|
return 0;
|
||||||
|
if (_mirror) {
|
||||||
|
_ypitch--;
|
||||||
|
if (scaling==0) {
|
||||||
|
s = -_xpos;
|
||||||
|
}
|
||||||
|
if (s > 0) {
|
||||||
|
_width2 -= s;
|
||||||
|
ignorePakCols(s);
|
||||||
|
_xpos = 0;
|
||||||
|
_docontinue = 1;
|
||||||
|
} else {
|
||||||
|
s = _right - 320;
|
||||||
|
if (s<=0) {
|
||||||
|
b = 2;
|
||||||
|
} else {
|
||||||
|
_width2 -= s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_ypitch++;
|
||||||
|
if(scaling==0)
|
||||||
|
s = _right - 320;
|
||||||
|
if (s > 0) {
|
||||||
|
_width2 -= s;
|
||||||
|
ignorePakCols(s);
|
||||||
|
_xpos = 319;
|
||||||
|
_docontinue = 1;
|
||||||
|
} else {
|
||||||
|
s = -1 - _left;
|
||||||
|
if (s <= 0)
|
||||||
|
b = 2;
|
||||||
|
else
|
||||||
|
_width2 -= s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_top > _vscreenheight || _top < 0)
|
||||||
|
_top = 0;
|
||||||
|
|
||||||
|
if (_bottom > _vscreenheight)
|
||||||
|
_bottom = _vscreenheight;
|
||||||
|
|
||||||
|
if (a->top > _top)
|
||||||
|
a->top = _top;
|
||||||
|
|
||||||
|
if (a->bottom < _bottom)
|
||||||
|
a->bottom = _bottom;
|
||||||
|
|
||||||
|
if (_height2 + _top >= 256) {
|
||||||
|
checkHeap();
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
_where_to_draw_ptr = _vm->getResourceAddress(0xA, 5) + _vm->virtscr[0].xstart + _ypos*320 + _xpos;
|
||||||
|
_bg_ptr = _vm->getResourceAddress(0xA, 1) + _vm->virtscr[0].xstart + _ypos*320 + _xpos;
|
||||||
|
charsetmask = _vm->hasCharsetMask(_left, _top + _vm->virtscr[0].topline, _right, _vm->virtscr[0].topline + _bottom);
|
||||||
|
masking = 0;
|
||||||
|
|
||||||
|
if (_zbuf) {
|
||||||
|
masking = _vm->isMaskActiveAt(_left, _top, _right, _bottom,
|
||||||
|
_vm->getResourceAddress(0xA, 9) + _vm->_imgBufOffs[_zbuf] + _vm->_screenStartStrip
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_zbuf || charsetmask) {
|
||||||
|
_mask_ptr = _vm->getResourceAddress(0xA, 9) + _ypos*40 + _vm->_screenStartStrip;
|
||||||
|
|
||||||
|
_imgbufoffs = _vm->_imgBufOffs[_zbuf];
|
||||||
|
if (!charsetmask && _zbuf!=0)
|
||||||
|
_mask_ptr += _imgbufoffs;
|
||||||
|
_mask_ptr_dest = _mask_ptr + _xpos / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
|
||||||
|
switch ((scaling<<2)|(masking<<1)|charsetmask) {
|
||||||
|
case 0:
|
||||||
|
proc6();
|
||||||
|
break;
|
||||||
|
case 1: case 2:
|
||||||
|
proc5();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
proc4();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
proc1();
|
||||||
|
break;
|
||||||
|
case 5:case 6:
|
||||||
|
proc2();
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
proc3();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CostumeRenderer::proc6() {
|
||||||
|
byte len;
|
||||||
|
byte *src, *dst;
|
||||||
|
byte width,height,pcolor;
|
||||||
|
int color;
|
||||||
|
uint y;
|
||||||
|
uint scrheight;
|
||||||
|
|
||||||
|
y = _ypos;
|
||||||
|
len = _replen;
|
||||||
|
src = _srcptr;
|
||||||
|
dst = _bg_ptr;
|
||||||
|
color = _repcolor;
|
||||||
|
scrheight = _vscreenheight;
|
||||||
|
width = _width2;
|
||||||
|
height = _height2;
|
||||||
|
|
||||||
|
if (_docontinue) goto StartPos;
|
||||||
|
|
||||||
|
do {
|
||||||
|
len = *src++;
|
||||||
|
color = len>>_shrval;
|
||||||
|
len &= _maskval;
|
||||||
|
if (!len) len = *src++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (color && y < scrheight) {
|
||||||
|
pcolor = _palette[color];
|
||||||
|
if (pcolor==13) {
|
||||||
|
pcolor = _transEffect[*dst];
|
||||||
|
}
|
||||||
|
*dst = pcolor;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst += 320;
|
||||||
|
y++;
|
||||||
|
if (!--height) {
|
||||||
|
if (!--width)
|
||||||
|
return;
|
||||||
|
height = _height;
|
||||||
|
dst -= _ypitch;
|
||||||
|
y = _ypostop;
|
||||||
|
}
|
||||||
|
StartPos:;
|
||||||
|
} while (--len);
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CostumeRenderer::proc5() {
|
||||||
|
byte *mask,*src,*dst;
|
||||||
|
byte maskbit,len,height,pcolor;
|
||||||
|
uint y,scrheight;
|
||||||
|
int color;
|
||||||
|
|
||||||
|
mask = _mask_ptr = _mask_ptr_dest;
|
||||||
|
maskbit = revBitMask[_xpos&7];
|
||||||
|
y = _ypos;
|
||||||
|
src = _srcptr;
|
||||||
|
dst = _bg_ptr;
|
||||||
|
len = _replen;
|
||||||
|
color = _repcolor;
|
||||||
|
scrheight = _vscreenheight;
|
||||||
|
height = _height2;
|
||||||
|
|
||||||
|
if (_docontinue) goto StartPos;
|
||||||
|
|
||||||
|
do {
|
||||||
|
len = *src++;
|
||||||
|
color = len>>_shrval;
|
||||||
|
len &= _maskval;
|
||||||
|
if (!len) len = *src++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (color && y<scrheight && !(*mask&maskbit)) {
|
||||||
|
pcolor = _palette[color];
|
||||||
|
if (pcolor==13)
|
||||||
|
pcolor = _transEffect[*dst];
|
||||||
|
*dst = pcolor;
|
||||||
|
}
|
||||||
|
dst += 320;
|
||||||
|
y++;
|
||||||
|
mask += 40;
|
||||||
|
if (!--height) {
|
||||||
|
if(!--_width2)
|
||||||
|
return;
|
||||||
|
height = _height;
|
||||||
|
dst -= _ypitch;
|
||||||
|
y = _ypostop;
|
||||||
|
if(_scaleIndexXStep!=1) {
|
||||||
|
maskbit<<=1;
|
||||||
|
if (!maskbit) {
|
||||||
|
maskbit=1;
|
||||||
|
_mask_ptr--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
maskbit>>=1;
|
||||||
|
if (!maskbit) {
|
||||||
|
maskbit=0x80;
|
||||||
|
_mask_ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mask = _mask_ptr;
|
||||||
|
}
|
||||||
|
StartPos:;
|
||||||
|
} while (--len);
|
||||||
|
} while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CostumeRenderer::proc4() {
|
||||||
|
byte *mask,*src,*dst;
|
||||||
|
byte maskbit,len,height,pcolor;
|
||||||
|
uint y,scrheight;
|
||||||
|
int color;
|
||||||
|
|
||||||
|
mask = _mask_ptr = _mask_ptr_dest;
|
||||||
|
maskbit = revBitMask[_xpos&7];
|
||||||
|
y = _ypos;
|
||||||
|
src = _srcptr;
|
||||||
|
dst = _bg_ptr;
|
||||||
|
len = _replen;
|
||||||
|
color = _repcolor;
|
||||||
|
scrheight = _vscreenheight;
|
||||||
|
height = _height2;
|
||||||
|
|
||||||
|
if (_docontinue) goto StartPos;
|
||||||
|
|
||||||
|
do {
|
||||||
|
len = *src++;
|
||||||
|
color = len>>_shrval;
|
||||||
|
len &= _maskval;
|
||||||
|
if (!len) len = *src++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (color && y<scrheight && !((*mask|mask[_imgbufoffs])&maskbit)) {
|
||||||
|
pcolor = _palette[color];
|
||||||
|
if (pcolor==13)
|
||||||
|
pcolor = _transEffect[*dst];
|
||||||
|
*dst = pcolor;
|
||||||
|
}
|
||||||
|
dst += 320;
|
||||||
|
y++;
|
||||||
|
mask += 40;
|
||||||
|
if (!--height) {
|
||||||
|
if(!--_width2)
|
||||||
|
return;
|
||||||
|
height = _height;
|
||||||
|
dst -= _ypitch;
|
||||||
|
y = _ypostop;
|
||||||
|
if(_scaleIndexXStep!=1) {
|
||||||
|
maskbit<<=1;
|
||||||
|
if (!maskbit) {
|
||||||
|
maskbit=1;
|
||||||
|
_mask_ptr--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
maskbit>>=1;
|
||||||
|
if (!maskbit) {
|
||||||
|
maskbit=0x80;
|
||||||
|
_mask_ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mask = _mask_ptr;
|
||||||
|
}
|
||||||
|
StartPos:;
|
||||||
|
} while (--len);
|
||||||
|
} while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CostumeRenderer::proc3() {
|
||||||
|
warning("COST_Proc3: not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CostumeRenderer::proc2() {
|
||||||
|
byte *mask,*src,*dst;
|
||||||
|
byte maskbit,len,height,pcolor,width;
|
||||||
|
int color,t;
|
||||||
|
uint y;
|
||||||
|
|
||||||
|
mask = _mask_ptr_dest;
|
||||||
|
dst = _bg_ptr;
|
||||||
|
height = _height2;
|
||||||
|
width = _width2;
|
||||||
|
len = _replen;
|
||||||
|
color = _repcolor;
|
||||||
|
src = _srcptr;
|
||||||
|
maskbit = revBitMask[_xpos&7];
|
||||||
|
y = _ypos;
|
||||||
|
|
||||||
|
if (_docontinue) goto StartPos;
|
||||||
|
|
||||||
|
do {
|
||||||
|
len = *src++;
|
||||||
|
color = len>>_shrval;
|
||||||
|
len &= _maskval;
|
||||||
|
if (!len) len = *src++;
|
||||||
|
do {
|
||||||
|
if (cost_scaleTable[_scaleIndexY++] < _scaleY) {
|
||||||
|
if (color && y < _vscreenheight && !(*mask&maskbit)) {
|
||||||
|
pcolor = _palette[color];
|
||||||
|
if (pcolor==13)
|
||||||
|
pcolor = _transEffect[*dst];
|
||||||
|
*dst = pcolor;
|
||||||
|
}
|
||||||
|
dst += 320;
|
||||||
|
mask += 40;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
if (!--height) {
|
||||||
|
if(!--width)
|
||||||
|
return;
|
||||||
|
height = _height;
|
||||||
|
y = _ypostop;
|
||||||
|
_scaleIndexY = _scaleIndexYTop;
|
||||||
|
t = _scaleIndexX;
|
||||||
|
_scaleIndexX = t + _scaleIndexXStep;
|
||||||
|
if (cost_scaleTable[t] < _scaleX) {
|
||||||
|
_xpos += _scaleIndexXStep;
|
||||||
|
if (_xpos >= 320)
|
||||||
|
return;
|
||||||
|
maskbit = revBitMask[_xpos&7];
|
||||||
|
_bg_ptr += _scaleIndexXStep;
|
||||||
|
}
|
||||||
|
dst = _bg_ptr;
|
||||||
|
mask = _mask_ptr + (_xpos>>3);
|
||||||
|
}
|
||||||
|
StartPos:;
|
||||||
|
} while (--len);
|
||||||
|
} while(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CostumeRenderer::proc1() {
|
||||||
|
byte *mask,*src,*dst;
|
||||||
|
byte maskbit,len,height,pcolor,width;
|
||||||
|
uint y;
|
||||||
|
int color;
|
||||||
|
int t;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
debug(1, "proc1(): (%d %d),(%d %d %d),(%d %d %d),(%d %d,%d %d,%d %d),(%d %d)",
|
||||||
|
_xpos, _ypos,
|
||||||
|
_width2, _height2, _height,
|
||||||
|
_replen,_repcolor,_docontinue,
|
||||||
|
_scaleX, _scaleY, _scaleIndexX, _scaleIndexY,
|
||||||
|
_scaleIndexXStep, _scaleIndexYStep,
|
||||||
|
_scaleIndexYTop,_vscreenheight
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mask = _mask_ptr = _mask_ptr_dest;
|
||||||
|
maskbit = revBitMask[_xpos&7];
|
||||||
|
y = _ypos;
|
||||||
|
|
||||||
|
dst = _bg_ptr;
|
||||||
|
height = _height2;
|
||||||
|
width = _width2;
|
||||||
|
len = _replen;
|
||||||
|
color = _repcolor;
|
||||||
|
src = _srcptr;
|
||||||
|
|
||||||
|
if (_docontinue) goto StartPos;
|
||||||
|
|
||||||
|
do {
|
||||||
|
len = *src++;
|
||||||
|
color = len>>_shrval;
|
||||||
|
len &= _maskval;
|
||||||
|
if (!len) len = *src++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (cost_scaleTable[_scaleIndexY++] < _scaleY) {
|
||||||
|
if (color && y < _vscreenheight) {
|
||||||
|
pcolor = _palette[color];
|
||||||
|
if (pcolor==13)
|
||||||
|
pcolor = _transEffect[*dst];
|
||||||
|
*dst = pcolor;
|
||||||
|
}
|
||||||
|
dst += 320;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
if (!--height) {
|
||||||
|
if(!--width)
|
||||||
|
return;
|
||||||
|
height = _height;
|
||||||
|
y = _ypostop;
|
||||||
|
_scaleIndexY = _scaleIndexYTop;
|
||||||
|
t = _scaleIndexX;
|
||||||
|
_scaleIndexX = t + _scaleIndexXStep;
|
||||||
|
if (cost_scaleTable[t] < _scaleX) {
|
||||||
|
_xpos += _scaleIndexXStep;
|
||||||
|
if (_xpos >= 320)
|
||||||
|
return;
|
||||||
|
_bg_ptr += _scaleIndexXStep;
|
||||||
|
}
|
||||||
|
dst = _bg_ptr;
|
||||||
|
}
|
||||||
|
StartPos:;
|
||||||
|
} while (--len);
|
||||||
|
} while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CostumeRenderer::loadCostume(int id) {
|
||||||
|
_ptr = _vm->getResourceAddress(3, id) + 2;
|
||||||
|
switch(_ptr[7]&0x7F) {
|
||||||
|
case 0x58:
|
||||||
|
_numColors = 16;
|
||||||
|
break;
|
||||||
|
case 0x59:
|
||||||
|
_numColors = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Costume %d is invalid", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
_dataptr = _ptr + READ_LE_UINT16(_ptr + _numColors + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte CostumeRenderer::drawOneSlot(Actor *a, int slot) {
|
||||||
|
int i;
|
||||||
|
int code;
|
||||||
|
CostumeData *cd = &a->cost;
|
||||||
|
|
||||||
|
if (cd->a[slot]==0xFFFF || cd->hdr & (1<<slot))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
i = cd->a[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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte CostumeRenderer::drawCostume(Actor *a) {
|
||||||
|
int i;
|
||||||
|
byte r = 0;
|
||||||
|
_xmove = _ymove = 0;
|
||||||
|
for (i=0; i<16; i++)
|
||||||
|
r|=drawOneSlot(a, i);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte CostumeRenderer::animateOneSlot(CostumeData *cd, int slot) {
|
||||||
|
int highflag;
|
||||||
|
int i,end,code;
|
||||||
|
|
||||||
|
if (cd->a[slot]==0xFFFF)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
highflag = cd->a[slot]&0x8000;
|
||||||
|
i = cd->a[slot]&0x7FFF;
|
||||||
|
end = cd->c[slot];
|
||||||
|
code=_dataptr[i]&0x7F;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!highflag) {
|
||||||
|
if (i++ >= end)
|
||||||
|
i = cd->b[slot];
|
||||||
|
} else {
|
||||||
|
if (i != end)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_dataptr[i]==0x7C) {
|
||||||
|
cd->animCounter1++;
|
||||||
|
if(cd->b[slot] != end)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_dataptr[i]==0x78) {
|
||||||
|
cd->animCounter2++;
|
||||||
|
if(cd->b[slot] != end)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cd->a[slot] = i|highflag;
|
||||||
|
return (_dataptr[i]&0x7F) != code;
|
||||||
|
} while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte CostumeRenderer::animate(CostumeData *cd) {
|
||||||
|
int i;
|
||||||
|
byte r = 0;
|
||||||
|
|
||||||
|
for (i=0; i<16; i++) {
|
||||||
|
if(cd->a[i]!=0xFFFF)
|
||||||
|
r+=animateOneSlot(cd, i);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
584
object.cpp
Normal file
584
object.cpp
Normal file
|
@ -0,0 +1,584 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:14 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
bool Scumm::getClass(int obj, int cls) {
|
||||||
|
checkRange(_maxNrObjects-1, 0, obj, "Object %d out of range in getClass");
|
||||||
|
|
||||||
|
cls &= 0x7F;
|
||||||
|
checkRange(32,1,cls,"Class %d out of range in getClass");
|
||||||
|
|
||||||
|
return (_classData[obj] & (1<<(cls-1))) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::putClass(int obj, int cls, bool set) {
|
||||||
|
checkRange(_maxNrObjects-1, 0, obj, "Object %d out of range in getClass");
|
||||||
|
|
||||||
|
cls &= 0x7F;
|
||||||
|
checkRange(32,1,cls,"Class %d out of range in getClass");
|
||||||
|
|
||||||
|
if (set)
|
||||||
|
_classData[obj] |= (1<<(cls-1));
|
||||||
|
else
|
||||||
|
_classData[obj] &= ~(1<<(cls-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getOwner(int obj) {
|
||||||
|
checkRange(_maxNrObjects-1, 0, obj, "Object %d out of range in getOwner");
|
||||||
|
return _objectFlagTable[obj]&0xF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::putOwner(int act, int owner) {
|
||||||
|
checkRange(_maxNrObjects-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]&0xF0) | owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getState(int act) {
|
||||||
|
checkRange(_maxNrObjects-1, 0, act, "Object %d out of range in getState");
|
||||||
|
return _objectFlagTable[act]>>4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::putState(int act, int state) {
|
||||||
|
checkRange(_maxNrObjects-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]&0x0F) | (state<<4);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getObjectIndex(int object) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((_objectFlagTable[object]&0xF)!=0xF) {
|
||||||
|
for (i=0; i<_maxInventoryItems; i++)
|
||||||
|
if (_inventory[i] == object)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
for (i=_numObjectsInRoom; i>0; i--) {
|
||||||
|
if (objs[i].obj_nr==object)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::whereIsObject(int object) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((_objectFlagTable[object]&0xF)!=0xF) {
|
||||||
|
for (i=0; i<_maxInventoryItems; i++)
|
||||||
|
if (_inventory[i] == object)
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=_numObjectsInRoom; i>0; i--)
|
||||||
|
if (objs[i].obj_nr == object) {
|
||||||
|
if (objs[i].fl_object_index)
|
||||||
|
return 4;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getObjectOrActorXY(int object) {
|
||||||
|
if (object <= vm.vars[VAR_NUM_ACTOR]) {
|
||||||
|
return getActorXYPos(derefActorSafe(object, "getObjectOrActorXY"));
|
||||||
|
}
|
||||||
|
switch(whereIsObject(object)) {
|
||||||
|
case -1:
|
||||||
|
return -1;
|
||||||
|
case 0:
|
||||||
|
return getActorXYPos(derefActorSafe(_objectFlagTable[object]&0xF,"getObjectOrActorXY(2)"));
|
||||||
|
}
|
||||||
|
getObjectXYPos(object);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::getObjectXYPos(int object) {
|
||||||
|
ObjectData *od = &objs[getObjectIndex(object)];
|
||||||
|
AdjustBoxResult abr;
|
||||||
|
abr = adjustXYToBeInBox(0, od->cdhd_10, od->cdhd_12);
|
||||||
|
_xPos = abr.x;
|
||||||
|
_yPos = abr.y;
|
||||||
|
_dir = od->actordir&3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getObjActToObjActDist(int a, int b) {
|
||||||
|
int x,y;
|
||||||
|
Actor *acta = NULL;
|
||||||
|
Actor *actb = NULL;
|
||||||
|
|
||||||
|
if (a<=vm.vars[VAR_NUM_ACTOR])
|
||||||
|
acta = derefActorSafe(a, "getObjActToObjActDist");
|
||||||
|
|
||||||
|
if (b<=vm.vars[VAR_NUM_ACTOR])
|
||||||
|
actb = derefActorSafe(b, "getObjActToObjActDist(2)");
|
||||||
|
|
||||||
|
if (acta && actb && acta->room==actb->room && acta->room &&
|
||||||
|
acta->room != _currentRoom)
|
||||||
|
return 0xFF;
|
||||||
|
|
||||||
|
if (getObjectOrActorXY(a)==-1)
|
||||||
|
return 0xFF;
|
||||||
|
|
||||||
|
x = _xPos;
|
||||||
|
y = _yPos;
|
||||||
|
|
||||||
|
if (getObjectOrActorXY(b)==-1)
|
||||||
|
return 0xFF;
|
||||||
|
|
||||||
|
/* XXX: bug here? should be <= */
|
||||||
|
if (acta) {
|
||||||
|
AdjustBoxResult r = adjustXYToBeInBox(acta, _xPos, _yPos);
|
||||||
|
_xPos = r.x;
|
||||||
|
_yPos = r.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
y = abs(y-_yPos);
|
||||||
|
x = abs(x-_xPos);
|
||||||
|
|
||||||
|
if (y>x) x=y;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::findObject(int x, int y) {
|
||||||
|
int i,a,b;
|
||||||
|
|
||||||
|
for (i=1; i<=_numObjectsInRoom; i++) {
|
||||||
|
if (!objs[i].obj_nr || getClass(objs[i].obj_nr, 32))
|
||||||
|
continue;
|
||||||
|
b = i;
|
||||||
|
do {
|
||||||
|
a = objs[b].cdhd_0e;
|
||||||
|
b = objs[b].cdhd_0f;
|
||||||
|
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))
|
||||||
|
return objs[i].obj_nr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ( (objs[b].ownerstate&0xF0) == a);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::drawRoomObjects(int arg) {
|
||||||
|
int num = _numObjectsInRoom;
|
||||||
|
ObjectData *od;
|
||||||
|
int a;
|
||||||
|
|
||||||
|
if (num==0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
do {
|
||||||
|
od = &objs[num];
|
||||||
|
if (!od->obj_nr || !(od->ownerstate&0xF0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
do {
|
||||||
|
a = od->cdhd_0e;
|
||||||
|
if (!od->cdhd_0f) {
|
||||||
|
drawObject(num, arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
od = &objs[od->cdhd_0f];
|
||||||
|
} while ((od->ownerstate & 0xF0)==a);
|
||||||
|
|
||||||
|
} while (--num);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32 state_tags[] = {
|
||||||
|
MKID('IM00'),
|
||||||
|
MKID('IM01'),
|
||||||
|
MKID('IM02'),
|
||||||
|
MKID('IM03'),
|
||||||
|
MKID('IM04'),
|
||||||
|
MKID('IM05'),
|
||||||
|
MKID('IM06'),
|
||||||
|
MKID('IM07'),
|
||||||
|
MKID('IM08'),
|
||||||
|
MKID('IM09'),
|
||||||
|
MKID('IM0A'),
|
||||||
|
MKID('IM0B'),
|
||||||
|
MKID('IM0C'),
|
||||||
|
MKID('IM0D'),
|
||||||
|
MKID('IM0E'),
|
||||||
|
MKID('IM0F')
|
||||||
|
};
|
||||||
|
|
||||||
|
void Scumm::drawObject(int obj, int arg) {
|
||||||
|
ObjectData *od;
|
||||||
|
int xpos, ypos, height, width;
|
||||||
|
byte *ptr;
|
||||||
|
int x,a,b;
|
||||||
|
|
||||||
|
if (_BgNeedsRedraw)
|
||||||
|
arg = 0;
|
||||||
|
|
||||||
|
gdi.virtScreen = 0;
|
||||||
|
|
||||||
|
od = &objs[obj];
|
||||||
|
|
||||||
|
xpos = od->x_pos;
|
||||||
|
ypos = od->y_pos;
|
||||||
|
width = od->numstrips;
|
||||||
|
height = od->height;
|
||||||
|
|
||||||
|
if (width==0 || xpos > _screenEndStrip || xpos + width < _screenStartStrip)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (od->fl_object_index) {
|
||||||
|
ptr = getResourceAddress(0xD, od->fl_object_index);
|
||||||
|
ptr = findResource(MKID('OBIM'), ptr);
|
||||||
|
} else {
|
||||||
|
ptr = getResourceAddress(1, _roomResource);
|
||||||
|
ptr = ptr + od->offs_obim_to_room;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = findResource(state_tags[getState(od->obj_nr)], ptr);
|
||||||
|
if (!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
x = 0xFFFF;
|
||||||
|
|
||||||
|
for (a=b=0; a<width; a++) {
|
||||||
|
_drawBmpX = xpos + a;
|
||||||
|
if (arg==1 && _screenStartStrip!=_drawBmpX)
|
||||||
|
continue;
|
||||||
|
if (arg==2 && _screenEndStrip!=_drawBmpX)
|
||||||
|
continue;
|
||||||
|
if (_screenStartStrip > _drawBmpX || _drawBmpX > _screenEndStrip)
|
||||||
|
continue;
|
||||||
|
actorDrawBits[_drawBmpX] |= 0x8000;
|
||||||
|
if (_drawBmpX < x)
|
||||||
|
x = _drawBmpX;
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b==0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_drawBmpY = ypos << 3;
|
||||||
|
gdi.numLinesToProcess = height << 3;
|
||||||
|
|
||||||
|
_drawBmpX = x;
|
||||||
|
drawBmp(ptr, x - xpos, b, 1, "Object", od->obj_nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::loadRoomObjects() {
|
||||||
|
int i,j;
|
||||||
|
ObjectData *od;
|
||||||
|
byte *ptr;
|
||||||
|
uint16 obim_id;
|
||||||
|
byte *room,*tmp_room;
|
||||||
|
ImageHeader *imhd;
|
||||||
|
RoomHeader *roomhdr;
|
||||||
|
|
||||||
|
CodeHeader *cdhd;
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
|
||||||
|
room = getResourceAddress(1, _roomResource);
|
||||||
|
roomhdr = (RoomHeader*)findResource(MKID('RMHD'), room);
|
||||||
|
|
||||||
|
_numObjectsInRoom = READ_LE_UINT16(&roomhdr->numObjects);
|
||||||
|
|
||||||
|
if (_numObjectsInRoom == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_numObjectsInRoom > 200)
|
||||||
|
error("More than %d objects in room %d", 200, _roomResource);
|
||||||
|
|
||||||
|
tmp_room = room;
|
||||||
|
|
||||||
|
od = &objs[1];
|
||||||
|
for (i=1; i<=_numObjectsInRoom; i++,od++) {
|
||||||
|
ptr = findResource(MKID('OBCD'), tmp_room);
|
||||||
|
if (ptr==NULL)
|
||||||
|
error("Room %d missing object code block(s)", _roomResource);
|
||||||
|
|
||||||
|
od->offs_obcd_to_room = ptr - room;
|
||||||
|
cdhd = (CodeHeader*)findResource2(MKID('CDHD'), ptr);
|
||||||
|
od->obj_nr = READ_LE_UINT16(&cdhd->obj_id);
|
||||||
|
|
||||||
|
#ifdef DUMP_SCRIPTS
|
||||||
|
do {
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf,"roomobj-%d-",_roomResource);
|
||||||
|
dumpResource(buf, od->obj_nr, ptr);
|
||||||
|
} while (0);
|
||||||
|
#endif
|
||||||
|
tmp_room = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_room = room;
|
||||||
|
for (i=1; i<=_numObjectsInRoom; i++) {
|
||||||
|
ptr = findResource(MKID('OBIM'), tmp_room);
|
||||||
|
if (ptr==NULL)
|
||||||
|
error("Room %d missing image blocks(s)", _roomResource);
|
||||||
|
|
||||||
|
imhd = (ImageHeader*)findResource2(MKID('IMHD'), ptr);
|
||||||
|
obim_id = READ_LE_UINT16(&imhd->obj_id);
|
||||||
|
|
||||||
|
for(j=1; j<=_numObjectsInRoom; j++) {
|
||||||
|
if (objs[j].obj_nr==obim_id)
|
||||||
|
objs[j].offs_obim_to_room = ptr - room;
|
||||||
|
}
|
||||||
|
tmp_room = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
od = &objs[1];
|
||||||
|
for (i=1; i<=_numObjectsInRoom; i++,od++) {
|
||||||
|
ptr = room + objs[i].offs_obcd_to_room;
|
||||||
|
cdhd = (CodeHeader*)findResource2(MKID('CDHD'), ptr);
|
||||||
|
objs[i].obj_nr = READ_LE_UINT16(&cdhd->obj_id);
|
||||||
|
objs[i].numstrips = cdhd->w;
|
||||||
|
objs[i].height = cdhd->h;
|
||||||
|
objs[i].x_pos = cdhd->x;
|
||||||
|
objs[i].y_pos = cdhd->y;
|
||||||
|
|
||||||
|
if (!(cdhd->flags&0x80)) {
|
||||||
|
objs[i].cdhd_0e = 0x10;
|
||||||
|
} else {
|
||||||
|
objs[i].cdhd_0e = cdhd->flags;
|
||||||
|
}
|
||||||
|
objs[i].cdhd_0f = cdhd->unk1;
|
||||||
|
objs[i].cdhd_10 = READ_LE_UINT16(&cdhd->unk2);
|
||||||
|
objs[i].cdhd_12 = READ_LE_UINT16(&cdhd->unk3);
|
||||||
|
objs[i].actordir = cdhd->unk4;
|
||||||
|
objs[i].fl_object_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::fixObjectFlags() {
|
||||||
|
int i;
|
||||||
|
ObjectData *od = &objs[1];
|
||||||
|
for (i=1; i<=_numObjectsInRoom; i++,od++) {
|
||||||
|
od->ownerstate = _objectFlagTable[od->obj_nr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::processDrawQue() {
|
||||||
|
int i, j;
|
||||||
|
for (i=0; i<_drawObjectQueNr; i++) {
|
||||||
|
j = _drawObjectQue[i];
|
||||||
|
if (j)
|
||||||
|
drawObject(j,0);
|
||||||
|
}
|
||||||
|
_drawObjectQueNr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::clearOwnerOf(int obj) {
|
||||||
|
int i,j;
|
||||||
|
uint16 *a;
|
||||||
|
byte *ptr;
|
||||||
|
|
||||||
|
stopObjectScript(obj);
|
||||||
|
|
||||||
|
if (getOwner(obj)==0xF) {
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
if (objs[i].obj_nr==obj) {
|
||||||
|
if (!objs[i].fl_object_index)
|
||||||
|
return;
|
||||||
|
nukeResource(0xD, objs[i].fl_object_index);
|
||||||
|
objs[i].obj_nr = 0;
|
||||||
|
objs[i].fl_object_index = 0;
|
||||||
|
}
|
||||||
|
} while(++i <= _numObjectsInRoom);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i=1; i<_maxInventoryItems; i++) {
|
||||||
|
if (_inventory[i] == obj) {
|
||||||
|
j = whereIsObject(obj);
|
||||||
|
if (j==0) {
|
||||||
|
nukeResource(5, i);
|
||||||
|
_inventory[i] = 0;
|
||||||
|
}
|
||||||
|
a = &_inventory[2];
|
||||||
|
for (i=1; i < _maxInventoryItems-1; i++) {
|
||||||
|
if (!a[-1] && a[0]) {
|
||||||
|
a[-1] = a[0];
|
||||||
|
ptr = getResourceAddress(5, i+1);
|
||||||
|
_baseInventoryItems[i] = _baseInventoryItems[i+1];
|
||||||
|
/* TODO: some wacky write is done here */
|
||||||
|
error("clearOwnerOf: not fully implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::removeObjectFromRoom(int obj) {
|
||||||
|
int i,cnt;
|
||||||
|
uint16 *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;
|
||||||
|
do {
|
||||||
|
*ptr++ |= 0x8000;
|
||||||
|
} while (--cnt);
|
||||||
|
}
|
||||||
|
_BgNeedsRedraw = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::addObjectToDrawQue(int object) {
|
||||||
|
_drawObjectQue[_drawObjectQueNr++] = object;
|
||||||
|
if (_drawObjectQueNr > 200)
|
||||||
|
error("Draw Object Que overflow");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::clearDrawObjectQueue() {
|
||||||
|
_drawObjectQueNr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *Scumm::getObjOrActorName(int obj) {
|
||||||
|
byte *objptr;
|
||||||
|
|
||||||
|
if (obj <= vm.vars[VAR_NUM_ACTOR])
|
||||||
|
return getActorName(derefActorSafe(obj, "getObjOrActorName"));
|
||||||
|
|
||||||
|
objptr = getObjectAddress(obj);
|
||||||
|
if (objptr==NULL)
|
||||||
|
return (byte*)" ";
|
||||||
|
|
||||||
|
return findResource(MKID('OBNA'), objptr) + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Scumm::getOBCDOffs(int object) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((_objectFlagTable[object]&0xF)!=0xF)
|
||||||
|
return 0;
|
||||||
|
for (i=_numObjectsInRoom; i>0; i--) {
|
||||||
|
if (objs[i].obj_nr == object) {
|
||||||
|
if (objs[i].fl_object_index!=0)
|
||||||
|
return 8;
|
||||||
|
return objs[i].offs_obcd_to_room;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *Scumm::getObjectAddress(int obj) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((_objectFlagTable[obj]&0xF)!=0xF) {
|
||||||
|
for(i=0; i<_maxInventoryItems; i++) {
|
||||||
|
if (_inventory[i] == obj)
|
||||||
|
return getResourceAddress(5, i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(i=_numObjectsInRoom; i>0; --i) {
|
||||||
|
if (objs[i].obj_nr==obj) {
|
||||||
|
if (objs[i].fl_object_index)
|
||||||
|
return getResourceAddress(0xD, objs[i].fl_object_index)+8;
|
||||||
|
return getResourceAddress(1, _roomResource) + objs[i].offs_obcd_to_room;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::addObjectToInventory(int obj, int room) {
|
||||||
|
int i, slot;
|
||||||
|
byte *ptr,*obcdptr;
|
||||||
|
uint32 size,cdoffs;
|
||||||
|
int numobj;
|
||||||
|
byte *tmp_roomptr,*roomptr;
|
||||||
|
CodeHeader *cdhd;
|
||||||
|
RoomHeader *roomhdr;
|
||||||
|
|
||||||
|
debug(1,"Adding object %d from room %d into inventory", obj, room);
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
|
||||||
|
if (whereIsObject(obj)==4) {
|
||||||
|
i = getObjectIndex(obj);
|
||||||
|
ptr = getResourceAddress(0xD, objs[i].fl_object_index) + 64;
|
||||||
|
size = READ_BE_UINT32_UNALIGNED(ptr+4);
|
||||||
|
slot = getInventorySlot();
|
||||||
|
_inventory[slot] = obj;
|
||||||
|
createResource(5, slot, size);
|
||||||
|
ptr = getResourceAddress(0xD, objs[i].fl_object_index) + 64;
|
||||||
|
memcpy(getResourceAddress(5, slot), ptr, size);
|
||||||
|
checkHeap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ensureResourceLoaded(1, room);
|
||||||
|
roomptr = getResourceAddress(1, room);
|
||||||
|
roomhdr = (RoomHeader*)findResource(MKID('RMHD'), roomptr);
|
||||||
|
numobj = READ_LE_UINT16(&roomhdr->numObjects);
|
||||||
|
if (numobj==0)
|
||||||
|
error("addObjectToInventory: No object found in room %d", room);
|
||||||
|
if (numobj > 200)
|
||||||
|
error("addObjectToInventory: More (%d) than %d objects in room %d", numobj, 200, room);
|
||||||
|
|
||||||
|
tmp_roomptr = roomptr;
|
||||||
|
for (i=1; i<=numobj; i++) {
|
||||||
|
obcdptr = findResource(MKID('OBCD'), tmp_roomptr);
|
||||||
|
if(obcdptr==NULL)
|
||||||
|
error("addObjectToInventory: Not enough code blocks in room %d", room);
|
||||||
|
cdhd = (CodeHeader*)findResource2(MKID('CDHD'), obcdptr);
|
||||||
|
if ( READ_LE_UINT16(&cdhd->obj_id) == obj) {
|
||||||
|
cdoffs = obcdptr - roomptr;
|
||||||
|
size = READ_BE_UINT32_UNALIGNED(obcdptr+4);
|
||||||
|
slot = getInventorySlot();
|
||||||
|
_inventory[slot] = obj;
|
||||||
|
createResource(5, slot, size);
|
||||||
|
obcdptr = getResourceAddress(1, room) + cdoffs;
|
||||||
|
memcpy(getResourceAddress(5,slot),obcdptr,size);
|
||||||
|
checkHeap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tmp_roomptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
error("addObjectToInventory: Object %d not found in room %d", obj, room);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getInventorySlot() {
|
||||||
|
int i;
|
||||||
|
for (i=1; i<=_maxInventoryItems; i++) {
|
||||||
|
if (_inventory[i]==0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
error("Inventory full, %d max items", _maxInventoryItems);
|
||||||
|
}
|
||||||
|
|
48
readme.txt
Normal file
48
readme.txt
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
2001-10-08
|
||||||
|
|
||||||
|
This is the first pre-alpha release of ScummVM. It is an implementation of the SCUMM engine used in various Lucas Arts games such as Monkey Island and Day of the Tentacle.
|
||||||
|
|
||||||
|
The engine is far from complete, and thus only Monkey Island 2 is supported at the moment.
|
||||||
|
|
||||||
|
Please be aware that the engine contains bugs and non-implemented-features that make it impossible to finish the game. Other stuff that's missing is sound and savegames.
|
||||||
|
|
||||||
|
Compiling:
|
||||||
|
--------
|
||||||
|
You need SDL-1.2.2 (maybe older versions will work), and a supported compiler. At the moment only GCC and Microsoft Visual C++ are supported.
|
||||||
|
|
||||||
|
GCC:
|
||||||
|
----
|
||||||
|
* Edit the makefile and replace /usr/local/include/SDL/ with the path to your SDL include files.
|
||||||
|
If your processor architecture is big endian, replace -DSCUMM_LITTLE_ENDIAN by -DSCUMM_BIG_ENDIAN -DSCUMM_NEED_ALIGNMENT
|
||||||
|
* Now type make (or gmake if that's what GNU make is called on your system) and hopefully ScummVM will compile for you.
|
||||||
|
|
||||||
|
Please note that big endian support is preliminary and contains bugs.
|
||||||
|
|
||||||
|
|
||||||
|
Microsoft Visual C++:
|
||||||
|
---------------------
|
||||||
|
* Open the workspace, scummwm.dsw
|
||||||
|
* If you want to compile the GDI version, remove sdl.cpp from the project and add windows.cpp.
|
||||||
|
for the SDL version, remove windows.cpp from the project and add sdl.cpp.
|
||||||
|
* Enter the path to the SDL include files in Tools|Options|Directories
|
||||||
|
* Now it should compile successfully.
|
||||||
|
|
||||||
|
|
||||||
|
Running:
|
||||||
|
--------
|
||||||
|
Before you run the engine, you need to put the game's datafiles in the same directory as the scummvm executable. The filenames must be in lowercase (monkey2.000 and monkey2.001).
|
||||||
|
|
||||||
|
|
||||||
|
Good Luck,
|
||||||
|
Ludvig Strigeus
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
647
resource.cpp
Normal file
647
resource.cpp
Normal file
|
@ -0,0 +1,647 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:14 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
/* Open a room */
|
||||||
|
void Scumm::openRoom(int room) {
|
||||||
|
uint room_offs;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
debug(9, "openRoom(%d)",room);
|
||||||
|
|
||||||
|
/* Don't load the same room again */
|
||||||
|
if (_lastLoadedRoom == room)
|
||||||
|
return;
|
||||||
|
_lastLoadedRoom = room;
|
||||||
|
|
||||||
|
/* Room -1 means close file */
|
||||||
|
if (room==-1) {
|
||||||
|
_encbyte = 0;
|
||||||
|
deleteRoomOffsets();
|
||||||
|
fileClose(_fileHandle);
|
||||||
|
_fileHandle = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Either xxx.lfl or monkey.xxx file name */
|
||||||
|
while (!_resFilePrefix) {
|
||||||
|
#if REAL_CODE
|
||||||
|
room_offs = _roomFileOffsets[room];
|
||||||
|
#else
|
||||||
|
room_offs = room ? _roomFileOffsets[room] : 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (room_offs == 0xFFFFFFFF)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (room_offs != 0 && room != 0) {
|
||||||
|
_fileOffset = _roomFileOffsets[room];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (room==0) {
|
||||||
|
sprintf(buf, "%s.000", _exe_name);
|
||||||
|
} else {
|
||||||
|
sprintf(buf, "%s.%.3d", _exe_name, res.roomno[1][room]);
|
||||||
|
}
|
||||||
|
_encbyte = 0x69;
|
||||||
|
if (openResourceFile(buf)) {
|
||||||
|
if (room==0)
|
||||||
|
return;
|
||||||
|
readRoomsOffsets();
|
||||||
|
_fileOffset = _roomFileOffsets[room];
|
||||||
|
|
||||||
|
if (_fileOffset != 8)
|
||||||
|
return;
|
||||||
|
|
||||||
|
error("Room %d not in %s", room, buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
askForDisk();
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
sprintf(buf, "%.3d.lfl", room);
|
||||||
|
_encbyte = 0;
|
||||||
|
if (openResourceFile(buf))
|
||||||
|
break;
|
||||||
|
askForDisk();
|
||||||
|
} while(1);
|
||||||
|
|
||||||
|
deleteRoomOffsets();
|
||||||
|
_fileOffset = 0; /* start of file */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete the currently loaded room offsets */
|
||||||
|
void Scumm::deleteRoomOffsets() {
|
||||||
|
if (!_dynamicRoomOffsets)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i=0; i<_maxRooms; i++) {
|
||||||
|
if (_roomFileOffsets[i]!=0xFFFFFFFF)
|
||||||
|
_roomFileOffsets[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read room offsets */
|
||||||
|
void Scumm::readRoomsOffsets() {
|
||||||
|
int num,room;
|
||||||
|
|
||||||
|
debug(9, "readRoomOffsets()");
|
||||||
|
|
||||||
|
deleteRoomOffsets();
|
||||||
|
if (!_dynamicRoomOffsets)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fileSeek(_fileHandle, 16, SEEK_SET);
|
||||||
|
|
||||||
|
num = fileReadByte();
|
||||||
|
while (num) {
|
||||||
|
num--;
|
||||||
|
|
||||||
|
room = fileReadByte();
|
||||||
|
if (_roomFileOffsets[room]!=0xFFFFFFFF) {
|
||||||
|
_roomFileOffsets[room] = fileReadDwordLE();
|
||||||
|
} else {
|
||||||
|
fileReadDwordLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scumm::openResourceFile(const char *filename) {
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
debug(9, "openResourceFile(%s)",filename);
|
||||||
|
|
||||||
|
if (_resFilePath) {
|
||||||
|
sprintf(buf, "%s.%d\\%s", _resFilePath, _resFilePathId, filename);
|
||||||
|
} else if (_resFilePrefix) {
|
||||||
|
sprintf(buf, "%s%s", _resFilePrefix, filename);
|
||||||
|
} else {
|
||||||
|
strcpy(buf, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_fileHandle != NULL) {
|
||||||
|
fileClose(_fileHandle);
|
||||||
|
_fileHandle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fileHandle = fileOpen(buf, 1);
|
||||||
|
|
||||||
|
return _fileHandle != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::askForDisk() {
|
||||||
|
/* TODO: Not yet implemented */
|
||||||
|
error("askForDisk: not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scumm::readIndexFile(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(6,MKID('CHAR'),"charset");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MKID('DOBJ'):
|
||||||
|
_maxNrObjects = fileReadWordLE();
|
||||||
|
_objectFlagTable = (byte*)alloc(_maxNrObjects);
|
||||||
|
if (mode==1) {
|
||||||
|
fileSeek(_fileHandle, itemsize - 10, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_classData = (uint32*)alloc(_maxNrObjects * sizeof(uint32));
|
||||||
|
fileRead(_fileHandle, _objectFlagTable, _maxNrObjects);
|
||||||
|
fileRead(_fileHandle, _classData, _maxNrObjects * sizeof(uint32));
|
||||||
|
#if defined(SCUMM_BIG_ENDIAN)
|
||||||
|
for (i=0; i<_maxNrObjects; i++)
|
||||||
|
_classData[i] = FROM_LE_32(_classData[i]);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MKID('RNAM'):
|
||||||
|
fileSeek(_fileHandle, itemsize-8,1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MKID('DROO'):
|
||||||
|
readResTypeList(1,MKID('ROOM'),"room");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MKID('DSCR'):
|
||||||
|
readResTypeList(2,MKID('SCRP'),"script");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MKID('DCOS'):
|
||||||
|
readResTypeList(3,MKID('COST'),"costume");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MKID('MAXS'):
|
||||||
|
fileReadWordLE();
|
||||||
|
fileReadWordLE();
|
||||||
|
fileReadWordLE();
|
||||||
|
fileReadWordLE();
|
||||||
|
fileReadWordLE();
|
||||||
|
fileReadWordLE();
|
||||||
|
fileReadWordLE();
|
||||||
|
fileReadWordLE();
|
||||||
|
fileReadWordLE();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MKID('DSOU'):
|
||||||
|
readResTypeList(4,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);
|
||||||
|
|
||||||
|
_numGlobalScriptsUsed = _maxScripts;
|
||||||
|
_dynamicRoomOffsets = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::readResTypeList(int id, uint32 tag, const char *name) {
|
||||||
|
int num;
|
||||||
|
#if defined(SCUMM_BIG_ENDIAN)
|
||||||
|
int i;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
debug(9, "readResTypeList(%d,%x,%s)",id,FROM_LE_32(tag),name);
|
||||||
|
|
||||||
|
num = fileReadWordLE();
|
||||||
|
|
||||||
|
if (num>0xFF) {
|
||||||
|
error("Too many %ss (%d) in directory", name, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
allocResTypeData(id, tag, num, name, 1);
|
||||||
|
|
||||||
|
fileRead(_fileHandle, res.roomno[id], num);
|
||||||
|
fileRead(_fileHandle, res.roomoffs[id], num*sizeof(uint32));
|
||||||
|
|
||||||
|
#if defined(SCUMM_BIG_ENDIAN)
|
||||||
|
for (i=0; i<num; i++)
|
||||||
|
res.roomoffs[id][i] = FROM_LE_32(res.roomoffs[id][i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::allocResTypeData(int id, uint32 tag, int num, const char *name, int mode) {
|
||||||
|
debug(9, "allocResTypeData(%d,%x,%d,%s,%d)",id,FROM_LE_32(tag),num,name,mode);
|
||||||
|
res.mode[id] = mode;
|
||||||
|
res.num[id] = num;
|
||||||
|
res.tags[id] = tag;
|
||||||
|
res.name[id] = name;
|
||||||
|
res.address[id] = (byte**)alloc(num*sizeof(void*));
|
||||||
|
res.flags[id] = (byte*)alloc(num*sizeof(byte));
|
||||||
|
|
||||||
|
if (mode) {
|
||||||
|
res.roomno[id] = (byte*)alloc(num*sizeof(byte));
|
||||||
|
res.roomoffs[id] = (uint32*)alloc(num*sizeof(uint32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::loadCharset(int no) {
|
||||||
|
int i;
|
||||||
|
byte *ptr;
|
||||||
|
|
||||||
|
debug(9, "loadCharset(%d)",no);
|
||||||
|
|
||||||
|
checkRange(_maxCharsets-1, 1, no, "Loading illegal charset %d");
|
||||||
|
ensureResourceLoaded(6, no);
|
||||||
|
ptr = getResourceAddress(6, no);
|
||||||
|
|
||||||
|
for (i=0; i<15; i++) {
|
||||||
|
_charsetData[no][i+1] = ptr[i+14];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::nukeCharset(int i) {
|
||||||
|
checkRange(_maxCharsets-1, 1, i, "Nuking illegal charset %d");
|
||||||
|
nukeResource(6, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::ensureResourceLoaded(int type, int i) {
|
||||||
|
void *addr;
|
||||||
|
|
||||||
|
debug(9, "ensureResourceLoaded(%d,%d)", type, i);
|
||||||
|
|
||||||
|
if (type==1 && i>127) {
|
||||||
|
i = _resourceMapper[i&127];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i==0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
addr = res.address[type][i];
|
||||||
|
if (addr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
loadResource(type, i);
|
||||||
|
|
||||||
|
if (type==1 && i==_roomResource)
|
||||||
|
vm.vars[VAR_ROOM_FLAG] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::loadResource(int type, int index) {
|
||||||
|
int roomNr, i;
|
||||||
|
uint32 fileOffs;
|
||||||
|
uint32 size, tag;
|
||||||
|
|
||||||
|
debug(9, "loadResource(%d,%d)", type,index);
|
||||||
|
|
||||||
|
roomNr = getResourceRoomNr(type, index);
|
||||||
|
if (roomNr == 0 || index >= res.num[type]) {
|
||||||
|
error("%s %d undefined",
|
||||||
|
res.name[type],index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type==1) {
|
||||||
|
fileOffs = 0;
|
||||||
|
} else {
|
||||||
|
fileOffs = res.roomoffs[type][index];
|
||||||
|
if (fileOffs==0xFFFFFFFF)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
for (i=0; i<5; i++) {
|
||||||
|
_resIndexToLoad = index;
|
||||||
|
_resTypeToLoad = type;
|
||||||
|
openRoom(roomNr);
|
||||||
|
|
||||||
|
fileSeek(_fileHandle, fileOffs + _fileOffset, SEEK_SET);
|
||||||
|
if (type==4) {
|
||||||
|
fileReadDwordLE();
|
||||||
|
fileReadDwordLE();
|
||||||
|
return readSoundResource(type, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = fileReadDword();
|
||||||
|
|
||||||
|
if (tag != res.tags[type]) {
|
||||||
|
error("%s %d not in room %d at %d+%d",
|
||||||
|
res.name[type], type, roomNr, _fileOffset, fileOffs);
|
||||||
|
}
|
||||||
|
|
||||||
|
size = fileReadDwordBE();
|
||||||
|
fileSeek(_fileHandle, -8, SEEK_CUR);
|
||||||
|
|
||||||
|
fileRead(_fileHandle, createResource(type, index, size), size);
|
||||||
|
|
||||||
|
/* dump the resource */
|
||||||
|
#ifdef DUMP_SCRIPTS
|
||||||
|
if(type==2) {
|
||||||
|
dumpResource("script-", index, getResourceAddress(2, index));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!fileReadFailed(_fileHandle)) {
|
||||||
|
_scummTimer = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nukeResource(type, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
error("Cannot read resource");
|
||||||
|
} while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::readSoundResource(int type, int index) {
|
||||||
|
uint32 resStart, size, tag, size2;
|
||||||
|
byte *ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
debug(9, "readSoundResource(%d,%d)", type, index);
|
||||||
|
|
||||||
|
resStart = 0;
|
||||||
|
|
||||||
|
fileReadDwordLE();
|
||||||
|
size = fileReadDwordBE();
|
||||||
|
|
||||||
|
while (size>resStart) {
|
||||||
|
tag = fileReadDword();
|
||||||
|
size2 = fileReadDwordBE();
|
||||||
|
|
||||||
|
resStart += size2 + 8;
|
||||||
|
|
||||||
|
for (i=0,ptr=_soundTagTable; i<_numSoundTags; i++,ptr+=5) {
|
||||||
|
/* endian OK, tags are in native format */
|
||||||
|
if (READ_UINT32_UNALIGNED(ptr) == tag) {
|
||||||
|
fileSeek(_fileHandle, -8, SEEK_CUR);
|
||||||
|
fileRead(_fileHandle,createResource(type, index, size2+8), size+8);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileSeek(_fileHandle, size2, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.roomoffs[type][index] = 0xFFFFFFFF;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Scumm::getResourceRoomNr(int type, int index) {
|
||||||
|
if (type==1)
|
||||||
|
return index;
|
||||||
|
return res.roomno[type][index];
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *Scumm::getResourceAddress(int type, int index) {
|
||||||
|
byte *ptr;
|
||||||
|
|
||||||
|
debug(9, "getResourceAddress(%d,%d)", type, index);
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
|
||||||
|
validateResource("getResourceAddress", type, index);
|
||||||
|
|
||||||
|
if (res.mode[type] && !res.address[type][index]) {
|
||||||
|
ensureResourceLoaded(type, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
setResourceFlags(type, index, 1);
|
||||||
|
|
||||||
|
ptr=(byte*)res.address[type][index];
|
||||||
|
if (!ptr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ptr + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::setResourceFlags(int type, int index, byte flag) {
|
||||||
|
res.flags[type][index] &= 0x80;
|
||||||
|
res.flags[type][index] |= flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *Scumm::createResource(int type, int index, uint32 size) {
|
||||||
|
byte *ptr;
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
|
||||||
|
debug(9, "createResource(%d,%d,%d)", type, index,size);
|
||||||
|
|
||||||
|
if (size > 65536*4+37856)
|
||||||
|
error("Invalid size allocating");
|
||||||
|
|
||||||
|
validateResource("allocating", type, index);
|
||||||
|
nukeResource(type, index);
|
||||||
|
|
||||||
|
ptr = (byte*)alloc(size + 8);
|
||||||
|
if (ptr==NULL) {
|
||||||
|
error("Out of memory while allocating %d", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.address[type][index] = ptr;
|
||||||
|
|
||||||
|
setResourceFlags(type, index, 1);
|
||||||
|
|
||||||
|
return ptr + 8; /* skip header */
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::validateResource(const char *str, int type, int index) {
|
||||||
|
if (type<1 || type>15 || index<0 || index >= res.num[type]) {
|
||||||
|
error("%d Illegal Glob type %d num %d", str, type, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::nukeResource(int type, int index) {
|
||||||
|
|
||||||
|
debug(9, "nukeResource(%d,%d)", type, index);
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
assert( res.address[type] );
|
||||||
|
assert( index>=0 && index < res.num[type]);
|
||||||
|
|
||||||
|
if (res.address[type][index]) {
|
||||||
|
free(res.address[type][index]);
|
||||||
|
res.address[type][index] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkResourceProc() {
|
||||||
|
int i;
|
||||||
|
for (i=1; i<16; i++) {
|
||||||
|
}
|
||||||
|
/* TODO: not implemented */
|
||||||
|
warning("unkResourceProc: not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
byte *Scumm::findResource(uint32 tag, byte *searchin) {
|
||||||
|
uint32 size;
|
||||||
|
|
||||||
|
if (searchin) {
|
||||||
|
searchin+=4;
|
||||||
|
_findResSize = READ_BE_UINT32_UNALIGNED(searchin);
|
||||||
|
_findResHeaderSize = 8;
|
||||||
|
_findResPos = searchin+4;
|
||||||
|
goto startScan;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
size = READ_BE_UINT32_UNALIGNED(_findResPos+4);
|
||||||
|
if ((int32)size <= 0) {
|
||||||
|
error("(%c%c%c%c) Not found in %d... illegal block len %d",
|
||||||
|
tag&0xFF,(tag>>8)&0xFF,(tag>>16)&0xFF,(tag>>24)&0xFF,
|
||||||
|
0,
|
||||||
|
size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
_findResHeaderSize += size;
|
||||||
|
_findResPos += size;
|
||||||
|
|
||||||
|
startScan:;
|
||||||
|
if (_findResHeaderSize >= _findResSize)
|
||||||
|
return NULL;
|
||||||
|
/* endian OK, tags are in native format */
|
||||||
|
} while (READ_UINT32_UNALIGNED(_findResPos) != tag);
|
||||||
|
|
||||||
|
return _findResPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *Scumm::findResource2(uint32 tag, byte *searchin) {
|
||||||
|
uint32 size;
|
||||||
|
|
||||||
|
if (searchin) {
|
||||||
|
searchin+=4;
|
||||||
|
_findResSize2 = READ_BE_UINT32_UNALIGNED(searchin);
|
||||||
|
_findResHeaderSize2 = 8;
|
||||||
|
_findResPos2 = searchin+4;
|
||||||
|
goto startScan;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
size = READ_BE_UINT32_UNALIGNED(_findResPos2+4);
|
||||||
|
if ((int32)size <= 0) {
|
||||||
|
error("(%c%c%c%c) Not found in %d... illegal block len %d",
|
||||||
|
tag&0xFF,(tag>>8)&0xFF,(tag>>16)&0xFF,(tag>>24)&0xFF,
|
||||||
|
0,
|
||||||
|
size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
_findResHeaderSize2 += size;
|
||||||
|
_findResPos2 += size;
|
||||||
|
|
||||||
|
startScan:;
|
||||||
|
if (_findResHeaderSize2 >= _findResSize2)
|
||||||
|
return NULL;
|
||||||
|
/* endian OK, tags are in native format */
|
||||||
|
} while (READ_UINT32_UNALIGNED(_findResPos2) != tag);
|
||||||
|
return _findResPos2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::lock(int type, int i) {
|
||||||
|
validateResource("Locking", type, i);
|
||||||
|
res.flags[type][i] |= 0x80;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unlock(int type, int i) {
|
||||||
|
validateResource("Unlocking", type, i);
|
||||||
|
res.flags[type][i] &= ~0x7F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::loadPtrToResource(int type, int resindex, byte *source) {
|
||||||
|
byte *ptr, *alloced;
|
||||||
|
int i,len;
|
||||||
|
|
||||||
|
nukeResource(type, resindex);
|
||||||
|
if (!source) {
|
||||||
|
ptr = _scriptPointer;
|
||||||
|
} else {
|
||||||
|
ptr = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
do {
|
||||||
|
i = *ptr++;
|
||||||
|
if (!i) break;
|
||||||
|
len++;
|
||||||
|
if (i==0xFF)
|
||||||
|
ptr += 3, len += 3;
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
if (++len <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
alloced = createResource(type, resindex, len);
|
||||||
|
|
||||||
|
if (!source) {
|
||||||
|
alloced[0] = fetchScriptByte();
|
||||||
|
for (i=1; i<len; i++)
|
||||||
|
alloced[i] = *_scriptPointer++;
|
||||||
|
} else {
|
||||||
|
for(i=0; i<len; i++)
|
||||||
|
alloced[i] = source[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::heapClear(int mode) {
|
||||||
|
/* TODO: implement this */
|
||||||
|
warning("heapClear: not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scumm::unkHeapProc2(int a, int b) {
|
||||||
|
warning("unkHeapProc2: not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkResProc(int a, int b) {
|
||||||
|
error("unkResProc:not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
59
saveload.cpp
Normal file
59
saveload.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:13 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool Scumm::saveState(const char *filename) {
|
||||||
|
FILE *out = fopen(filename,"wb");
|
||||||
|
if (out==NULL)
|
||||||
|
return false;
|
||||||
|
saveOrLoad(out,true);
|
||||||
|
fclose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scumm::loadState(const char *filename) {
|
||||||
|
FILE *out = fopen(filename,"rb");
|
||||||
|
if (out==NULL)
|
||||||
|
return false;
|
||||||
|
saveOrLoad(out,false);
|
||||||
|
fclose(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::saveOrLoad(FILE *inout, bool mode) {
|
||||||
|
_saveLoadStream = inout;
|
||||||
|
_saveOrLoad = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scumm::saveLoadBytes(void *b, int len) {
|
||||||
|
if (_saveOrLoad)
|
||||||
|
fwrite(b, 1, len, _saveLoadStream);
|
||||||
|
else
|
||||||
|
fread(b, 1, len, _saveLoadStream);
|
||||||
|
}
|
2857
script.cpp
Normal file
2857
script.cpp
Normal file
File diff suppressed because it is too large
Load diff
152
scummsys.h
Normal file
152
scummsys.h
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:14 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
|
||||||
|
#define SCUMM_LITTLE_ENDIAN
|
||||||
|
|
||||||
|
#define FORCEINLINE __forceinline
|
||||||
|
#define NORETURN _declspec(noreturn)
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
typedef unsigned short uint16;
|
||||||
|
typedef unsigned long uint32;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef signed char int8;
|
||||||
|
typedef signed short int16;
|
||||||
|
typedef signed long int32;
|
||||||
|
|
||||||
|
#define START_PACK_STRUCTS pack (push,1)
|
||||||
|
#define END_PACK_STRUCTS pack(pop)
|
||||||
|
|
||||||
|
#elif defined(UNIX)
|
||||||
|
|
||||||
|
#define FORCEINLINE inline
|
||||||
|
#define NORETURN
|
||||||
|
#define CDECL
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
typedef unsigned short uint16;
|
||||||
|
typedef unsigned long uint32;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef signed char int8;
|
||||||
|
typedef signed short int16;
|
||||||
|
typedef signed long int32;
|
||||||
|
|
||||||
|
#define START_PACK_STRUCTS pack (1)
|
||||||
|
#define END_PACK_STRUCTS pack ()
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error No system type defined
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(SCUMM_LITTLE_ENDIAN)
|
||||||
|
|
||||||
|
#if defined(SCUMM_NEED_ALIGNMENT)
|
||||||
|
#error Little endian processors that need alignment is not implemented
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MKID(a) ((((a)>>24)&0xFF) | (((a)>>8)&0xFF00) | (((a)<<8)&0xFF0000) | (((a)<<24)&0xFF000000))
|
||||||
|
|
||||||
|
int FORCEINLINE READ_LE_UINT16(void *ptr) {
|
||||||
|
return *(uint16*)(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FORCEINLINE READ_BE_UINT16(void *ptr) {
|
||||||
|
return (((byte*)ptr)[0]<<8)|((byte*)ptr)[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 FORCEINLINE READ_LE_UINT32(void *ptr) {
|
||||||
|
return *(uint32*)(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 FORCEINLINE READ_BE_UINT32(void *ptr) {
|
||||||
|
byte *b = (byte*)ptr;
|
||||||
|
return (b[0]<<24)+(b[1]<<16)+(b[2]<<8)+(b[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define READ_BE_UINT32_UNALIGNED READ_BE_UINT32
|
||||||
|
#define READ_BE_UINT16_UNALIGNED READ_BE_UINT16
|
||||||
|
|
||||||
|
#define READ_UINT32_UNALIGNED(a) (*((uint32*)a))
|
||||||
|
|
||||||
|
#define FROM_LE_32(__a__) __a__
|
||||||
|
#define FROM_LE_16(__a__) __a__
|
||||||
|
|
||||||
|
#define TO_BE_32(a) ((((a)>>24)&0xFF) | (((a)>>8)&0xFF00) | (((a)<<8)&0xFF0000) | (((a)<<24)&0xFF000000))
|
||||||
|
|
||||||
|
#elif defined(SCUMM_BIG_ENDIAN)
|
||||||
|
|
||||||
|
#define MKID(a) (a)
|
||||||
|
|
||||||
|
uint32 FORCEINLINE FROM_LE_32(uint32 a) {
|
||||||
|
return ((a>>24)&0xFF) + ((a>>8)&0xFF00) + ((a<<8)&0xFF0000) + ((a<<24)&0xFF000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 FORCEINLINE FROM_LE_16(uint16 a) {
|
||||||
|
return ((a>>8)&0xFF) + ((a<<8)&0xFF00);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 FORCEINLINE READ_LE_UINT32(void *ptr) {
|
||||||
|
byte *b = (byte*)ptr;
|
||||||
|
return (b[3]<<24)+(b[2]<<16)+(b[1]<<8)+(b[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 FORCEINLINE READ_BE_UINT32(void *ptr) {
|
||||||
|
return *(uint32*)(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FORCEINLINE READ_LE_UINT16(void *ptr) {
|
||||||
|
byte *b = (byte*)ptr;
|
||||||
|
return (b[1]<<8) + b[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
int FORCEINLINE READ_BE_UINT16(void *ptr) {
|
||||||
|
return *(uint16*)(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FORCEINLINE READ_BE_UINT16_UNALIGNED(void *ptr) {
|
||||||
|
return (((byte*)ptr)[0]<<8)|((byte*)ptr)[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32 FORCEINLINE READ_BE_UINT32_UNALIGNED(void *ptr) {
|
||||||
|
byte *b = (byte*)ptr;
|
||||||
|
return (b[0]<<24)+(b[1]<<16)+(b[2]<<8)+(b[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define READ_UINT32_UNALIGNED READ_BE_UINT32_UNALIGNED
|
||||||
|
|
||||||
|
#define TO_BE_32(a) (a)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error No endianness defined
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
810
scummvm.cpp
Normal file
810
scummvm.cpp
Normal file
|
@ -0,0 +1,810 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:13 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
void Scumm::initThings() {
|
||||||
|
readIndexFile(1);
|
||||||
|
|
||||||
|
allocResTypeData(5, MKID('NONE'), 0x50, "inventory", 0);
|
||||||
|
allocResTypeData(12,MKID('NONE'),10, "temp", 0);
|
||||||
|
allocResTypeData(11,MKID('NONE'),5, "scale table", 0);
|
||||||
|
allocResTypeData(9, MKID('NONE'),13,"actor name", 0);
|
||||||
|
allocResTypeData(10, MKID('NONE'),10,"buffer", 0);
|
||||||
|
allocResTypeData(8, MKID('NONE'),100,"verb", 0);
|
||||||
|
allocResTypeData(7, MKID('NONE'),0x32,"string", 0);
|
||||||
|
allocResTypeData(13, MKID('NONE'),0x32,"flobject", 0);
|
||||||
|
allocResTypeData(14, MKID('NONE'),10,"boxes", 0);
|
||||||
|
|
||||||
|
readIndexFile(2);
|
||||||
|
|
||||||
|
initVideoMode();
|
||||||
|
initKbdAndMouse();
|
||||||
|
detectSound();
|
||||||
|
|
||||||
|
initRandSeeds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::initVideoMode() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::initKbdAndMouse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::detectSound() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::initRandSeeds() {
|
||||||
|
_randSeed1 = 0xA943DE35;
|
||||||
|
_randSeed2 = 0x37A9ED27;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Scumm::getRandomNumber(uint max) {
|
||||||
|
/* TODO: my own random number generator */
|
||||||
|
_randSeed1 = 0xDEADBEEF * (_randSeed1 + 1);
|
||||||
|
_randSeed1 = (_randSeed1>>13) | (_randSeed1<<19);
|
||||||
|
return _randSeed1%(max+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::scummInit() {
|
||||||
|
int i;
|
||||||
|
Actor *a;
|
||||||
|
|
||||||
|
debug(9, "scummInit");
|
||||||
|
readIndexFile(3);
|
||||||
|
loadCharset(1);
|
||||||
|
initScreens(0, 16, 320, 144);
|
||||||
|
|
||||||
|
setShake(0);
|
||||||
|
setCursor(0);
|
||||||
|
|
||||||
|
for (i=1,a=getFirstActor(); ++a,i<13; i++) {
|
||||||
|
a->number = i;
|
||||||
|
initActor(a, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(vm.vars, 0, sizeof(vm.vars));
|
||||||
|
memset(vm.bitvars, 0, sizeof(vm.bitvars));
|
||||||
|
memset(vm.scriptoffs, 0, sizeof(vm.scriptoffs));
|
||||||
|
memset(vm.inventory, 0, sizeof(vm.inventory));
|
||||||
|
|
||||||
|
_defaultTalkDelay = 60;
|
||||||
|
vm.vars[37] = 4;
|
||||||
|
|
||||||
|
_numNestedScripts = 0;
|
||||||
|
vm.cutSceneStackPointer = 0;
|
||||||
|
|
||||||
|
memset(vm.cutScenePtr, 0, sizeof(vm.cutScenePtr));
|
||||||
|
memset(vm.cutSceneData, 0, sizeof(vm.cutSceneData));
|
||||||
|
|
||||||
|
for (i=0; i<_maxVerbs; i++) {
|
||||||
|
verbs[i].verbid = 0;
|
||||||
|
verbs[i].right = 319;
|
||||||
|
verbs[i].oldleft = -1;
|
||||||
|
verbs[i].type = 0;
|
||||||
|
verbs[i].color = 2;
|
||||||
|
verbs[i].hicolor = 0;
|
||||||
|
verbs[i].charset_nr = 1;
|
||||||
|
verbs[i].curmode = 0;
|
||||||
|
verbs[i].saveid = 0;
|
||||||
|
verbs[i].center=0;
|
||||||
|
verbs[i].key = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
camera._leftTrigger = 10;
|
||||||
|
camera._rightTrigger = 30;
|
||||||
|
camera._mode = 0;
|
||||||
|
camera._follows = 0;
|
||||||
|
|
||||||
|
|
||||||
|
virtscr[0].xstart = 0;
|
||||||
|
|
||||||
|
vm.vars[9] = 11;
|
||||||
|
|
||||||
|
_lightsValueA = _lightsValueB = 7;
|
||||||
|
|
||||||
|
vm.vars[59] = 3;
|
||||||
|
|
||||||
|
mouse.x = 104;
|
||||||
|
mouse.y = 56;
|
||||||
|
|
||||||
|
_ENCD_offs = 0;
|
||||||
|
_EXCD_offs = 0;
|
||||||
|
|
||||||
|
_unkTabIndex = 0xFF;
|
||||||
|
_currentScript = 0xFF;
|
||||||
|
|
||||||
|
_currentRoom = 0;
|
||||||
|
_numObjectsInRoom = 0;
|
||||||
|
_actorToPrintStrFor = 0;
|
||||||
|
|
||||||
|
charset._bufPos = 0;
|
||||||
|
_haveMsg = 0;
|
||||||
|
|
||||||
|
_screenStartStrip = 0;
|
||||||
|
|
||||||
|
vm.vars[25] = 0;
|
||||||
|
|
||||||
|
_talkDelay = 0;
|
||||||
|
_keepText = false;
|
||||||
|
|
||||||
|
_cursorState = 0;
|
||||||
|
_userPut = 0;
|
||||||
|
|
||||||
|
_newEffect = 129;
|
||||||
|
_fullRedraw = 1;
|
||||||
|
|
||||||
|
clearDrawObjectQueue();
|
||||||
|
|
||||||
|
for (i=0; i<6; i++) {
|
||||||
|
textslot.x[i] = 2;
|
||||||
|
textslot.y[i] = 5;
|
||||||
|
textslot.right[i] = 319;
|
||||||
|
textslot.color[i] = 0xF;
|
||||||
|
textslot.center[i] = 0;
|
||||||
|
textslot.charset[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_numInMsgStack = 0;
|
||||||
|
|
||||||
|
createResource(0xC, 6, 500);
|
||||||
|
|
||||||
|
initScummVars();
|
||||||
|
|
||||||
|
vm.vars[54] = -0x50;
|
||||||
|
|
||||||
|
getGraphicsPerformance();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scumm::initScummVars() {
|
||||||
|
vm.vars[VAR_CURRENTDRIVE] = _currentDrive;
|
||||||
|
vm.vars[VAR_FIXEDDISK] = checkFixedDisk();
|
||||||
|
vm.vars[VAR_SOUNDCARD] = _soundCardType;
|
||||||
|
vm.vars[VAR_VIDEOMODE] = _videoMode;
|
||||||
|
vm.vars[VAR_HEAPSPACE] = _heapSpace;
|
||||||
|
vm.vars[VAR_MOUSEPRESENT] = _mousePresent;
|
||||||
|
vm.vars[VAR_SOUNDPARAM] = _soundParam;
|
||||||
|
vm.vars[VAR_SOUNDPARAM2] = _soundParam2;
|
||||||
|
vm.vars[VAR_SOUNDPARAM3] = _soundParam3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::checkRange(int max, int min, int no, const char *str) {
|
||||||
|
if (no < min || no > max) {
|
||||||
|
error("Value %d is out of bounds (%d,%d) msg %s", no, min,max, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::scummMain() {
|
||||||
|
int tmr, i;
|
||||||
|
Actor *a;
|
||||||
|
|
||||||
|
charset._vm = this;
|
||||||
|
cost._vm = this;
|
||||||
|
|
||||||
|
_exe_name = "monkey2";
|
||||||
|
|
||||||
|
_fileHandle = NULL;
|
||||||
|
|
||||||
|
_bootParam = 0;
|
||||||
|
_debugMode = 1;
|
||||||
|
|
||||||
|
initThings();
|
||||||
|
scummInit();
|
||||||
|
|
||||||
|
vm.vars[VAR_VERSION] = 21;
|
||||||
|
vm.vars[VAR_DEBUGMODE] = _debugMode;
|
||||||
|
|
||||||
|
runScript(1,0,0,&_bootParam);
|
||||||
|
_scummTimer = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (_playBackFile) {
|
||||||
|
while ((_scummTimer>>2) < vm.vars[VAR_PLAYBACKTIMER]) {}
|
||||||
|
_scummTimer = vm.vars[VAR_PLAYBACKTIMER] << 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateScreen(this);
|
||||||
|
|
||||||
|
vm.vars[VAR_TIMER] = _scummTimer >> 2;
|
||||||
|
do {
|
||||||
|
waitForTimer(this);
|
||||||
|
tmr = _scummTimer >> 2;
|
||||||
|
if (_fastMode)
|
||||||
|
tmr += 15;
|
||||||
|
} while (tmr < vm.vars[VAR_TIMER_NEXT]);
|
||||||
|
_scummTimer = 0;
|
||||||
|
|
||||||
|
vm.vars[VAR_TMR_1] += tmr;
|
||||||
|
vm.vars[VAR_TMR_2] += tmr;
|
||||||
|
vm.vars[VAR_TMR_3] += tmr;
|
||||||
|
vm.vars[VAR_TMR_4] += tmr;
|
||||||
|
|
||||||
|
if (tmr > 15)
|
||||||
|
tmr = 15;
|
||||||
|
|
||||||
|
decreaseScriptDelay(tmr);
|
||||||
|
|
||||||
|
_talkDelay -= tmr;
|
||||||
|
if (_talkDelay<0) _talkDelay=0;
|
||||||
|
|
||||||
|
processKbd();
|
||||||
|
|
||||||
|
/* XXX: memory low check skipped */
|
||||||
|
vm.vars[VAR_CAMERA_CUR_POS] = camera._curPos;
|
||||||
|
vm.vars[VAR_HAVE_MSG] = _haveMsg;
|
||||||
|
vm.vars[VAR_VIRT_MOUSE_X] = _virtual_mouse_x;
|
||||||
|
vm.vars[VAR_VIRT_MOUSE_Y] = _virtual_mouse_y;
|
||||||
|
vm.vars[VAR_MOUSE_X] = mouse.x;
|
||||||
|
vm.vars[VAR_MOUSE_Y] = mouse.y;
|
||||||
|
vm.vars[VAR_DEBUGMODE] = _debugMode;
|
||||||
|
|
||||||
|
if (_saveLoadFlag) {
|
||||||
|
error("Loading/saving not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_completeScreenRedraw) {
|
||||||
|
_completeScreenRedraw = 0;
|
||||||
|
clearUpperMask();
|
||||||
|
charset._hasMask = false;
|
||||||
|
redrawVerbs();
|
||||||
|
_fullRedraw = 1;
|
||||||
|
for (i=0,a=getFirstActor(); i<13; i++,a++)
|
||||||
|
a->needRedraw = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
runAllScripts();
|
||||||
|
checkExecVerbs();
|
||||||
|
checkAndRunVar33();
|
||||||
|
|
||||||
|
if (_currentRoom==0) {
|
||||||
|
gdi.unk4 = 0;
|
||||||
|
CHARSET_1();
|
||||||
|
unkVirtScreen2();
|
||||||
|
unkSoundProc22();
|
||||||
|
camera._lastPos = camera._curPos;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
walkActors();
|
||||||
|
moveCamera();
|
||||||
|
fixObjectFlags();
|
||||||
|
CHARSET_1();
|
||||||
|
if (camera._curPos != camera._lastPos || _BgNeedsRedraw || _fullRedraw) {
|
||||||
|
redrawBGAreas();
|
||||||
|
}
|
||||||
|
processDrawQue();
|
||||||
|
setActorRedrawFlags();
|
||||||
|
resetActorBgs();
|
||||||
|
|
||||||
|
if (!(vm.vars[VAR_DRAWFLAGS]&2) && vm.vars[VAR_DRAWFLAGS]&4) {
|
||||||
|
error("Flashlight not implemented in this version");
|
||||||
|
}
|
||||||
|
|
||||||
|
processActors(); /* process actors makes the heap invalid */
|
||||||
|
clear_fullRedraw();
|
||||||
|
cyclePalette();
|
||||||
|
palManipulate();
|
||||||
|
|
||||||
|
if (dseg_4F8A) {
|
||||||
|
screenEffect(_newEffect);
|
||||||
|
dseg_4F8A = 0;
|
||||||
|
clearClickedStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cursorState > 0) {
|
||||||
|
verbMouseOver(checkMouseOver(mouse.x, mouse.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
gdi.unk4 = _cursorState > 0;
|
||||||
|
|
||||||
|
unkVirtScreen2();
|
||||||
|
|
||||||
|
playActorSounds();
|
||||||
|
unkSoundProc22();
|
||||||
|
camera._lastPos = camera._curPos;
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::startScene(int room, Actor *a, int objectNr) {
|
||||||
|
int i;
|
||||||
|
Actor *at;
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
|
||||||
|
removeMouseCursor();
|
||||||
|
clearMsgQueue();
|
||||||
|
|
||||||
|
unkVirtScreen4(_switchRoomEffect2);
|
||||||
|
_newEffect = _switchRoomEffect;
|
||||||
|
|
||||||
|
if (_currentScript!=0xFF) {
|
||||||
|
if (vm.slot[_currentScript].type==1 || vm.slot[_currentScript].type==4) {
|
||||||
|
if(vm.slot[_currentScript].cutsceneOverride!=0)
|
||||||
|
error("Object %d stopped with active cutscene/override in exit", vm.slot[_currentScript].number);
|
||||||
|
_currentScript = 0xFF;
|
||||||
|
} else if (vm.slot[_currentScript].type==3) {
|
||||||
|
if (vm.slot[_currentScript].cutsceneOverride!=0)
|
||||||
|
error("Script %d stopped with active cutscene/override in exit", vm.slot[_currentScript].number);
|
||||||
|
_currentScript = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.vars[VAR_NEW_ROOM] = room;
|
||||||
|
runExitScript();
|
||||||
|
killScriptsAndResources();
|
||||||
|
stopCycle(0);
|
||||||
|
|
||||||
|
for(i=1,at=getFirstActor(); ++at,i<13; i++) {
|
||||||
|
if (at->visible)
|
||||||
|
hideActor(at);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<0x100; i++)
|
||||||
|
cost._transEffect[i] = i;
|
||||||
|
|
||||||
|
clearDrawObjectQueue();
|
||||||
|
|
||||||
|
vm.vars[VAR_ROOM] = room;
|
||||||
|
_fullRedraw = 1;
|
||||||
|
|
||||||
|
_roomResource = _currentRoom = 0xFF;
|
||||||
|
|
||||||
|
unkResourceProc();
|
||||||
|
|
||||||
|
_currentRoom = room;
|
||||||
|
vm.vars[VAR_ROOM] = room;
|
||||||
|
|
||||||
|
if (room >= 0x80)
|
||||||
|
_roomResource = _resourceMapper[room&0x7F];
|
||||||
|
else
|
||||||
|
_roomResource = room;
|
||||||
|
|
||||||
|
vm.vars[VAR_ROOM_RESOURCE] = _roomResource;
|
||||||
|
|
||||||
|
if (room!=0)
|
||||||
|
ensureResourceLoaded(1, room);
|
||||||
|
|
||||||
|
if (_currentRoom == 0) {
|
||||||
|
_ENCD_offs = _EXCD_offs = 0;
|
||||||
|
_numObjectsInRoom = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
initRoomSubBlocks();
|
||||||
|
|
||||||
|
loadRoomObjects();
|
||||||
|
|
||||||
|
camera._mode = 1;
|
||||||
|
camera._curPos = camera._destPos = 160;
|
||||||
|
|
||||||
|
if (_roomResource == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vm.vars[VAR_CAMERA_MAX] = (_scrWidthIn8Unit<<3) - 160;
|
||||||
|
vm.vars[VAR_CAMERA_MIN] = 160;
|
||||||
|
|
||||||
|
memset(actorDrawBits, 0, sizeof(actorDrawBits));
|
||||||
|
|
||||||
|
if (a) {
|
||||||
|
if (whereIsObject(objectNr)!=1 &&
|
||||||
|
whereIsObject(objectNr)!=4)
|
||||||
|
error("startScene: Object %d is not in room %d", objectNr, _currentRoom);
|
||||||
|
getObjectXYPos(objectNr);
|
||||||
|
putActor(a, _xPos, _yPos, _currentRoom);
|
||||||
|
startAnimActor(a, 0x3E, _dir^1);
|
||||||
|
a->moving = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
showActors();
|
||||||
|
dseg_3A76 = 0;
|
||||||
|
runEntryScript();
|
||||||
|
|
||||||
|
|
||||||
|
if (a && dseg_3A76==0) {
|
||||||
|
getObjectXYPos(objectNr);
|
||||||
|
putActor(a, _xPos, _yPos, _currentRoom);
|
||||||
|
a->moving = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dseg_4F8A = 1;
|
||||||
|
|
||||||
|
checkHeap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::initRoomSubBlocks() {
|
||||||
|
int i,offs;
|
||||||
|
byte *ptr;
|
||||||
|
byte *roomptr;
|
||||||
|
|
||||||
|
_ENCD_offs = 0;
|
||||||
|
_EXCD_offs = 0;
|
||||||
|
|
||||||
|
nukeResource(0xE, 1);
|
||||||
|
nukeResource(0xE, 2);
|
||||||
|
|
||||||
|
for (i=1; i<_maxScaleTable; i++)
|
||||||
|
nukeResource(0xB, i);
|
||||||
|
|
||||||
|
roomptr = getResourceAddress(1, _roomResource);
|
||||||
|
|
||||||
|
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)) -
|
||||||
|
roomptr;
|
||||||
|
|
||||||
|
ptr = findResource(MKID('EXCD'), roomptr);
|
||||||
|
if (ptr) {
|
||||||
|
_EXCD_offs = ptr - roomptr;
|
||||||
|
#ifdef DUMP_SCRIPTS
|
||||||
|
dumpResource("exit-", _roomResource, ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = findResource(MKID('ENCD'), roomptr);
|
||||||
|
if (ptr) {
|
||||||
|
_ENCD_offs = ptr - roomptr;
|
||||||
|
#ifdef DUMP_SCRIPTS
|
||||||
|
dumpResource("entry-", _roomResource, ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = findResource(MKID('BOXD'), roomptr);
|
||||||
|
if (ptr) {
|
||||||
|
int size = READ_BE_UINT32_UNALIGNED(ptr+4);
|
||||||
|
createResource(0xE, 2, size);
|
||||||
|
roomptr = getResourceAddress(1, _roomResource);
|
||||||
|
ptr = findResource(MKID('BOXD'), roomptr);
|
||||||
|
memcpy(getResourceAddress(0xE, 2), ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = findResource(MKID('BOXM'), roomptr);
|
||||||
|
if (ptr) {
|
||||||
|
int size = READ_BE_UINT32_UNALIGNED(ptr+4);
|
||||||
|
createResource(0xE, 1, size);
|
||||||
|
roomptr = getResourceAddress(1, _roomResource);
|
||||||
|
ptr = findResource(MKID('BOXM'), roomptr);
|
||||||
|
memcpy(getResourceAddress(0xE, 1), ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = findResource(MKID('SCAL'), roomptr);
|
||||||
|
if (ptr) {
|
||||||
|
offs = ptr - roomptr;
|
||||||
|
for (i=1; i<_maxScaleTable; i++, offs+=8) {
|
||||||
|
int a = READ_LE_UINT16(roomptr + offs + 8);
|
||||||
|
int b = READ_LE_UINT16(roomptr + offs + 10);
|
||||||
|
int c = READ_LE_UINT16(roomptr + offs + 12);
|
||||||
|
int d = READ_LE_UINT16(roomptr + offs + 14);
|
||||||
|
if (a || b || c || d) {
|
||||||
|
setScaleItem(i, b, a, d, c);
|
||||||
|
roomptr = getResourceAddress(1, _roomResource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(_localScriptList, 0, (0x100 - _numGlobalScriptsUsed) * 4);
|
||||||
|
|
||||||
|
roomptr = getResourceAddress(1, _roomResource);
|
||||||
|
ptr = findResource(MKID('LSCR'), roomptr);
|
||||||
|
while (ptr) {
|
||||||
|
_localScriptList[ptr[8] - _numGlobalScriptsUsed] = ptr - roomptr;
|
||||||
|
|
||||||
|
#ifdef DUMP_SCRIPTS
|
||||||
|
do {
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf,"room-%d-",_roomResource);
|
||||||
|
dumpResource(buf, ptr[8], ptr);
|
||||||
|
} while (0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ptr = findResource(MKID('LSCR'), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
_CLUT_offs = findResource(MKID('CLUT'), roomptr) - roomptr;
|
||||||
|
ptr = findResource(MKID('EPAL'), roomptr);
|
||||||
|
if (ptr)
|
||||||
|
_EPAL_offs = ptr - roomptr;
|
||||||
|
|
||||||
|
setPaletteFromRes();
|
||||||
|
initCycl(findResource(MKID('CYCL'), roomptr) + 8);
|
||||||
|
|
||||||
|
ptr = findResource(MKID('TRNS'), roomptr);
|
||||||
|
if (ptr)
|
||||||
|
gdi.transparency = ptr[8];
|
||||||
|
else
|
||||||
|
gdi.transparency = 255;
|
||||||
|
|
||||||
|
initBGBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::setScaleItem(int slot, int a, int b, int c, int d) {
|
||||||
|
byte *ptr;
|
||||||
|
int cur,amounttoadd,i,tmp;
|
||||||
|
|
||||||
|
ptr = createResource(0xB, slot, 200);
|
||||||
|
|
||||||
|
if (a==c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cur = (b-d)*a;
|
||||||
|
amounttoadd = d - b;
|
||||||
|
|
||||||
|
for (i=200; i>0; i--) {
|
||||||
|
tmp = cur / (c - a) + b;
|
||||||
|
if (tmp<1) tmp=1;
|
||||||
|
if (tmp>255) tmp=255;
|
||||||
|
*ptr++ = tmp;
|
||||||
|
cur += amounttoadd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::dumpResource(char *tag, int index, byte *ptr) {
|
||||||
|
char buf[256];
|
||||||
|
FILE *out;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32 size = READ_BE_UINT32_UNALIGNED(ptr+4);
|
||||||
|
|
||||||
|
sprintf(buf, "d:\\monkey2\\dumps\\%s%d.dmp", tag,index);
|
||||||
|
|
||||||
|
out = fopen(buf,"rb");
|
||||||
|
if (!out) {
|
||||||
|
out = fopen(buf, "wb");
|
||||||
|
if (!out)
|
||||||
|
return;
|
||||||
|
fwrite(ptr, size, 1, out);
|
||||||
|
}
|
||||||
|
fclose(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scumm::clear_fullRedraw() {
|
||||||
|
_fullRedraw = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::clearClickedStatus() {
|
||||||
|
checkKeyHit();
|
||||||
|
_mouseButStat = 0;
|
||||||
|
_leftBtnPressed = 0;
|
||||||
|
_rightBtnPressed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::checkKeyHit() {
|
||||||
|
int a = _keyPressed;
|
||||||
|
_keyPressed = 0;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkRoomFunc3(int a, int b, int c, int d, int e) {
|
||||||
|
warning("stub unkRoomFunc3(%d,%d,%d,%d,%d)",a,b,c,d,e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkRoomFunc2(int a, int b, int c, int d, int e) {
|
||||||
|
byte *cptr, *cur;
|
||||||
|
int num;
|
||||||
|
byte color;
|
||||||
|
|
||||||
|
if (_videoMode==0xE) {
|
||||||
|
warning("stub unkRoomFunc2(%d,%d,%d,%d,%d)",a,b,c,d,e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_videoMode==0x13) {
|
||||||
|
cptr = getResourceAddress(1, _roomResource) + _CLUT_offs + 8 + a*3;
|
||||||
|
cur = _currentPalette + a*3;
|
||||||
|
if (a <= b) {
|
||||||
|
num = b - a + 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (c != 0xFF) {
|
||||||
|
color = *cptr++ * (c>>2) / 0xFF;
|
||||||
|
} else {
|
||||||
|
color = *cptr++ >> 2;
|
||||||
|
}
|
||||||
|
if(color>63) color = 63;
|
||||||
|
*cur++=color;
|
||||||
|
|
||||||
|
if (d != 0xFF) {
|
||||||
|
color = *cptr++ * (d>>2) / 0xFF;
|
||||||
|
} else {
|
||||||
|
color = *cptr++ >> 2;
|
||||||
|
}
|
||||||
|
if(color>63) color = 63;
|
||||||
|
*cur++=color;
|
||||||
|
|
||||||
|
if (e != 0xFF) {
|
||||||
|
color = *cptr++ * (e>>2) / 0xFF;
|
||||||
|
} else {
|
||||||
|
color = *cptr++ >> 2;
|
||||||
|
}
|
||||||
|
if(color>63) color = 63;
|
||||||
|
*cur++=color;
|
||||||
|
} while (--num);
|
||||||
|
}
|
||||||
|
setDirtyColors(a,b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scumm::unkRoomFunc4(int a, int b, int c, int d, int e) {
|
||||||
|
/* TODO: implement this */
|
||||||
|
warning("unkRoomFunc4: not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scumm::pauseGame(int i) {
|
||||||
|
/* TODO: implement this */
|
||||||
|
warning("pauseGame: not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::shutDown(int i) {
|
||||||
|
/* TODO: implement this */
|
||||||
|
warning("shutDown: not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::processKbd() {
|
||||||
|
getKeyInput(0);
|
||||||
|
|
||||||
|
_virtual_mouse_x = mouse.x + virtscr[0].xstart;
|
||||||
|
_virtual_mouse_y = mouse.y + virtscr[0].topline;
|
||||||
|
if (_virtual_mouse_y < 0)
|
||||||
|
_virtual_mouse_y = -1;
|
||||||
|
if (_virtual_mouse_y >= virtscr[0].height)
|
||||||
|
_virtual_mouse_y = -1;
|
||||||
|
|
||||||
|
if (!_lastKeyHit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_lastKeyHit==vm.vars[VAR_RESTART_KEY]) {
|
||||||
|
warning("Restart not implemented");
|
||||||
|
pauseGame(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastKeyHit==vm.vars[VAR_PAUSE_KEY]) {
|
||||||
|
warning("Pause not implemented");
|
||||||
|
/* pause */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastKeyHit==vm.vars[VAR_CUTSCENEEXIT_KEY]) {
|
||||||
|
uint32 offs = vm.cutScenePtr[vm.cutSceneStackPointer];
|
||||||
|
if (offs) {
|
||||||
|
ScriptSlot *ss = &vm.slot[vm.cutSceneScript[vm.cutSceneStackPointer]];
|
||||||
|
ss->offs = offs;
|
||||||
|
ss->status = 2;
|
||||||
|
ss->freezeCount = 0;
|
||||||
|
ss->cutsceneOverride--;
|
||||||
|
vm.vars[VAR_OVERRIDE] = 1;
|
||||||
|
vm.cutScenePtr[vm.cutSceneStackPointer] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastKeyHit==vm.vars[VAR_TALKSTOP_KEY]) {
|
||||||
|
_talkDelay = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_mouseButStat = _lastKeyHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getKeyInput(int a) {
|
||||||
|
_mouseButStat = 0;
|
||||||
|
|
||||||
|
_lastKeyHit = checkKeyHit();
|
||||||
|
if (a==0)
|
||||||
|
convertKeysToClicks();
|
||||||
|
|
||||||
|
if (mouse.x<0) mouse.x=0;
|
||||||
|
if (mouse.x>319) mouse.x=319;
|
||||||
|
if (mouse.y<0) mouse.y=0;
|
||||||
|
if (mouse.y>199) mouse.y=199;
|
||||||
|
|
||||||
|
if (_leftBtnPressed&1 && _rightBtnPressed&1) {
|
||||||
|
_mouseButStat = 0;
|
||||||
|
_lastKeyHit = vm.vars[VAR_CUTSCENEEXIT_KEY];
|
||||||
|
} else if (_leftBtnPressed&1) {
|
||||||
|
_mouseButStat = 0x8000;
|
||||||
|
} else if (_rightBtnPressed&1) {
|
||||||
|
_mouseButStat = 0x4000;
|
||||||
|
}
|
||||||
|
|
||||||
|
_leftBtnPressed &= ~1;
|
||||||
|
_rightBtnPressed &= ~1;
|
||||||
|
|
||||||
|
return _lastKeyHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::convertKeysToClicks() {
|
||||||
|
if (_lastKeyHit && _cursorState>0) {
|
||||||
|
if (_lastKeyHit==9) {
|
||||||
|
_mouseButStat = 0x4000;
|
||||||
|
} else if (_lastKeyHit==13) {
|
||||||
|
_mouseButStat = 0x8000;
|
||||||
|
} else
|
||||||
|
return;
|
||||||
|
_lastKeyHit = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Actor *Scumm::derefActorSafe(int id, const char *errmsg) {
|
||||||
|
if (id<1 || id>=13)
|
||||||
|
error("Invalid actor %d in %s", id, errmsg);
|
||||||
|
return derefActor(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern Scumm scumm;
|
||||||
|
|
||||||
|
void NORETURN CDECL error(const char *s, ...) {
|
||||||
|
char buf[1024];
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, s);
|
||||||
|
vsprintf(buf, s, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
if (scumm._currentScript != 0xFF) {
|
||||||
|
fprintf(stderr, "Error(%d): %s!\nPress a key to quit.\n", scumm.vm.slot[scumm._currentScript].number, buf);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Error: %s!\nPress a key to quit.\n", buf);
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDECL warning(const char *s, ...) {
|
||||||
|
char buf[1024];
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va,s);
|
||||||
|
vsprintf(buf, s, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
fprintf(stderr, "WARNING: %s!\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDECL debug(int level, const char *s, ...) {
|
||||||
|
char buf[1024];
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
if (level>5)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(va,s);
|
||||||
|
vsprintf(buf, s, va);
|
||||||
|
va_end(va);
|
||||||
|
printf("%s\n", buf);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkHeap() {
|
||||||
|
#if 0
|
||||||
|
if (_heapchk() != _HEAPOK) {
|
||||||
|
error("Heap is invalid!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
175
scummvm.dsp
Normal file
175
scummvm.dsp
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="scummvm" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=scummvm - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "scummvm.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "scummvm.mak" CFG="scummvm - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "scummvm - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "scummvm - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "scummvm - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD CPP /nologo /Zp4 /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD BASE RSC /l 0x41d /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x41d /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sdl.lib /nologo /subsystem:console /machine:I386
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "scummvm - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# 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 BASE RSC /l 0x41d /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x41d /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sdl.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "scummvm - Win32 Release"
|
||||||
|
# Name "scummvm - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\actor.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\boxes.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\costume.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\gfx.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\object.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\resource.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\saveload.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\script.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\scummvm.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\sdl.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\sound.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\StdAfx.cpp
|
||||||
|
# ADD CPP /Yc"stdafx.h"
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\string.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\sys.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\verbs.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\scumm.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\scummsys.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\StdAfx.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\ReadMe.txt
|
||||||
|
# End Source File
|
||||||
|
# End Target
|
||||||
|
# End Project
|
29
scummvm.dsw
Normal file
29
scummvm.dsw
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "scummvm"=.\scummvm.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
213
sdl.cpp
Normal file
213
sdl.cpp
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:13 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
#define SCALEUP_2x2
|
||||||
|
|
||||||
|
Scumm scumm;
|
||||||
|
|
||||||
|
static SDL_Surface *screen;
|
||||||
|
|
||||||
|
void updatePalette(Scumm *s) {
|
||||||
|
SDL_Color colors[256];
|
||||||
|
int first = s->_palDirtyMin;
|
||||||
|
int num = s->_palDirtyMax - first + 1;
|
||||||
|
int i;
|
||||||
|
byte *data = s->_currentPalette;
|
||||||
|
|
||||||
|
data += first*3;
|
||||||
|
for (i=0; i<num; i++,data+=3) {
|
||||||
|
colors[i].r = data[0]<<2;
|
||||||
|
colors[i].g = data[1]<<2;
|
||||||
|
colors[i].b = data[2]<<2;
|
||||||
|
colors[i].unused = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetColors(screen, colors, first, num);
|
||||||
|
|
||||||
|
s->_palDirtyMax = -1;
|
||||||
|
s->_palDirtyMin = 0x3E8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void waitForTimer(Scumm *s) {
|
||||||
|
SDL_Event event;
|
||||||
|
byte dontPause = true;
|
||||||
|
|
||||||
|
do {
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
switch(event.type) {
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
s->_keyPressed = event.key.keysym.sym;
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEMOTION:
|
||||||
|
#if !defined(SCALEUP_2x2)
|
||||||
|
s->mouse.x = event.motion.x;
|
||||||
|
s->mouse.y = event.motion.y;
|
||||||
|
#else
|
||||||
|
s->mouse.x = event.motion.x>>1;
|
||||||
|
s->mouse.y = event.motion.y>>1;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
if (event.button.button==SDL_BUTTON_LEFT)
|
||||||
|
s->_leftBtnPressed |= 1;
|
||||||
|
else if (event.button.button==SDL_BUTTON_RIGHT)
|
||||||
|
s->_rightBtnPressed |= 1;
|
||||||
|
break;
|
||||||
|
#if 0
|
||||||
|
case SDL_ACTIVEEVENT:
|
||||||
|
if (event.active.state & SDL_APPINPUTFOCUS) {
|
||||||
|
dontPause = event.active.gain;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case SDL_QUIT:
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_Delay(dontPause ? 10 : 100);
|
||||||
|
} while (!dontPause);
|
||||||
|
|
||||||
|
s->_scummTimer+=3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_DIRTY_RECTS 40
|
||||||
|
SDL_Rect dirtyRects[MAX_DIRTY_RECTS];
|
||||||
|
int numDirtyRects;
|
||||||
|
bool fullRedraw;
|
||||||
|
|
||||||
|
/* Copy part of bitmap */
|
||||||
|
void blitToScreen(Scumm *s, byte *src,int x, int y, int w, int h) {
|
||||||
|
byte *dst;
|
||||||
|
SDL_Rect *r;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (SDL_LockSurface(screen)==-1)
|
||||||
|
error("SDL_LockSurface failed: %s.\n", SDL_GetError());
|
||||||
|
|
||||||
|
#if !defined(SCALEUP_2x2)
|
||||||
|
dst = (byte*)screen->pixels + y*320 + x;
|
||||||
|
|
||||||
|
if (numDirtyRects==MAX_DIRTY_RECTS)
|
||||||
|
fullRedraw = true;
|
||||||
|
else if (!fullRedraw) {
|
||||||
|
r = &dirtyRects[numDirtyRects++];
|
||||||
|
r->x = x;
|
||||||
|
r->y = y;
|
||||||
|
r->w = w;
|
||||||
|
r->h = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
memcpy(dst, src, w);
|
||||||
|
dst += 640;
|
||||||
|
src += 320;
|
||||||
|
} while (--h);
|
||||||
|
#else
|
||||||
|
dst = (byte*)screen->pixels + y*640*2 + x*2;
|
||||||
|
|
||||||
|
if (numDirtyRects==MAX_DIRTY_RECTS)
|
||||||
|
fullRedraw = true;
|
||||||
|
else if (!fullRedraw) {
|
||||||
|
r = &dirtyRects[numDirtyRects++];
|
||||||
|
r->x = x*2;
|
||||||
|
r->y = y*2;
|
||||||
|
r->w = w*2;
|
||||||
|
r->h = h*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
i=0;
|
||||||
|
do {
|
||||||
|
dst[i*2] = dst[i*2+1] = src[i];
|
||||||
|
} while (++i!=w);
|
||||||
|
memcpy(dst+640, dst, w*2);
|
||||||
|
dst += 640*2;
|
||||||
|
src += 320;
|
||||||
|
} while (--h);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_UnlockSurface(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateScreen(Scumm *s) {
|
||||||
|
|
||||||
|
if(s->_palDirtyMax != -1) {
|
||||||
|
updatePalette(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fullRedraw) {
|
||||||
|
SDL_UpdateRect(screen, 0,0,0,0);
|
||||||
|
#if defined(SHOW_AREA)
|
||||||
|
debug(2,"update area 100 %%");
|
||||||
|
#endif
|
||||||
|
} else if (numDirtyRects) {
|
||||||
|
#if defined(SHOW_AREA)
|
||||||
|
int area = 0,i;
|
||||||
|
for (i=0; i<numDirtyRects; i++)
|
||||||
|
area += (dirtyRects[i].w * dirtyRects[i].h);
|
||||||
|
debug(2,"update area %f %%", (float)area/640);
|
||||||
|
#endif
|
||||||
|
SDL_UpdateRects(screen, numDirtyRects, dirtyRects);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
numDirtyRects = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef main
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO)==-1) {
|
||||||
|
printf("Could not initialize SDL: %s.\n", SDL_GetError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%d %d, %d %d, %d %d %d, %d %d %d %d %d\n",
|
||||||
|
sizeof(int8), sizeof(uint8),
|
||||||
|
sizeof(int16), sizeof(uint16),
|
||||||
|
sizeof(int32), sizeof(uint32),
|
||||||
|
sizeof(void*),
|
||||||
|
sizeof(Box), sizeof(MouseCursor),sizeof(CodeHeader),
|
||||||
|
sizeof(ImageHeader),
|
||||||
|
&((CodeHeader*)0)->unk4
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Clean up on exit */
|
||||||
|
atexit(SDL_Quit);
|
||||||
|
|
||||||
|
#if !defined(SCALEUP_2x2)
|
||||||
|
screen = SDL_SetVideoMode(320, 200, 8, SDL_SWSURFACE);
|
||||||
|
#else
|
||||||
|
screen = SDL_SetVideoMode(640, 400, 8, SDL_SWSURFACE);
|
||||||
|
#endif
|
||||||
|
scumm._videoMode = 0x13;
|
||||||
|
scumm.scummMain();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
86
sound.cpp
Normal file
86
sound.cpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:13 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
void Scumm::addSoundToQueue(int sound) {
|
||||||
|
vm.vars[VAR_LAST_SOUND] = sound;
|
||||||
|
ensureResourceLoaded(4, sound);
|
||||||
|
addSoundToQueue2(sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::addSoundToQueue2(int sound) {
|
||||||
|
if (_soundQue2Pos < 10) {
|
||||||
|
_soundQue2[_soundQue2Pos++] = sound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkSoundProc22() {
|
||||||
|
byte d;
|
||||||
|
int i,j;
|
||||||
|
int num;
|
||||||
|
int16 data[16];
|
||||||
|
|
||||||
|
while (_soundQue2Pos){
|
||||||
|
d=_soundQue2[--_soundQue2Pos];
|
||||||
|
if (d)
|
||||||
|
playSound(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for (i=0; i<_soundQuePos; ) {
|
||||||
|
num = _soundQue[i++];
|
||||||
|
for (j=0; j<16; j++)
|
||||||
|
data[j] = 0;
|
||||||
|
if (num>0) {
|
||||||
|
for (j=0; j<num; j++)
|
||||||
|
_soundQue[i+j] = data[j];
|
||||||
|
i += num;
|
||||||
|
/* XXX: not implemented */
|
||||||
|
warning("unkSoundProc22: not implemented");
|
||||||
|
// vm.vars[VAR_SOUNDRESULT] = soundProcPtr1(...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
_soundQuePos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::playSound(int sound) {
|
||||||
|
getResourceAddress(4, sound);
|
||||||
|
/* XXX: not implemented */
|
||||||
|
warning("stub playSound(%d)", sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::unkSoundProc23(int a) {
|
||||||
|
/* TODO: implement this */
|
||||||
|
warning("unkSoundProc23: not implemented");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkSoundProc1(int a) {
|
||||||
|
/* TODO: implement this */
|
||||||
|
warning("unkSoundProc: not implemented");
|
||||||
|
}
|
8
stdafx.cpp
Normal file
8
stdafx.cpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// stdafx.cpp : source file that includes just the standard includes
|
||||||
|
// scummvm.pch will be the pre-compiled header
|
||||||
|
// stdafx.obj will contain the pre-compiled type information
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
// TODO: reference any additional headers you need in STDAFX.H
|
||||||
|
// and not in this file
|
58
stdafx.h
Normal file
58
stdafx.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#if defined(WIN32)
|
||||||
|
|
||||||
|
#if _MSC_VER > 1000
|
||||||
|
#pragma once
|
||||||
|
#endif // _MSC_VER > 1000
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||||
|
#define NOGDICAPMASKS
|
||||||
|
#define OEMRESOURCE
|
||||||
|
#define NONLS
|
||||||
|
#define NOICONS
|
||||||
|
#define NOMCX
|
||||||
|
#define NOPROFILER
|
||||||
|
#define NOKANJI
|
||||||
|
#define NOSERVICE
|
||||||
|
#define NOMETAFILE
|
||||||
|
#define NOCOMM
|
||||||
|
#define NOCRYPT
|
||||||
|
#define NOIME
|
||||||
|
#define NOATOM
|
||||||
|
#define NOCTLMGR
|
||||||
|
#define NOCLIPBOARD
|
||||||
|
#define NOMEMMGR
|
||||||
|
#define NOSYSMETRICS
|
||||||
|
#define NOMENUS
|
||||||
|
#define NOOPENFILE
|
||||||
|
#define NOWH
|
||||||
|
#define NOSOUND
|
||||||
|
#define NODRAWTEXT
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <conio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
697
string.cpp
Normal file
697
string.cpp
Normal file
|
@ -0,0 +1,697 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:13 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
int CharsetRenderer::getStringWidth(int arg, byte *text, int pos) {
|
||||||
|
byte *ptr;
|
||||||
|
int width,offs,w;
|
||||||
|
byte chr;
|
||||||
|
|
||||||
|
width = 1;
|
||||||
|
ptr = _vm->getResourceAddress(6, _curId) + 29;
|
||||||
|
|
||||||
|
while ( (chr = text[pos++]) != 0) {
|
||||||
|
if (chr==0xD)
|
||||||
|
break;
|
||||||
|
if (chr=='@')
|
||||||
|
continue;
|
||||||
|
if (chr==254) chr=255;
|
||||||
|
if (chr==255) {
|
||||||
|
chr=text[pos++];
|
||||||
|
if (chr==3)
|
||||||
|
break;
|
||||||
|
if (chr==8) {
|
||||||
|
if (arg==1)
|
||||||
|
break;
|
||||||
|
while (text[pos]==' ')
|
||||||
|
text[pos++] = '@';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (chr==1 || chr==2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
offs = READ_LE_UINT32(ptr + chr*4 + 4);
|
||||||
|
if (offs) {
|
||||||
|
if (ptr[offs+2]>=0x80) {
|
||||||
|
w = ptr[offs+2] - 0x100;
|
||||||
|
} else {
|
||||||
|
w = ptr[offs+2];
|
||||||
|
}
|
||||||
|
width += ptr[offs] + w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) {
|
||||||
|
int lastspace = -1;
|
||||||
|
int curw = 1;
|
||||||
|
int offs,w;
|
||||||
|
byte *ptr;
|
||||||
|
byte chr;
|
||||||
|
|
||||||
|
ptr = _vm->getResourceAddress(6, _curId) + 29;
|
||||||
|
|
||||||
|
while ( (chr=str[pos++]) != 0) {
|
||||||
|
if (chr=='@')
|
||||||
|
continue;
|
||||||
|
if (chr==254) chr=255;
|
||||||
|
if (chr==255) {
|
||||||
|
chr = str[pos++];
|
||||||
|
if (chr==3)
|
||||||
|
break;
|
||||||
|
if (chr==8) {
|
||||||
|
if (a==1) {
|
||||||
|
curw = 1;
|
||||||
|
} else {
|
||||||
|
while (str[pos]==' ')
|
||||||
|
str[pos++] = '@';
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (chr==1) {
|
||||||
|
curw = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (chr==2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chr==' ')
|
||||||
|
lastspace = pos - 1;
|
||||||
|
|
||||||
|
offs = READ_LE_UINT32(ptr + chr*4 + 4);
|
||||||
|
if (offs) {
|
||||||
|
if (ptr[offs+2]>=0x80) {
|
||||||
|
w = ptr[offs+2] - 0x100;
|
||||||
|
} else {
|
||||||
|
w = ptr[offs+2];
|
||||||
|
}
|
||||||
|
curw += w + ptr[offs];
|
||||||
|
}
|
||||||
|
if (lastspace==-1)
|
||||||
|
continue;
|
||||||
|
if (curw > maxwidth) {
|
||||||
|
str[lastspace] = 0xD;
|
||||||
|
curw = 1;
|
||||||
|
pos = lastspace + 1;
|
||||||
|
lastspace = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkMessage1() {
|
||||||
|
byte buf[100];
|
||||||
|
_msgPtrToAdd = buf;
|
||||||
|
_messagePtr = addMessageToStack(_messagePtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkMessage2() {
|
||||||
|
byte buf[100], *tmp;
|
||||||
|
|
||||||
|
_msgPtrToAdd = buf;
|
||||||
|
tmp = _messagePtr = addMessageToStack(_messagePtr);
|
||||||
|
|
||||||
|
if (_stringColor[3]==0)
|
||||||
|
_stringColor[3] = 4;
|
||||||
|
|
||||||
|
error("unkMessage2: call to printScummMessage(%s)", buf);
|
||||||
|
vm.vars[0] = 0;
|
||||||
|
_messagePtr = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Scumm::CHARSET_1() {
|
||||||
|
int s, i, t, c;
|
||||||
|
int frme;
|
||||||
|
Actor *a;
|
||||||
|
|
||||||
|
if (!_haveMsg || (camera._destPos>>3) != (camera._curPos>>3) ||
|
||||||
|
camera._curPos != camera._lastPos
|
||||||
|
) return;
|
||||||
|
|
||||||
|
a = NULL;
|
||||||
|
if (vm.vars[VAR_TALK_ACTOR] != 0xFF)
|
||||||
|
a = derefActorSafe(vm.vars[VAR_TALK_ACTOR], "CHARSET_1");
|
||||||
|
|
||||||
|
if (a && _stringOverhead[0]!=0) {
|
||||||
|
_stringXpos[0] = a->x - camera._curPos + 160;
|
||||||
|
|
||||||
|
if (vm.vars[VAR_TALK_STRING_Y] < 0) {
|
||||||
|
s = (a->scaley * (int)vm.vars[VAR_TALK_STRING_Y]) / 0xFF;
|
||||||
|
_stringYpos[0] = ((vm.vars[VAR_TALK_STRING_Y]-s)>>1) + s - a->elevation + a->y;
|
||||||
|
} else {
|
||||||
|
_stringYpos[0] = vm.vars[VAR_TALK_STRING_Y];
|
||||||
|
}
|
||||||
|
if (_stringYpos[0] < 1)
|
||||||
|
_stringYpos[0] = 1;
|
||||||
|
|
||||||
|
if (_stringXpos[0] < 80)
|
||||||
|
_stringXpos[0] = 80;
|
||||||
|
if (_stringXpos[0] > 240)
|
||||||
|
_stringXpos[0] = 240;
|
||||||
|
}
|
||||||
|
|
||||||
|
charset._top = _stringYpos[0];
|
||||||
|
charset._left = _stringXpos[0];
|
||||||
|
charset._left2 = _stringXpos[0];
|
||||||
|
charset._curId = _stringCharset[0];
|
||||||
|
|
||||||
|
if (a && a->charset)
|
||||||
|
charset._curId = a->charset;
|
||||||
|
|
||||||
|
charset._center = _stringCenter[0];
|
||||||
|
charset._right = _stringRight[0];
|
||||||
|
charset._color = _charsetColor;
|
||||||
|
dseg_4E3C = 0;
|
||||||
|
|
||||||
|
for (i=0; i<4; i++)
|
||||||
|
charset._colorMap[i] = _charsetData[charset._curId][i];
|
||||||
|
|
||||||
|
if (_keepText) {
|
||||||
|
charset._strLeft = charset._mask_left;
|
||||||
|
charset._strRight = charset._mask_right;
|
||||||
|
charset._strTop = charset._mask_top;
|
||||||
|
charset._strBottom = charset._mask_bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_haveMsg || _talkDelay)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_haveMsg!=0xFF) {
|
||||||
|
stopTalk();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a) {
|
||||||
|
startAnimActor(a, a->talkFrame1, a->facing);
|
||||||
|
}
|
||||||
|
|
||||||
|
_talkDelay = _defaultTalkDelay;
|
||||||
|
|
||||||
|
if (!_keepText) {
|
||||||
|
restoreCharsetBg();
|
||||||
|
_stringXpos2[0] = _stringXpos[0];
|
||||||
|
_stringYpos2[0] = _stringYpos[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
t = charset._right - _stringXpos2[0] - 1;
|
||||||
|
if (charset._center) {
|
||||||
|
if (t > _stringXpos2[0])
|
||||||
|
t = _stringXpos2[0];
|
||||||
|
t <<= 1;
|
||||||
|
}
|
||||||
|
charset.addLinebreaks(0, charset._buffer, charset._bufPos, t);
|
||||||
|
|
||||||
|
_lastXstart = virtscr[0].xstart;
|
||||||
|
if (charset._center) {
|
||||||
|
_stringXpos2[0] -= charset.getStringWidth(0, charset._buffer, charset._bufPos) >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
charset._disableOffsX = charset._unk12 = !_keepText;
|
||||||
|
|
||||||
|
do {
|
||||||
|
c = charset._buffer[charset._bufPos++];
|
||||||
|
if (c==0) {
|
||||||
|
_haveMsg = 1;
|
||||||
|
_keepText = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c != 13) {
|
||||||
|
if (c==0xFE)
|
||||||
|
c=0xFF;
|
||||||
|
|
||||||
|
if (c!=0xFF) {
|
||||||
|
PrintChar:;
|
||||||
|
charset._left = _stringXpos2[0];
|
||||||
|
charset._top = _stringYpos2[0];
|
||||||
|
|
||||||
|
if (!vm.vars[VAR_CHARFLAG]) {
|
||||||
|
charset.printChar(c);
|
||||||
|
}
|
||||||
|
_stringXpos2[0] = charset._left;
|
||||||
|
_stringYpos2[0] = charset._top;
|
||||||
|
|
||||||
|
_talkDelay += vm.vars[VAR_CHARINC];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = charset._buffer[charset._bufPos++];
|
||||||
|
if (c==3) {
|
||||||
|
_haveMsg = 0xFF;
|
||||||
|
_keepText = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c!=1) {
|
||||||
|
if (c==2) {
|
||||||
|
_haveMsg = 0;
|
||||||
|
_keepText = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c==9) {
|
||||||
|
frme = charset._buffer[charset._bufPos++];
|
||||||
|
frme |= charset._buffer[charset._bufPos++]<<8;
|
||||||
|
if (a)
|
||||||
|
startAnimActor(a, frme, a->facing);
|
||||||
|
}
|
||||||
|
goto PrintChar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_stringXpos2[0] = _stringXpos[0];
|
||||||
|
if (charset._center) {
|
||||||
|
_stringXpos2[0] -= charset.getStringWidth(0, charset._buffer, charset._bufPos)>>1;
|
||||||
|
}
|
||||||
|
_stringYpos2[0] += getResourceAddress(6,charset._curId)[30];
|
||||||
|
charset._disableOffsX = 1;
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
charset._mask_left = charset._strLeft;
|
||||||
|
charset._mask_right = charset._strRight;
|
||||||
|
charset._mask_top = charset._strTop;
|
||||||
|
charset._mask_bottom = charset._strBottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::drawString(int a) {
|
||||||
|
byte buf[256];
|
||||||
|
byte *charsetptr,*space;
|
||||||
|
int i;
|
||||||
|
byte byte1, chr;
|
||||||
|
|
||||||
|
_msgPtrToAdd = buf;
|
||||||
|
_messagePtr = addMessageToStack(_messagePtr);
|
||||||
|
|
||||||
|
charset._left2 = charset._left = _stringXpos[a];
|
||||||
|
charset._top = _stringYpos[a];
|
||||||
|
charset._curId = _stringCharset[a];
|
||||||
|
charset._center = _stringCenter[a];
|
||||||
|
charset._right = _stringRight[a];
|
||||||
|
charset._color = _stringColor[a];
|
||||||
|
dseg_4E3C = 0;
|
||||||
|
charset._unk12 = 1;
|
||||||
|
charset._disableOffsX = 1;
|
||||||
|
|
||||||
|
charsetptr = getResourceAddress(6, charset._curId);
|
||||||
|
assert(charsetptr);
|
||||||
|
charsetptr += 29;
|
||||||
|
|
||||||
|
for(i=0; i<4; i++)
|
||||||
|
charset._colorMap[i] = _charsetData[charset._curId][i];
|
||||||
|
|
||||||
|
byte1 = charsetptr[1];
|
||||||
|
|
||||||
|
_msgPtrToAdd = buf;
|
||||||
|
|
||||||
|
/* trim from the right */
|
||||||
|
space = NULL;
|
||||||
|
while (*_msgPtrToAdd){
|
||||||
|
if (*_msgPtrToAdd==' ') {
|
||||||
|
if (!space) space = _msgPtrToAdd;
|
||||||
|
} else {
|
||||||
|
space = NULL;
|
||||||
|
}
|
||||||
|
_msgPtrToAdd++;
|
||||||
|
}
|
||||||
|
if(space) *space='\0';
|
||||||
|
|
||||||
|
if (charset._center) {
|
||||||
|
charset._left -= charset.getStringWidth(a, buf, 0) >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
charset._ignoreCharsetMask = 1;
|
||||||
|
|
||||||
|
if (!buf[0]) {
|
||||||
|
buf[0] = ' ';
|
||||||
|
buf[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; (chr=buf[i++]) != 0; ) {
|
||||||
|
if (chr==254) chr=255;
|
||||||
|
if (chr==255) {
|
||||||
|
chr = buf[i++];
|
||||||
|
switch(chr) {
|
||||||
|
case 9:
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
case 1: case 8:
|
||||||
|
if (charset._center) {
|
||||||
|
charset._left = charset._left2 - charset.getStringWidth(a, buf, i);
|
||||||
|
} else {
|
||||||
|
charset._left = charset._left2;
|
||||||
|
}
|
||||||
|
charset._top += byte1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
charset.printChar(chr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
charset._ignoreCharsetMask = 0;
|
||||||
|
_stringXpos2[a] = charset._left;
|
||||||
|
_stringYpos2[a] = charset._top;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *Scumm::addMessageToStack(byte *msg) {
|
||||||
|
int num, numorg;
|
||||||
|
byte *ptr, chr;
|
||||||
|
|
||||||
|
numorg = num = _numInMsgStack;
|
||||||
|
ptr = getResourceAddress(0xC, 6);
|
||||||
|
|
||||||
|
if (ptr==NULL)
|
||||||
|
error("Message stack not allocated");
|
||||||
|
|
||||||
|
while ( (chr=*msg++) != 0) {
|
||||||
|
if (num > 500)
|
||||||
|
error("Message stack overflow");
|
||||||
|
|
||||||
|
ptr[num++] = chr;
|
||||||
|
|
||||||
|
if (chr==255) {
|
||||||
|
ptr[num++] = chr = *msg++;
|
||||||
|
|
||||||
|
if (chr==0 || chr!=2 && chr!=3 && chr!=8) {
|
||||||
|
ptr[num++] = chr = *msg++;
|
||||||
|
ptr[num++] = chr = *msg++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr[num++] = 0;
|
||||||
|
|
||||||
|
_numInMsgStack = num;
|
||||||
|
num = numorg;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ptr = getResourceAddress(0xC, 6);
|
||||||
|
chr = ptr[num++];
|
||||||
|
if (chr == 0)
|
||||||
|
break;
|
||||||
|
if (chr == 0xFF) {
|
||||||
|
ptr = getResourceAddress(0xC, 6);
|
||||||
|
chr = ptr[num++];
|
||||||
|
switch(chr) {
|
||||||
|
case 4:
|
||||||
|
unkAddMsgToStack2(
|
||||||
|
READ_LE_UINT16(getResourceAddress(0xC, 6)+ num)
|
||||||
|
);
|
||||||
|
num+=2;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
unkAddMsgToStack3(
|
||||||
|
READ_LE_UINT16(getResourceAddress(0xC, 6)+ num)
|
||||||
|
);
|
||||||
|
num+=2;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
unkAddMsgToStack4(
|
||||||
|
READ_LE_UINT16(getResourceAddress(0xC, 6)+ num)
|
||||||
|
);
|
||||||
|
num+=2;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
unkAddMsgToStack5(
|
||||||
|
READ_LE_UINT16(getResourceAddress(0xC, 6)+num)
|
||||||
|
);
|
||||||
|
num+=2;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
*_msgPtrToAdd++ = 0xFF;
|
||||||
|
*_msgPtrToAdd++ = chr;
|
||||||
|
*_msgPtrToAdd++ = getResourceAddress(0xC, 6)[num++];
|
||||||
|
*_msgPtrToAdd++ = getResourceAddress(0xC, 6)[num++];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*_msgPtrToAdd++ = 0xFF;
|
||||||
|
*_msgPtrToAdd++ = chr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chr!='@') {
|
||||||
|
*_msgPtrToAdd++ = chr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*_msgPtrToAdd = 0;
|
||||||
|
_numInMsgStack = numorg;
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkAddMsgToStack2(int var) {
|
||||||
|
int num,max;
|
||||||
|
byte flag;
|
||||||
|
|
||||||
|
num = readVar(var);
|
||||||
|
if (num < 0) {
|
||||||
|
*_msgPtrToAdd++ = '-';
|
||||||
|
num = -num;
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = 0;
|
||||||
|
max = 10000;
|
||||||
|
do {
|
||||||
|
if (num>=max || flag) {
|
||||||
|
*_msgPtrToAdd++ = num/max + '0';
|
||||||
|
num -= (num/max)*max;
|
||||||
|
flag=1;
|
||||||
|
}
|
||||||
|
max/=10;
|
||||||
|
if (max==1) flag=1;
|
||||||
|
} while (max);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkAddMsgToStack3(int var) {
|
||||||
|
int num,i;
|
||||||
|
|
||||||
|
num = readVar(var);
|
||||||
|
if (num) {
|
||||||
|
for (i=1; i<_maxVerbs; i++) {
|
||||||
|
if (num==verbs[i].verbid && !verbs[i].type && !verbs[i].saveid) {
|
||||||
|
addMessageToStack(getResourceAddress(8, i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addMessageToStack((byte*)"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkAddMsgToStack4(int var) {
|
||||||
|
int num;
|
||||||
|
|
||||||
|
num = readVar(var);
|
||||||
|
if (num) {
|
||||||
|
addMessageToStack(getObjOrActorName(num));
|
||||||
|
} else {
|
||||||
|
addMessageToStack((byte*)"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::unkAddMsgToStack5(int var) {
|
||||||
|
byte *ptr;
|
||||||
|
if (var) {
|
||||||
|
ptr = getResourceAddress(7, var);
|
||||||
|
if (ptr) {
|
||||||
|
addMessageToStack(ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addMessageToStack((byte*)"");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::initCharset(int charsetno) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!getResourceAddress(6, charsetno))
|
||||||
|
loadCharset(charsetno);
|
||||||
|
|
||||||
|
textslot.charset[0] = charsetno;
|
||||||
|
textslot.charset[1] = charsetno;
|
||||||
|
|
||||||
|
for (i=0; i<0x10; i++)
|
||||||
|
charset._colorMap[i] = _charsetData[charsetno][i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharsetRenderer::printChar(int chr) {
|
||||||
|
int d,right;
|
||||||
|
VirtScreen *vs;
|
||||||
|
|
||||||
|
_vm->checkRange(_vm->_maxCharsets-1, 1, _curId, "Printing with bad charset %d");
|
||||||
|
if (_vm->findVirtScreen(_top)==-1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vs = &_vm->virtscr[_vm->gdi.virtScreen];
|
||||||
|
|
||||||
|
if (chr=='@')
|
||||||
|
return;
|
||||||
|
|
||||||
|
_ptr = _vm->getResourceAddress(6, _curId) + 29;
|
||||||
|
|
||||||
|
_bpp = _unk2 = *_ptr;
|
||||||
|
_invNumBits = 8 - _bpp;
|
||||||
|
_bitMask = 0xFF << _invNumBits;
|
||||||
|
_colorMap[1] = _color;
|
||||||
|
|
||||||
|
_charOffs = READ_LE_UINT32(_ptr + chr*4 + 4);
|
||||||
|
|
||||||
|
if (!_charOffs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(_charOffs < 0x10000);
|
||||||
|
|
||||||
|
_charPtr = _ptr + _charOffs;
|
||||||
|
|
||||||
|
_width = _charPtr[0];
|
||||||
|
_height = _charPtr[1];
|
||||||
|
if (_unk12) {
|
||||||
|
_strLeft = 0;
|
||||||
|
_strTop = 0;
|
||||||
|
_strRight = 0;
|
||||||
|
_strBottom = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_disableOffsX) {
|
||||||
|
_offsX = 0;
|
||||||
|
} else {
|
||||||
|
d = _charPtr[2];
|
||||||
|
if (d>=0x80)
|
||||||
|
d -= 0x100;
|
||||||
|
_offsX = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = _charPtr[3];
|
||||||
|
if(d>=0x80)
|
||||||
|
d -= 0x100;
|
||||||
|
_offsY = d;
|
||||||
|
|
||||||
|
_top += _offsY;
|
||||||
|
_left += _offsX;
|
||||||
|
|
||||||
|
right = _left + _width;
|
||||||
|
|
||||||
|
if (right>_right+1 || _left < 0) {
|
||||||
|
_left = right;
|
||||||
|
_top -= _offsY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_disableOffsX = 0;
|
||||||
|
|
||||||
|
if (_unk12) {
|
||||||
|
_strLeft = _left;
|
||||||
|
_strTop = _top;
|
||||||
|
_strRight = _left;
|
||||||
|
_strBottom = _top;
|
||||||
|
_unk12 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_left < _strLeft)
|
||||||
|
_strLeft = _left;
|
||||||
|
|
||||||
|
if (_top < _strTop)
|
||||||
|
_strTop = _top;
|
||||||
|
|
||||||
|
_drawTop = _top - vs->topline;
|
||||||
|
_bottom = _drawTop + _height + _offsY;
|
||||||
|
|
||||||
|
_vm->updateDirtyRect(_vm->gdi.virtScreen, _left, right, _drawTop, _bottom, 0);
|
||||||
|
|
||||||
|
if (_vm->gdi.virtScreen==0)
|
||||||
|
_hasMask = true;
|
||||||
|
|
||||||
|
_bg_ptr = _vm->getResourceAddress(0xA, _vm->gdi.virtScreen+1)
|
||||||
|
+ vs->xstart + _drawTop * 320 + _left;
|
||||||
|
|
||||||
|
_where_to_draw_ptr = _vm->getResourceAddress(0xA, _vm->gdi.virtScreen+5)
|
||||||
|
+ vs->xstart + _drawTop * 320 + _left;
|
||||||
|
|
||||||
|
_mask_ptr = _vm->getResourceAddress(0xA, 9)
|
||||||
|
+ _drawTop * 40 + _left/8
|
||||||
|
+ _vm->_screenStartStrip;
|
||||||
|
|
||||||
|
_revBitMask = revBitMask[_left&7];
|
||||||
|
|
||||||
|
_virtScreenHeight = vs->height;
|
||||||
|
_charPtr += 4;
|
||||||
|
|
||||||
|
drawBits();
|
||||||
|
|
||||||
|
_left += _width;
|
||||||
|
if (_left > _strRight)
|
||||||
|
_strRight = _left;
|
||||||
|
|
||||||
|
if (_top + _height > _strBottom)
|
||||||
|
_strBottom = _top + _height;
|
||||||
|
|
||||||
|
_top -= _offsY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CharsetRenderer::drawBits() {
|
||||||
|
bool usemask;
|
||||||
|
byte *dst, *mask,maskmask;
|
||||||
|
int y,x;
|
||||||
|
int maskpos;
|
||||||
|
int color;
|
||||||
|
byte numbits,bits;
|
||||||
|
|
||||||
|
usemask = (_vm->gdi.virtScreen==0 && _ignoreCharsetMask==0);
|
||||||
|
|
||||||
|
bits = *_charPtr++;
|
||||||
|
numbits = 8;
|
||||||
|
|
||||||
|
dst = _bg_ptr;
|
||||||
|
mask = _mask_ptr;
|
||||||
|
y = 0;
|
||||||
|
|
||||||
|
for(y=0; y<_height && y+_drawTop < _virtScreenHeight;) {
|
||||||
|
maskmask = _revBitMask;
|
||||||
|
maskpos = 0;
|
||||||
|
|
||||||
|
for (x=0; x<_width; x++) {
|
||||||
|
color = (bits&_bitMask)>>_invNumBits;
|
||||||
|
if (color) {
|
||||||
|
if (usemask) {
|
||||||
|
mask[maskpos] |= maskmask;
|
||||||
|
}
|
||||||
|
*dst = _colorMap[color];
|
||||||
|
}
|
||||||
|
dst++;
|
||||||
|
bits <<= _bpp;
|
||||||
|
if ((numbits -= _bpp)==0) {
|
||||||
|
bits = *_charPtr++;
|
||||||
|
numbits = 8;
|
||||||
|
}
|
||||||
|
if ((maskmask>>=1)==0) {
|
||||||
|
maskmask = 0x80;
|
||||||
|
maskpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst = (_bg_ptr += 320);
|
||||||
|
mask += 40;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
164
sys.cpp
Normal file
164
sys.cpp
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:13 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
void *Scumm::fileOpen(const char *filename, int mode) {
|
||||||
|
_fileMode = mode;
|
||||||
|
_whereInResToRead = 0;
|
||||||
|
clearFileReadFailed(_fileHandle);
|
||||||
|
|
||||||
|
if (mode==1)
|
||||||
|
return fopen(filename, "rb");
|
||||||
|
|
||||||
|
if (mode==2) {
|
||||||
|
error("fileOpen: write not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::fileClose(void *file) {
|
||||||
|
if (_fileMode==1 || _fileMode==2)
|
||||||
|
fclose((FILE*)file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scumm::fileReadFailed(void *file) {
|
||||||
|
return _fileReadFailed != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::clearFileReadFailed(void *file) {
|
||||||
|
_fileReadFailed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scumm::fileEof(void *file) {
|
||||||
|
FILE *a = (FILE*)file;
|
||||||
|
return feof((FILE*)file) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::fileSeek(void *file, long offs, int whence) {
|
||||||
|
switch(_fileMode) {
|
||||||
|
case 1: case 2:
|
||||||
|
fseek((FILE*)file, offs, whence);
|
||||||
|
return;
|
||||||
|
case 3:
|
||||||
|
_whereInResToRead = offs;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::fileRead(void *file, void *ptr, uint32 size) {
|
||||||
|
byte *ptr2 = (byte*)ptr, *src;
|
||||||
|
|
||||||
|
switch(_fileMode) {
|
||||||
|
case 1:
|
||||||
|
if (size==0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((uint32)fread(ptr2, size, 1, (FILE*)file) != 1)
|
||||||
|
_fileReadFailed = true;
|
||||||
|
|
||||||
|
do {
|
||||||
|
*ptr2++ ^= _encbyte;
|
||||||
|
} while(--size);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
if (size==0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
src = getResourceAddress(0xC, 3) + _whereInResToRead;
|
||||||
|
_whereInResToRead += size;
|
||||||
|
do {
|
||||||
|
*ptr2++ = *src++ ^ _encbyte;
|
||||||
|
} while (--size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::fileReadByte() {
|
||||||
|
byte b;
|
||||||
|
byte *src;
|
||||||
|
|
||||||
|
switch(_fileMode) {
|
||||||
|
case 1:
|
||||||
|
if (fread(&b,1,1,(FILE*)_fileHandle) != 1)
|
||||||
|
_fileReadFailed = true;
|
||||||
|
return b ^ _encbyte;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
src = getResourceAddress(0xC, 3) + _whereInResToRead;
|
||||||
|
_whereInResToRead++;
|
||||||
|
return *src ^ _encbyte;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Scumm::fileReadWordLE() {
|
||||||
|
uint a = fileReadByte();
|
||||||
|
uint b = fileReadByte();
|
||||||
|
return a|(b<<8);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Scumm::fileReadDwordLE() {
|
||||||
|
uint a = fileReadWordLE();
|
||||||
|
uint b = fileReadWordLE();
|
||||||
|
return (b<<16)|a;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Scumm::fileReadWordBE() {
|
||||||
|
uint b = fileReadByte();
|
||||||
|
uint a = fileReadByte();
|
||||||
|
return a|(b<<8);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Scumm::fileReadDwordBE() {
|
||||||
|
uint b = fileReadWordBE();
|
||||||
|
uint a = fileReadWordBE();
|
||||||
|
return (b<<16)|a;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *Scumm::alloc(int size) {
|
||||||
|
byte *me = (byte*)::calloc(size+4,1);
|
||||||
|
*((uint32*)me) = 0xDEADBEEF;
|
||||||
|
return me + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::free(void *mem) {
|
||||||
|
byte *me = (byte*)mem - 4;
|
||||||
|
if ( *((uint32*)me) != 0xDEADBEEF) {
|
||||||
|
error("Freeing invalid block.");
|
||||||
|
}
|
||||||
|
|
||||||
|
*((uint32*)me) = 0xC007CAFE;
|
||||||
|
::free(me);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scumm::checkFixedDisk() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
288
verbs.cpp
Normal file
288
verbs.cpp
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:13 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
void Scumm::redrawVerbs() {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<_maxVerbs; i++)
|
||||||
|
drawVerb(i, 0);
|
||||||
|
verbMouseOver(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::checkExecVerbs() {
|
||||||
|
int i,over;
|
||||||
|
VerbSlot *vs;
|
||||||
|
|
||||||
|
if (_userPut<=0 || _mouseButStat==0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_mouseButStat < 0x200) {
|
||||||
|
/* Check keypresses */
|
||||||
|
vs = &verbs[1];
|
||||||
|
for (i=1; i<_maxVerbs; i++,vs++) {
|
||||||
|
if (vs->verbid && vs->saveid && vs->curmode==1) {
|
||||||
|
if (_mouseButStat == vs->key) {
|
||||||
|
runInputScript(1, vs->verbid, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runInputScript(4, _mouseButStat, 1);
|
||||||
|
} else if (_mouseButStat&0xC000) {
|
||||||
|
byte code = _mouseButStat&0x8000 ? 1 : 2;
|
||||||
|
if (virtscr[0].topline <= mouse.y || virtscr[0].topline + virtscr[0].height > mouse.y) {
|
||||||
|
over = checkMouseOver(mouse.x, mouse.y);
|
||||||
|
if (over != 0) {
|
||||||
|
runInputScript(1,verbs[over].verbid,code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
runInputScript(2, 0, code);
|
||||||
|
} else {
|
||||||
|
over=checkMouseOver(mouse.x, mouse.y);
|
||||||
|
runInputScript(1, over!=0 ? verbs[over].verbid : 0, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::verbMouseOver(int verb) {
|
||||||
|
if (_verbMouseOver==verb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (verbs[_verbMouseOver].type!=1) {
|
||||||
|
drawVerb(_verbMouseOver, 0);
|
||||||
|
_verbMouseOver = verb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbs[verb].type!=1 && verbs[verb].hicolor) {
|
||||||
|
drawVerb(verb, 1);
|
||||||
|
_verbMouseOver = verb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::checkMouseOver(int x, int y) {
|
||||||
|
VerbSlot *vs;
|
||||||
|
int i = _maxVerbs;
|
||||||
|
|
||||||
|
vs = &verbs[i];
|
||||||
|
do {
|
||||||
|
if (vs->curmode!=1 || !vs->verbid || vs->saveid ||
|
||||||
|
y < vs->y || y >= vs->bottom)
|
||||||
|
continue;
|
||||||
|
if (vs->center) {
|
||||||
|
if (x < -(vs->right - vs->x - vs->x) || x >= vs->right)
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (x < vs->x || x >= vs->right)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
} while (--vs, i--);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::drawVerb(int vrb, int mode) {
|
||||||
|
VerbSlot *vs;
|
||||||
|
byte color;
|
||||||
|
byte tmp;
|
||||||
|
|
||||||
|
if (!vrb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vs = &verbs[vrb];
|
||||||
|
|
||||||
|
if (!vs->saveid && vs->curmode && vs->verbid) {
|
||||||
|
if (vs->type==1) {
|
||||||
|
drawVerbBitmap(vrb, vs->x, vs->y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
restoreVerbBG(vrb);
|
||||||
|
|
||||||
|
_stringCharset[4] = vs->charset_nr;
|
||||||
|
_stringXpos[4] = vs->x;
|
||||||
|
_stringYpos[4] = vs->y;
|
||||||
|
_stringRight[4] = 319;
|
||||||
|
_stringCenter[4] = vs->center;
|
||||||
|
if (mode && vs->hicolor)
|
||||||
|
color = vs->hicolor;
|
||||||
|
else
|
||||||
|
color = vs->color;
|
||||||
|
_stringColor[4] = color;
|
||||||
|
if (vs->curmode==2)
|
||||||
|
_stringColor[4] = vs->dimcolor;
|
||||||
|
_messagePtr = getResourceAddress(8, vrb);
|
||||||
|
assert(_messagePtr);
|
||||||
|
tmp = charset._center;
|
||||||
|
charset._center = 0;
|
||||||
|
drawString(4);
|
||||||
|
charset._center = tmp;
|
||||||
|
vs->right = charset._strRight;
|
||||||
|
vs->bottom = charset._strBottom;
|
||||||
|
vs->oldleft = charset._strLeft;
|
||||||
|
vs->oldright = charset._strRight;
|
||||||
|
vs->oldtop = charset._strTop;
|
||||||
|
vs->oldbottom = charset._strBottom;
|
||||||
|
charset._strLeft = charset._strRight;
|
||||||
|
} else {
|
||||||
|
restoreVerbBG(vrb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::restoreVerbBG(int verb) {
|
||||||
|
VerbSlot *vs;
|
||||||
|
|
||||||
|
vs = &verbs[verb];
|
||||||
|
|
||||||
|
if (vs->oldleft != -1) {
|
||||||
|
dseg_4E3C = vs->bkcolor;
|
||||||
|
restoreBG(vs->oldleft, vs->oldtop, vs->oldright, vs->oldbottom);
|
||||||
|
vs->oldleft = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::drawVerbBitmap(int vrb, int x, int y) {
|
||||||
|
int nozbufs;
|
||||||
|
VirtScreen *vs;
|
||||||
|
VerbSlot *vst;
|
||||||
|
byte twobufs, *imptr;
|
||||||
|
int ydiff, xstrip;
|
||||||
|
int imgw, imgh;
|
||||||
|
int i;
|
||||||
|
byte *IMHD_ptr;
|
||||||
|
|
||||||
|
if (findVirtScreen(y) == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_lastXstart = virtscr[0].xstart;
|
||||||
|
nozbufs = _numZBuffer;
|
||||||
|
_numZBuffer = 0;
|
||||||
|
|
||||||
|
vs = &virtscr[gdi.virtScreen];
|
||||||
|
|
||||||
|
twobufs = vs->alloctwobuffers;
|
||||||
|
vs->alloctwobuffers = 0;
|
||||||
|
|
||||||
|
xstrip = x>>3;
|
||||||
|
ydiff = y - vs->topline;
|
||||||
|
|
||||||
|
IMHD_ptr = findResource2(MKID('IMHD'), getResourceAddress(8, vrb));
|
||||||
|
|
||||||
|
imgw = READ_LE_UINT16(IMHD_ptr+0x14) >> 3;
|
||||||
|
imgh = READ_LE_UINT16(IMHD_ptr+0x16) >> 3;
|
||||||
|
|
||||||
|
imptr = findResource2(MKID('IM01'), NULL);
|
||||||
|
if (!imptr)
|
||||||
|
error("No image for verb %d", vrb);
|
||||||
|
|
||||||
|
for (i=0; i<imgw; i++) {
|
||||||
|
_drawBmpX = xstrip + i;
|
||||||
|
if (_drawBmpX < 40) {
|
||||||
|
_drawBmpY = ydiff;
|
||||||
|
gdi.numLinesToProcess = imgh<<3;
|
||||||
|
drawBmp(imptr, i, 1, 1, "Verb", READ_LE_UINT16(IMHD_ptr+8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vst = &verbs[vrb];
|
||||||
|
vst->right = vst->x + imgw*8;
|
||||||
|
vst->bottom = vst->y + imgh*8;
|
||||||
|
vst->oldleft = vst->x;
|
||||||
|
vst->oldright = vst->right;
|
||||||
|
vst->oldtop = vst->y;
|
||||||
|
vst->oldbottom = vst->bottom;
|
||||||
|
_numZBuffer = nozbufs;
|
||||||
|
|
||||||
|
vs->alloctwobuffers = twobufs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Scumm::getVerbSlot(int id, int mode) {
|
||||||
|
int i;
|
||||||
|
for (i=1; i<_maxVerbs; i++) {
|
||||||
|
if (verbs[i].verbid == id && verbs[i].saveid == mode) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::killVerb(int slot) {
|
||||||
|
VerbSlot *vs;
|
||||||
|
|
||||||
|
if (slot==0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vs = &verbs[slot];
|
||||||
|
vs->verbid = 0;
|
||||||
|
vs->curmode = 0;
|
||||||
|
|
||||||
|
nukeResource(8, slot);
|
||||||
|
|
||||||
|
if (vs->saveid==0) {
|
||||||
|
drawVerb(slot, 0);
|
||||||
|
verbMouseOver(0);
|
||||||
|
}
|
||||||
|
vs->saveid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scumm::setVerbObject(int room, int object, int verb) {
|
||||||
|
int numobj, i;
|
||||||
|
byte *obimptr;
|
||||||
|
uint32 imoffs,size;
|
||||||
|
byte *roomptr,*tmp_roomptr;
|
||||||
|
ImageHeader *imhd;
|
||||||
|
RoomHeader *roomhdr;
|
||||||
|
|
||||||
|
if (whereIsObject(object) == 4)
|
||||||
|
error("Can't grab verb image from flobject");
|
||||||
|
|
||||||
|
ensureResourceLoaded(1,room);
|
||||||
|
roomptr = getResourceAddress(1, room);
|
||||||
|
roomhdr = (RoomHeader*)findResource(MKID('RMHD'), roomptr);
|
||||||
|
|
||||||
|
numobj = READ_LE_UINT16(&roomhdr->numObjects);
|
||||||
|
if (numobj==0)
|
||||||
|
error("No images found in room %d", room);
|
||||||
|
if (numobj > 200)
|
||||||
|
error("More (%d) than %d objects in room %d", numobj, 200, room);
|
||||||
|
|
||||||
|
tmp_roomptr = roomptr;
|
||||||
|
for (i=1; i<=numobj; i++) {
|
||||||
|
obimptr = findResource(MKID('OBIM'), tmp_roomptr);
|
||||||
|
if (obimptr==NULL)
|
||||||
|
error("Not enough image blocks in room %d", room);
|
||||||
|
imhd = (ImageHeader*)findResource2(MKID('IMHD'), obimptr);
|
||||||
|
if ( READ_LE_UINT16(&imhd->obj_id) == object) {
|
||||||
|
imoffs = obimptr - roomptr;
|
||||||
|
size = READ_BE_UINT32_UNALIGNED(obimptr+4);
|
||||||
|
createResource(8, verb, size);
|
||||||
|
obimptr = getResourceAddress(1, room) + imoffs;
|
||||||
|
memcpy(getResourceAddress(8, verb), obimptr, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tmp_roomptr = NULL;
|
||||||
|
}
|
||||||
|
error("Image %d not found in room %d", object, room);
|
||||||
|
}
|
4
whatsnew.txt
Normal file
4
whatsnew.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
0.0.1 (2001-10-08):
|
||||||
|
- initial version
|
||||||
|
|
||||||
|
|
787
windows.cpp
Normal file
787
windows.cpp
Normal file
|
@ -0,0 +1,787 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2001 Ludvig Strigeus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Change Log:
|
||||||
|
* $Log$
|
||||||
|
* Revision 1.1 2001/10/09 14:30:13 strigeus
|
||||||
|
* Initial revision
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USE_DIRECTX
|
||||||
|
#define INITGUID
|
||||||
|
#include <ddraw.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if USE_DRAWDIB
|
||||||
|
#include <vfw.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "scumm.h"
|
||||||
|
|
||||||
|
#define SRC_WIDTH 320
|
||||||
|
#define SRC_HEIGHT 200
|
||||||
|
#define SRC_PITCH (320)
|
||||||
|
|
||||||
|
#define DEST_WIDTH 320
|
||||||
|
#define DEST_HEIGHT 200
|
||||||
|
|
||||||
|
#define USE_DIRECTX 0
|
||||||
|
#define USE_DRAWDIB 0
|
||||||
|
#define USE_GDI 1
|
||||||
|
|
||||||
|
#if USE_GDI
|
||||||
|
typedef struct DIB {
|
||||||
|
HBITMAP hSect;
|
||||||
|
byte *buf;
|
||||||
|
RGBQUAD *pal;
|
||||||
|
bool new_pal;
|
||||||
|
} DIB;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class WndMan {
|
||||||
|
HMODULE hInst;
|
||||||
|
HWND hWnd;
|
||||||
|
|
||||||
|
|
||||||
|
bool terminated;
|
||||||
|
|
||||||
|
#if USE_GDI
|
||||||
|
// BITMAPINFO *biHeader;
|
||||||
|
// byte *BmpBG;
|
||||||
|
public:
|
||||||
|
DIB dib;
|
||||||
|
private:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_DRAWDIB
|
||||||
|
BITMAPINFOHEADER *biHeader;
|
||||||
|
HDRAWDIB hdb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
byte *_vgabuf;
|
||||||
|
|
||||||
|
Scumm *_scumm;
|
||||||
|
|
||||||
|
#if USE_DIRECTX
|
||||||
|
IDirectDrawSurface4 *MainSurf,*Surf2;
|
||||||
|
IDirectDraw *DxObject;
|
||||||
|
IDirectDraw4 *Dx4Object;
|
||||||
|
IDirectDrawPalette *DxPal;
|
||||||
|
bool OutOfGame;
|
||||||
|
void InitDirectX();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
|
||||||
|
bool handleMessage();
|
||||||
|
void run();
|
||||||
|
void setPalette(byte *ctab, int first, int num);
|
||||||
|
void writeToScreen();
|
||||||
|
|
||||||
|
#if USE_GDI
|
||||||
|
bool allocateDIB(int w, int h);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
void Error(const char *msg) {
|
||||||
|
OutputDebugString(msg);
|
||||||
|
MessageBoxA(0, msg, "Error", MB_ICONSTOP);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sel;
|
||||||
|
Scumm scumm;
|
||||||
|
WndMan wm[1];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void modifyslot(int sel, int what);
|
||||||
|
|
||||||
|
|
||||||
|
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||||
|
WndMan *wm = (WndMan*)GetWindowLong(hWnd, GWL_USERDATA);
|
||||||
|
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case WM_DESTROY:
|
||||||
|
case WM_CLOSE:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
case WM_CHAR:
|
||||||
|
wm->_scumm->_keyPressed = wParam;
|
||||||
|
break;
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
wm->_scumm->mouse.x = ((int16*)&lParam)[0];
|
||||||
|
wm->_scumm->mouse.y = ((int16*)&lParam)[1];
|
||||||
|
break;
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
wm->_scumm->_leftBtnPressed |= 1;
|
||||||
|
break;
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
wm->_scumm->_rightBtnPressed |= 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_GDI
|
||||||
|
|
||||||
|
void copy_320x200_to_640x400(byte *s, byte *d) {
|
||||||
|
_asm {
|
||||||
|
push ebp
|
||||||
|
|
||||||
|
mov esi,s
|
||||||
|
mov edi,d
|
||||||
|
|
||||||
|
mov ebp,SRC_HEIGHT
|
||||||
|
againouter:
|
||||||
|
|
||||||
|
mov ebx,320/4
|
||||||
|
againinner:
|
||||||
|
mov eax,[esi]
|
||||||
|
mov dl,ah
|
||||||
|
mov dh,ah
|
||||||
|
shl edx,16
|
||||||
|
mov dl,al
|
||||||
|
mov dh,al
|
||||||
|
shr eax,16
|
||||||
|
mov cl,ah
|
||||||
|
mov ch,ah
|
||||||
|
shl ecx,16
|
||||||
|
mov cl,al
|
||||||
|
mov ch,al
|
||||||
|
|
||||||
|
mov [edi],edx
|
||||||
|
mov [edi+4],ecx
|
||||||
|
mov [edi+640],edx
|
||||||
|
mov [edi+644],ecx
|
||||||
|
|
||||||
|
add esi,4
|
||||||
|
add edi,8
|
||||||
|
|
||||||
|
dec ebx
|
||||||
|
jnz againinner
|
||||||
|
// add esi,15
|
||||||
|
add edi,640
|
||||||
|
dec ebp
|
||||||
|
jnz againouter
|
||||||
|
pop ebp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WndMan::allocateDIB(int w, int h) {
|
||||||
|
struct {
|
||||||
|
BITMAPINFOHEADER bih;
|
||||||
|
RGBQUAD rgb[256];
|
||||||
|
} d;
|
||||||
|
|
||||||
|
if (dib.hSect)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
memset(&d.bih, 0, sizeof(d.bih));
|
||||||
|
d.bih.biSize = sizeof(d.bih);
|
||||||
|
d.bih.biWidth = w;
|
||||||
|
d.bih.biHeight = -h;
|
||||||
|
d.bih.biPlanes = 1;
|
||||||
|
d.bih.biBitCount = 8;
|
||||||
|
d.bih.biCompression = BI_RGB;
|
||||||
|
|
||||||
|
memcpy(d.rgb, dib.pal, 256*sizeof(RGBQUAD));
|
||||||
|
dib.new_pal=false;
|
||||||
|
|
||||||
|
dib.hSect = CreateDIBSection(0, (BITMAPINFO*)&d, DIB_RGB_COLORS, (void**)&dib.buf,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
return dib.hSect != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WndMan::writeToScreen() {
|
||||||
|
RECT r;
|
||||||
|
HDC dc,bmpdc;
|
||||||
|
HBITMAP bmpOld;
|
||||||
|
// if (!BmpBG)
|
||||||
|
// BmpBG = (byte*)LocalAlloc(LMEM_FIXED, DEST_WIDTH*DEST_HEIGHT);
|
||||||
|
#if DEST_WIDTH==640
|
||||||
|
copy_320x200_to_640x400(_vgabuf, dib.buf);
|
||||||
|
#endif
|
||||||
|
#if DEST_WIDTH==320
|
||||||
|
if (_vgabuf) {
|
||||||
|
for (int y=0; y<200; y++) {
|
||||||
|
memcpy(dib.buf + y*320,_vgabuf + y*320, 320);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// setsel(dib.buf);
|
||||||
|
|
||||||
|
r.left = r.top = 0;
|
||||||
|
r.right = DEST_WIDTH;
|
||||||
|
r.bottom = DEST_HEIGHT;
|
||||||
|
|
||||||
|
dc = GetDC(hWnd);
|
||||||
|
|
||||||
|
bmpdc = CreateCompatibleDC(dc);
|
||||||
|
bmpOld = (HBITMAP)SelectObject(bmpdc, dib.hSect);
|
||||||
|
|
||||||
|
if (dib.new_pal) {
|
||||||
|
dib.new_pal = false;
|
||||||
|
SetDIBColorTable(bmpdc, 0, 256, dib.pal);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetStretchBltMode(dc, BLACKONWHITE);
|
||||||
|
#if DEST_WIDTH==640
|
||||||
|
StretchBlt(dc, r.left, r.top, r.right-r.left, r.bottom-r.top, bmpdc, 0, 0, 640,480, SRCCOPY);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DEST_WIDTH==320
|
||||||
|
StretchBlt(dc, r.left, r.top, r.right-r.left, r.bottom-r.top, bmpdc, 0, 0, 320,200, SRCCOPY);
|
||||||
|
#endif
|
||||||
|
// //StretchDIBits(dc, r.left, r.top, r.right - r.left, r.bottom - r.top, 0, 0, DEST_WIDTH, DEST_HEIGHT, BmpBG, biHeader, DIB_RGB_COLORS, SRCCOPY);
|
||||||
|
|
||||||
|
|
||||||
|
SelectObject(bmpdc, bmpOld);
|
||||||
|
DeleteDC(bmpdc);
|
||||||
|
ReleaseDC(hWnd, dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WndMan::setPalette(byte *ctab, int first, int num) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
for (i=0; i<256; i++) {
|
||||||
|
dib.pal[i].rgbRed = ctab[i*3+0]<<2;
|
||||||
|
dib.pal[i].rgbGreen = ctab[i*3+1]<<2;
|
||||||
|
dib.pal[i].rgbBlue = ctab[i*3+2]<<2;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
for (i=0; i<256; i++) {
|
||||||
|
dib.pal[i].rgbRed = i;
|
||||||
|
dib.pal[i].rgbGreen = i;
|
||||||
|
dib.pal[i].rgbBlue = i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dib.new_pal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_DIRECTX
|
||||||
|
|
||||||
|
void WndMan::writeToScreen() {
|
||||||
|
RECT r;
|
||||||
|
DDSURFACEDESC2 dd;
|
||||||
|
|
||||||
|
r.left = r.top = 0;
|
||||||
|
r.right = SRC_WIDTH;
|
||||||
|
r.bottom = SRC_HEIGHT;
|
||||||
|
|
||||||
|
if (OutOfGame) {
|
||||||
|
if (GetForegroundWindow() != hWnd) return;
|
||||||
|
OutOfGame = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd.dwSize = sizeof(dd);
|
||||||
|
|
||||||
|
int j;
|
||||||
|
do {
|
||||||
|
j = MainSurf->Lock(NULL, &dd, DDLOCK_WRITEONLY, NULL);
|
||||||
|
if (j!=DDERR_SURFACELOST) break;
|
||||||
|
if (MainSurf->Restore() != DD_OK) {
|
||||||
|
OutOfGame = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
if (j == DD_OK) {
|
||||||
|
byte *d = (byte*)dd.lpSurface;
|
||||||
|
byte *s = _vgabuf;
|
||||||
|
|
||||||
|
for(int h=SRC_HEIGHT;--h>=0; ) {
|
||||||
|
memcpy(d, s, SRC_WIDTH);
|
||||||
|
d+=dd.lPitch;
|
||||||
|
s+=SRC_PITCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainSurf->Unlock(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WndMan::setPalette(byte *ctab, int first, int num) {
|
||||||
|
PALETTEENTRY pal[256];
|
||||||
|
|
||||||
|
for (int i=0; i<256; i++) {
|
||||||
|
pal[i].peFlags = 0;
|
||||||
|
pal[i].peRed = *ctab++;
|
||||||
|
pal[i].peGreen = *ctab++;
|
||||||
|
pal[i].peBlue = *ctab++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DxPal->SetEntries(0, 0, 256, (PALETTEENTRY*)&pal);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDirectDrawSurface4 *CreateMainSurface(IDirectDraw4 *dd);
|
||||||
|
|
||||||
|
void WndMan::InitDirectX() {
|
||||||
|
|
||||||
|
if (DirectDrawCreate(NULL, &DxObject, NULL) != DD_OK) Error("DirectDrawCreate failed!");
|
||||||
|
if (DxObject->QueryInterface(IID_IDirectDraw4, (void**)&Dx4Object) != DD_OK) Error("QueryInterface failed!");
|
||||||
|
|
||||||
|
if (Dx4Object->SetCooperativeLevel(hWnd,DDSCL_NORMAL) != DD_OK) Error("SetCooperativeLevel failed!");
|
||||||
|
|
||||||
|
DDCAPS ddcaps;
|
||||||
|
BOOL bHasOverlay, bHasColorKey, bCanStretch;
|
||||||
|
ddcaps.dwSize = sizeof( ddcaps );
|
||||||
|
if (Dx4Object->GetCaps(&ddcaps, NULL ) != DD_OK) Error("GetCaps failed!");
|
||||||
|
|
||||||
|
/* Determine if the hardware supports overlay surfaces */
|
||||||
|
bHasOverlay = ddcaps.dwCaps & DDCAPS_OVERLAY;
|
||||||
|
|
||||||
|
/* Determine if the hardware supports colorkeying */
|
||||||
|
bHasColorKey = ((ddcaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) ? TRUE : FALSE;
|
||||||
|
|
||||||
|
/* Determine if the hardware supports scaling of the overlay surface */
|
||||||
|
bCanStretch = ((ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH) == DDCAPS_OVERLAYSTRETCH) ? TRUE : FALSE;
|
||||||
|
|
||||||
|
if ( ( ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST ) ||
|
||||||
|
( ddcaps.dwCaps & DDCAPS_ALIGNBOUNDARYSRC ) ||
|
||||||
|
( ddcaps.dwCaps & DDCAPS_ALIGNSIZEDEST ) ||
|
||||||
|
( ddcaps.dwCaps & DDCAPS_ALIGNSIZESRC ) ) {
|
||||||
|
|
||||||
|
Error("Alignment restriction!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Are any overlays available for use?
|
||||||
|
if ( ddcaps.dwMaxVisibleOverlays ==
|
||||||
|
ddcaps.dwCurrVisibleOverlays )
|
||||||
|
{
|
||||||
|
Error("No overlay free");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!bHasOverlay || !bHasColorKey || !bCanStretch) {
|
||||||
|
Error("Bad hardware!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create primary surface */
|
||||||
|
|
||||||
|
DDSURFACEDESC2 ddsd;
|
||||||
|
DDSCAPS ddscaps;
|
||||||
|
LPDIRECTDRAWSURFACE4 lpFrontBuffer;
|
||||||
|
LPDIRECTDRAWSURFACE4 lpBackBuffer;
|
||||||
|
LPDIRECTDRAWSURFACE4 lpPrimary;
|
||||||
|
HRESULT LastError;
|
||||||
|
RECT rectOverlaySource, rectOverlayDest;
|
||||||
|
DDOVERLAYFX ddofx;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (!CreateMainSurface(Dx4Object))
|
||||||
|
// Error("sad");
|
||||||
|
|
||||||
|
/* Create the primary surface */
|
||||||
|
memset(&ddsd, 0, sizeof(ddsd));
|
||||||
|
ddsd.dwSize = sizeof(ddsd);
|
||||||
|
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
||||||
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP |
|
||||||
|
DDSCAPS_COMPLEX |
|
||||||
|
DDSCAPS_VIDEOMEMORY;
|
||||||
|
ddsd.dwBackBufferCount = 1;
|
||||||
|
|
||||||
|
if (Dx4Object->CreateSurface(&ddsd, &lpPrimary, NULL) != DD_OK)
|
||||||
|
Error("Main surface creation failed!");
|
||||||
|
|
||||||
|
/* Create a flippable scaleable overlay surface */
|
||||||
|
ddsd.dwSize = sizeof(ddsd);
|
||||||
|
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_BACKBUFFERCOUNT | DDSD_PIXELFORMAT;
|
||||||
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY;
|
||||||
|
ddsd.dwBackBufferCount = 1; /* One back buffer for triple buffering, set to 2 */
|
||||||
|
ddsd.dwWidth = 320;
|
||||||
|
ddsd.dwHeight = 240;
|
||||||
|
// ddsd.ddckCKDestOverlay.dwColorSpaceLowValue = 0x123456;
|
||||||
|
// ddsd.ddckCKDestOverlay.dwColorSpaceHighValue = 0x123456;
|
||||||
|
|
||||||
|
|
||||||
|
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
|
||||||
|
|
||||||
|
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
||||||
|
ddsd.ddpfPixelFormat.dwFourCC = 0;
|
||||||
|
ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
|
||||||
|
ddsd.ddpfPixelFormat.dwRBitMask = 0x7C00; //0x7C00 is a hexadecimal memory address
|
||||||
|
ddsd.ddpfPixelFormat.dwGBitMask = 0x03e0;
|
||||||
|
ddsd.ddpfPixelFormat.dwBBitMask = 0x001F;
|
||||||
|
ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0;
|
||||||
|
|
||||||
|
// ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
|
||||||
|
// ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
|
||||||
|
|
||||||
|
if ((LastError = Dx4Object->CreateSurface(&ddsd, &lpFrontBuffer, NULL)) != DD_OK) {
|
||||||
|
if (LastError==DDERR_NOOVERLAYHW )
|
||||||
|
Error("No hardware!");
|
||||||
|
else
|
||||||
|
Error("2nd surface failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (Dx4Object->SetCooperativeLevel(hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE) != DD_OK) Error("SetCooperativeLevel failed!");
|
||||||
|
// if (Dx4Object->SetDisplayMode(SRC_WIDTH,SRC_HEIGHT,8,0,DDSDM_STANDARDVGAMODE) != DD_OK) Error("SetDisplayMode failed!");
|
||||||
|
if (!(MainSurf = CreateMainSurface(Dx4Object))) Error("CreateMainSurface failed!");
|
||||||
|
if (!(Surf2 = Create2ndSurface(Dx4Object, _vgabuf))) Error("Create 2ndSurface failed!");
|
||||||
|
if (!(DxPal = CreateGamePalette(Dx4Object))) Error("CreateGamePalette failed!");
|
||||||
|
if (MainSurf->SetPalette(DxPal) != DD_OK) Error("SetPalette Failed!");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IDirectDrawSurface4 *CreateMainSurface(IDirectDraw4 *dd) {
|
||||||
|
DDSURFACEDESC2 d;
|
||||||
|
IDirectDrawSurface4 *ds;
|
||||||
|
|
||||||
|
// if(dd->GetGDISurface(&ds) != DD_OK)
|
||||||
|
// return NULL;
|
||||||
|
|
||||||
|
memset(&d, 0, sizeof(d));
|
||||||
|
|
||||||
|
d.dwSize = sizeof(d);
|
||||||
|
d.dwFlags = DDSD_CAPS;
|
||||||
|
d.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
if ((i = dd->CreateSurface(&d, &ds, NULL)) != DD_OK)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IDirectDrawSurface4 *Create2ndSurface(IDirectDraw4 *dd, byte *surfmem) {
|
||||||
|
DDSURFACEDESC2 d;
|
||||||
|
IDirectDrawSurface4 *ds;
|
||||||
|
|
||||||
|
memset(&d, 0, sizeof(d));
|
||||||
|
|
||||||
|
d.dwSize = sizeof(d);
|
||||||
|
d.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH | /*DDSD_LPSURFACE |*/ DDSD_PIXELFORMAT;
|
||||||
|
d.dwWidth = 640/*SRC_WIDTH*/;
|
||||||
|
d.dwHeight = 480/*SRC_HEIGHT*/;
|
||||||
|
d.lPitch = 640;
|
||||||
|
d.lpSurface = surfmem;
|
||||||
|
|
||||||
|
d.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
||||||
|
d.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
|
||||||
|
d.ddpfPixelFormat.dwRGBBitCount = 8;
|
||||||
|
|
||||||
|
d.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
if ((i = dd->CreateSurface(&d, &ds, NULL)) != DD_OK)
|
||||||
|
return NULL;
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDirectDrawPalette *CreateGamePalette(IDirectDraw4 *dd) {
|
||||||
|
PALETTEENTRY pal[256];
|
||||||
|
int i;
|
||||||
|
IDirectDrawPalette *p;
|
||||||
|
|
||||||
|
memset(&pal, 0, sizeof(pal));
|
||||||
|
if ((i=dd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, pal, &p, NULL)) != DD_OK)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_DRAWDIB
|
||||||
|
void WndMan::writeToScreen() {
|
||||||
|
RECT r;
|
||||||
|
HDC dc;
|
||||||
|
|
||||||
|
r.left = r.top = 0;
|
||||||
|
r.right = DEST_WIDTH/2;
|
||||||
|
r.bottom = DEST_HEIGHT/2;
|
||||||
|
|
||||||
|
dc = GetDC(hWnd);
|
||||||
|
|
||||||
|
DrawDibRealize(hdb, dc, TRUE);
|
||||||
|
DrawDibDraw(hdb, dc, r.left, r.top, r.right-r.left, r.bottom-r.top, biHeader, _vgabuf, 0, 0, 320, 240, 0);
|
||||||
|
|
||||||
|
// StretchDIBits(dc, r.left, r.top, r.right - r.left, r.bottom - r.top, 0, 0, DEST_WIDTH, DEST_HEIGHT, BmpBG, biHeader, DIB_RGB_COLORS, SRCCOPY);
|
||||||
|
ReleaseDC(hWnd, dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WndMan::setPalette(byte *ctab, int first, int num) {
|
||||||
|
PALETTEENTRY pal[256];
|
||||||
|
for (int i=0; i < num; i++,ctab+=3) {
|
||||||
|
pal[i].peFlags = 0;
|
||||||
|
pal[i].peRed = ctab[0];
|
||||||
|
pal[i].peGreen = ctab[1];
|
||||||
|
pal[i].peBlue = ctab[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawDibChangePalette(hdb, 0, 16, pal);
|
||||||
|
|
||||||
|
GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
HWND globWnd;
|
||||||
|
|
||||||
|
void WndMan::init() {
|
||||||
|
|
||||||
|
/* Retrieve the handle of this module */
|
||||||
|
hInst = GetModuleHandle(NULL);
|
||||||
|
|
||||||
|
/* Register the window class */
|
||||||
|
WNDCLASSEX wcex;
|
||||||
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
wcex.lpfnWndProc = (WNDPROC)WndProc;
|
||||||
|
wcex.cbClsExtra = 0;
|
||||||
|
wcex.cbWndExtra = 0;
|
||||||
|
wcex.hInstance = hInst;
|
||||||
|
wcex.hIcon = 0;
|
||||||
|
wcex.hCursor = ::LoadCursor(NULL, IDC_ARROW);
|
||||||
|
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
||||||
|
wcex.lpszMenuName = 0;
|
||||||
|
wcex.lpszClassName = "ScummVM";
|
||||||
|
wcex.hIconSm = 0;
|
||||||
|
if (!RegisterClassEx(&wcex))
|
||||||
|
Error("Cannot register window class!");
|
||||||
|
|
||||||
|
#if USE_DIRECTX
|
||||||
|
hWnd = CreateWindow("ScummVM", "ScummVM", 0,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, SRC_WIDTH, SRC_HEIGHT, NULL, NULL, hInst, NULL);
|
||||||
|
|
||||||
|
SetWindowLong(hWnd, GWL_USERDATA, (long)this);
|
||||||
|
SetWindowLong(hWnd, GWL_STYLE, 0);
|
||||||
|
ShowCursor(false);
|
||||||
|
|
||||||
|
|
||||||
|
InitDirectX();
|
||||||
|
|
||||||
|
ShowWindow(hWnd, SW_SHOW);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_GDI
|
||||||
|
globWnd = hWnd = CreateWindow("ScummVM", "ScummVM", WS_OVERLAPPEDWINDOW,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, DEST_WIDTH+10, DEST_HEIGHT+30, NULL, NULL, hInst, NULL);
|
||||||
|
SetWindowLong(hWnd, GWL_USERDATA, (long)this);
|
||||||
|
// ShowCursor(false);
|
||||||
|
|
||||||
|
dib.pal = (RGBQUAD*)calloc(sizeof(RGBQUAD),256);
|
||||||
|
dib.new_pal = false;
|
||||||
|
|
||||||
|
if (!allocateDIB(DEST_WIDTH, DEST_HEIGHT))
|
||||||
|
Error("allocateDIB failed!");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
biHeader = (BITMAPINFO*)LocalAlloc(LMEM_FIXED, sizeof(BITMAPINFOHEADER) + 1024 );
|
||||||
|
memset(biHeader, 0, sizeof(BITMAPINFOHEADER) + 1024);
|
||||||
|
|
||||||
|
biHeader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
biHeader->bmiHeader.biWidth = DEST_WIDTH;
|
||||||
|
biHeader->bmiHeader.biHeight = -DEST_HEIGHT; /* top down */
|
||||||
|
biHeader->bmiHeader.biPlanes = 1;
|
||||||
|
biHeader->bmiHeader.biBitCount = 8; /* 256 colors */
|
||||||
|
biHeader->bmiHeader.biCompression = BI_RGB; /* uncompressed */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ShowWindow(hWnd, SW_SHOW);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_DRAWDIB
|
||||||
|
hdb = DrawDibOpen();
|
||||||
|
|
||||||
|
hWnd = CreateWindow("ScummVM", "ScummVM", WS_OVERLAPPEDWINDOW,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, DEST_WIDTH+10, DEST_HEIGHT+30, NULL, NULL, hInst, NULL);
|
||||||
|
SetWindowLong(hWnd, GWL_USERDATA, (long)this);
|
||||||
|
ShowCursor(false);
|
||||||
|
|
||||||
|
biHeader = (BITMAPINFOHEADER*)LocalAlloc(LMEM_FIXED, sizeof(BITMAPINFOHEADER));
|
||||||
|
memset(biHeader, 0, sizeof(BITMAPINFOHEADER));
|
||||||
|
|
||||||
|
biHeader->biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
biHeader->biWidth = SRC_PITCH;
|
||||||
|
biHeader->biHeight = SRC_HEIGHT; /* top down */
|
||||||
|
biHeader->biPlanes = 1;
|
||||||
|
biHeader->biBitCount = 8; /* 256 colors */
|
||||||
|
biHeader->biCompression = BI_RGB; /* uncompressed */
|
||||||
|
|
||||||
|
ShowWindow(hWnd, SW_SHOW);
|
||||||
|
|
||||||
|
// int k = DrawDibProfileDisplay(biHeader);
|
||||||
|
// printf("%d\n", k&PD_CAN_STRETCHDIB);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WndMan::handleMessage() {
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (msg.message==WM_QUIT) {
|
||||||
|
terminated=true;
|
||||||
|
exit(1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long rdtsc_timer;
|
||||||
|
|
||||||
|
void _declspec(naked) beginpentiumtest() {
|
||||||
|
_asm {
|
||||||
|
rdtsc
|
||||||
|
mov rdtsc_timer,eax
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int _declspec(naked) endpentiumtest() {
|
||||||
|
_asm {
|
||||||
|
rdtsc
|
||||||
|
sub eax,rdtsc_timer
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
void decompressMask(byte *d, byte *s) {
|
||||||
|
int x,y;
|
||||||
|
byte bits = 0x80, bdata = *s++;
|
||||||
|
|
||||||
|
for (y=0; y<144; y++)
|
||||||
|
for (x=0; x<320; x++) {
|
||||||
|
*d++ = (bdata & bits) ? 128 : 0;
|
||||||
|
bits>>=1;
|
||||||
|
if (!bits) {
|
||||||
|
bdata = *s++;
|
||||||
|
bits=0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void outputdisplay2(Scumm *s, int disp) {
|
||||||
|
byte *old = wm->_vgabuf;
|
||||||
|
switch(disp) {
|
||||||
|
case 0:
|
||||||
|
wm->_vgabuf = s->getResourceAddress(0xA, 5);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
wm->_vgabuf = s->getResourceAddress(0xA, 1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
wm->_vgabuf = NULL;
|
||||||
|
decompressMask(wm->dib.buf, s->getResourceAddress(0xA, 9)+s->_screenStartStrip);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
wm->_vgabuf = NULL;
|
||||||
|
decompressMask(wm->dib.buf, s->getResourceAddress(0xA, 9)+5920+s->_screenStartStrip);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
wm->_vgabuf = NULL;
|
||||||
|
decompressMask(wm->dib.buf, s->getResourceAddress(0xA, 9)+5920*2+s->_screenStartStrip);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
wm->_vgabuf = NULL;
|
||||||
|
decompressMask(wm->dib.buf, s->getResourceAddress(0xA, 9)+5920*3+s->_screenStartStrip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wm->writeToScreen();
|
||||||
|
wm->_vgabuf = old;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void outputdisplay(Scumm *s) {
|
||||||
|
s->drawMouse();
|
||||||
|
wm->writeToScreen();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void blitToScreen(Scumm *s, byte *src,int x, int y, int w, int h) {
|
||||||
|
byte *dst;
|
||||||
|
SDL_Rect *r;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dst = (byte*)wm->_vgabuf + y*320 + x;
|
||||||
|
|
||||||
|
do {
|
||||||
|
memcpy(dst, src, w);
|
||||||
|
dst += 320;
|
||||||
|
src += 320;
|
||||||
|
} while (--h);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateScreen(Scumm *s) {
|
||||||
|
if (s->_palDirtyMax != -1) {
|
||||||
|
wm->setPalette(s->_currentPalette, 0, 256);
|
||||||
|
s->_palDirtyMax = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wm->writeToScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
void waitForTimer(Scumm *s) {
|
||||||
|
Sleep(10);
|
||||||
|
s->_scummTimer+=2;
|
||||||
|
wm->handleMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef main
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
scumm._videoMode = 0x13;
|
||||||
|
|
||||||
|
wm->init();
|
||||||
|
wm->_vgabuf = (byte*)calloc(320,200);
|
||||||
|
wm->_scumm = &scumm;
|
||||||
|
|
||||||
|
scumm.scummMain();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue