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