Split code into more specific files and cleanup
svn-id: r24394
This commit is contained in:
parent
e26954bcdb
commit
ff574a63ee
20 changed files with 3275 additions and 3120 deletions
File diff suppressed because it is too large
Load diff
|
@ -771,7 +771,7 @@ protected:
|
|||
|
||||
void loadZone(uint zoneNum);
|
||||
|
||||
void loadSprite(uint windowNum, uint vga_res, uint vga_sprite_id, uint x, uint y, uint palette);
|
||||
void animate(uint windowNum, uint zoneNum, uint vgaSpriteId, uint x, uint y, uint palette, bool setZone = true);
|
||||
void playSpeech(uint speech_id, uint vga_sprite_id);
|
||||
void skipSpeech();
|
||||
|
||||
|
|
743
engines/agos/gfx.cpp
Normal file
743
engines/agos/gfx.cpp
Normal file
|
@ -0,0 +1,743 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 Ludvig Strigeus
|
||||
* Copyright (C) 2001-2006 The ScummVM project
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stdafx.h"
|
||||
|
||||
#include "agos/agos.h"
|
||||
#include "agos/intern.h"
|
||||
#include "agos/vga.h"
|
||||
|
||||
namespace AGOS {
|
||||
|
||||
byte *vc10_depackColumn(VC10_state * vs) {
|
||||
int8 a = vs->depack_cont;
|
||||
const byte *src = vs->depack_src;
|
||||
byte *dst = vs->depack_dest;
|
||||
uint16 dh = vs->dh;
|
||||
byte color;
|
||||
|
||||
if (a == -0x80)
|
||||
a = *src++;
|
||||
|
||||
for (;;) {
|
||||
if (a >= 0) {
|
||||
color = *src++;
|
||||
do {
|
||||
*dst++ = color;
|
||||
if (!--dh) {
|
||||
if (--a < 0)
|
||||
a = -0x80;
|
||||
else
|
||||
src--;
|
||||
goto get_out;
|
||||
}
|
||||
} while (--a >= 0);
|
||||
} else {
|
||||
do {
|
||||
*dst++ = *src++;
|
||||
if (!--dh) {
|
||||
if (++a == 0)
|
||||
a = -0x80;
|
||||
goto get_out;
|
||||
}
|
||||
} while (++a != 0);
|
||||
}
|
||||
a = *src++;
|
||||
}
|
||||
|
||||
get_out:;
|
||||
vs->depack_src = src;
|
||||
vs->depack_cont = a;
|
||||
return vs->depack_dest + vs->y_skip;
|
||||
}
|
||||
|
||||
void vc10_skip_cols(VC10_state *vs) {
|
||||
while (vs->x_skip) {
|
||||
vc10_depackColumn(vs);
|
||||
vs->x_skip--;
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::decodeColumn(byte *dst, const byte *src, int height) {
|
||||
const uint pitch = _dxSurfacePitch;
|
||||
int8 reps = (int8)0x80;
|
||||
byte color;
|
||||
byte *dstPtr = dst;
|
||||
uint h = height, w = 8;
|
||||
|
||||
for (;;) {
|
||||
reps = *src++;
|
||||
if (reps >= 0) {
|
||||
color = *src++;
|
||||
|
||||
do {
|
||||
*dst = color;
|
||||
dst += pitch;
|
||||
|
||||
/* reached bottom? */
|
||||
if (--h == 0) {
|
||||
/* reached right edge? */
|
||||
if (--w == 0)
|
||||
return;
|
||||
dst = ++dstPtr;
|
||||
h = height;
|
||||
}
|
||||
} while (--reps >= 0);
|
||||
} else {
|
||||
|
||||
do {
|
||||
*dst = *src++;
|
||||
dst += pitch;
|
||||
|
||||
/* reached bottom? */
|
||||
if (--h == 0) {
|
||||
/* reached right edge? */
|
||||
if (--w == 0)
|
||||
return;
|
||||
dst = ++dstPtr;
|
||||
h = height;
|
||||
}
|
||||
} while (++reps != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::decodeRow(byte *dst, const byte *src, int width) {
|
||||
const uint pitch = _dxSurfacePitch;
|
||||
int8 reps = (int8)0x80;
|
||||
byte color;
|
||||
byte *dstPtr = dst;
|
||||
uint w = width, h = 8;
|
||||
|
||||
for (;;) {
|
||||
reps = *src++;
|
||||
if (reps >= 0) {
|
||||
color = *src++;
|
||||
|
||||
do {
|
||||
*dst++ = color;
|
||||
|
||||
/* reached right edge? */
|
||||
if (--w == 0) {
|
||||
/* reached bottom? */
|
||||
if (--h == 0)
|
||||
return;
|
||||
dstPtr += pitch;
|
||||
dst = dstPtr;
|
||||
w = width;
|
||||
}
|
||||
} while (--reps >= 0);
|
||||
} else {
|
||||
|
||||
do {
|
||||
*dst++ = *src++;
|
||||
|
||||
/* reached right edge? */
|
||||
if (--w == 0) {
|
||||
/* reached bottom? */
|
||||
if (--h == 0)
|
||||
return;
|
||||
dstPtr += pitch;
|
||||
dst = dstPtr;
|
||||
w = width;
|
||||
}
|
||||
} while (++reps != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AGOSEngine::drawImages_clip(VC10_state *state) {
|
||||
const uint16 *vlut;
|
||||
uint maxWidth, maxHeight;
|
||||
int cur;
|
||||
|
||||
vlut = &_videoWindows[_windowNum * 4];
|
||||
|
||||
if (getGameType() != GType_FF && getGameType() != GType_PP) {
|
||||
state->draw_width = state->width * 2;
|
||||
}
|
||||
|
||||
cur = state->x;
|
||||
if (cur < 0) {
|
||||
do {
|
||||
if (!--state->draw_width)
|
||||
return 0;
|
||||
state->x_skip++;
|
||||
} while (++cur);
|
||||
}
|
||||
state->x = cur;
|
||||
|
||||
maxWidth = (getGameType() == GType_FF || getGameType() == GType_PP) ? _screenWidth : (vlut[2] * 2);
|
||||
cur += state->draw_width - maxWidth;
|
||||
if (cur > 0) {
|
||||
do {
|
||||
if (!--state->draw_width)
|
||||
return 0;
|
||||
} while (--cur);
|
||||
}
|
||||
|
||||
cur = state->y;
|
||||
if (cur < 0) {
|
||||
do {
|
||||
if (!--state->draw_height)
|
||||
return 0;
|
||||
state->y_skip++;
|
||||
} while (++cur);
|
||||
}
|
||||
state->y = cur;
|
||||
|
||||
maxHeight = (getGameType() == GType_FF || getGameType() == GType_PP) ? _screenHeight : vlut[3];
|
||||
cur += state->draw_height - maxHeight;
|
||||
if (cur > 0) {
|
||||
do {
|
||||
if (!--state->draw_height)
|
||||
return 0;
|
||||
} while (--cur);
|
||||
}
|
||||
|
||||
assert(state->draw_width != 0 && state->draw_height != 0);
|
||||
|
||||
if (getGameType() != GType_FF && getGameType() != GType_PP) {
|
||||
state->draw_width *= 4;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void AGOSEngine::drawImages_Feeble(VC10_state *state) {
|
||||
if (state->flags & kDFCompressed) {
|
||||
if (state->flags & kDFScaled) {
|
||||
state->surf_addr = getScaleBuf();
|
||||
state->surf_pitch = _dxSurfacePitch;
|
||||
|
||||
uint w, h;
|
||||
byte *src, *dst, *dstPtr;
|
||||
|
||||
state->dl = state->width;
|
||||
state->dh = state->height;
|
||||
|
||||
dstPtr = state->surf_addr;
|
||||
w = 0;
|
||||
do {
|
||||
src = vc10_depackColumn(state);
|
||||
dst = dstPtr;
|
||||
|
||||
h = 0;
|
||||
do {
|
||||
*dst = *src;
|
||||
dst += _screenWidth;
|
||||
src++;
|
||||
} while (++h != state->draw_height);
|
||||
dstPtr++;
|
||||
} while (++w != state->draw_width);
|
||||
|
||||
if (_vgaCurSpritePriority % 10 != 9) {
|
||||
_scaleX = state->x;
|
||||
_scaleY = state->y;
|
||||
_scaleWidth = state->width;
|
||||
_scaleHeight = state->height;
|
||||
} else {
|
||||
scaleClip(state->height, state->width, state->y, state->x, state->y + _scrollY);
|
||||
}
|
||||
} else if (state->flags & kDFOverlayed) {
|
||||
state->surf_addr = getScaleBuf();
|
||||
state->surf_pitch = _dxSurfacePitch;
|
||||
state->surf_addr += (state->x + _scrollX) + (state->y + _scrollY) * state->surf_pitch;
|
||||
|
||||
uint w, h;
|
||||
byte *src, *dst, *dstPtr;
|
||||
|
||||
state->dl = state->width;
|
||||
state->dh = state->height;
|
||||
|
||||
dstPtr = state->surf_addr;
|
||||
w = 0;
|
||||
do {
|
||||
byte color;
|
||||
|
||||
src = vc10_depackColumn(state);
|
||||
dst = dstPtr;
|
||||
|
||||
h = 0;
|
||||
do {
|
||||
color = *src;
|
||||
if (color != 0)
|
||||
*dst = color;
|
||||
dst += _screenWidth;
|
||||
src++;
|
||||
} while (++h != state->draw_height);
|
||||
dstPtr++;
|
||||
} while (++w != state->draw_width);
|
||||
|
||||
if (_vgaCurSpritePriority % 10 == 9) {
|
||||
scaleClip(_scaleHeight, _scaleWidth, _scaleY, _scaleX, _scaleY + _scrollY);
|
||||
}
|
||||
} else {
|
||||
if (drawImages_clip(state) == 0)
|
||||
return;
|
||||
|
||||
state->surf_addr += state->x + state->y * state->surf_pitch;
|
||||
|
||||
uint w, h;
|
||||
byte *src, *dst, *dstPtr;
|
||||
|
||||
state->dl = state->width;
|
||||
state->dh = state->height;
|
||||
|
||||
vc10_skip_cols(state);
|
||||
|
||||
|
||||
if (state->flags & kDFMasked) {
|
||||
if (getGameType() == GType_FF && !getBitFlag(81)) {
|
||||
if (state->x > _feebleRect.right)
|
||||
return;
|
||||
if (state->y > _feebleRect.bottom)
|
||||
return;
|
||||
if (state->x + state->width < _feebleRect.left)
|
||||
return;
|
||||
if (state->y + state->height < _feebleRect.top)
|
||||
return;
|
||||
}
|
||||
|
||||
dstPtr = state->surf_addr;
|
||||
w = 0;
|
||||
do {
|
||||
byte color;
|
||||
|
||||
src = vc10_depackColumn(state);
|
||||
dst = dstPtr;
|
||||
|
||||
h = 0;
|
||||
do {
|
||||
color = *src;
|
||||
if (color)
|
||||
*dst = color;
|
||||
dst += _screenWidth;
|
||||
src++;
|
||||
} while (++h != state->draw_height);
|
||||
dstPtr++;
|
||||
} while (++w != state->draw_width);
|
||||
} else {
|
||||
dstPtr = state->surf_addr;
|
||||
w = 0;
|
||||
do {
|
||||
byte color;
|
||||
|
||||
src = vc10_depackColumn(state);
|
||||
dst = dstPtr;
|
||||
|
||||
h = 0;
|
||||
do {
|
||||
color = *src;
|
||||
if ((state->flags & kDFNonTrans) || color != 0)
|
||||
*dst = color;
|
||||
dst += _screenWidth;
|
||||
src++;
|
||||
} while (++h != state->draw_height);
|
||||
dstPtr++;
|
||||
} while (++w != state->draw_width);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (drawImages_clip(state) == 0)
|
||||
return;
|
||||
|
||||
state->surf_addr += state->x + state->y * state->surf_pitch;
|
||||
|
||||
const byte *src;
|
||||
byte *dst;
|
||||
uint count;
|
||||
|
||||
src = state->depack_src + state->width * state->y_skip;
|
||||
dst = state->surf_addr;
|
||||
do {
|
||||
for (count = 0; count != state->draw_width; count++) {
|
||||
byte color;
|
||||
color = src[count + state->x_skip];
|
||||
if (color) {
|
||||
if ((state->flags & kDFShaded) && color == 220)
|
||||
color = 244;
|
||||
|
||||
dst[count] = color;
|
||||
}
|
||||
}
|
||||
dst += _screenWidth;
|
||||
src += state->width;
|
||||
} while (--state->draw_height);
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::drawImages(VC10_state *state) {
|
||||
const uint16 *vlut = &_videoWindows[_windowNum * 4];
|
||||
|
||||
if (drawImages_clip(state) == 0)
|
||||
return;
|
||||
|
||||
uint xoffs, yoffs;
|
||||
if (getGameType() == GType_ELVIRA1) {
|
||||
//if (_windowNum != 2 && _windowNum != 3 && _windowNum != 6) {
|
||||
// xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8;
|
||||
// yoffs = (vlut[1] - _videoWindows[17] + state->y);
|
||||
//} else {
|
||||
xoffs = (vlut[0] * 2 + state->x) * 8;
|
||||
yoffs = vlut[1] + state->y;
|
||||
//}
|
||||
} else if (getGameType() == GType_ELVIRA2) {
|
||||
//if (_windowNum == 4 || _windowNum >= 10) {
|
||||
// xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8;
|
||||
// yoffs = (vlut[1] - _videoWindows[17] + state->y);
|
||||
//} else {
|
||||
xoffs = (vlut[0] * 2 + state->x) * 8;
|
||||
yoffs = vlut[1] + state->y;
|
||||
//}
|
||||
} else if (getGameType() == GType_WW) {
|
||||
//if (_windowNum == 4 || (_windowNum >= 10 && _windowNum < 28)) {
|
||||
// xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8;
|
||||
// yoffs = (vlut[1] - _videoWindows[17] + state->y);
|
||||
//} else {
|
||||
xoffs = (vlut[0] * 2 + state->x) * 8;
|
||||
yoffs = vlut[1] + state->y;
|
||||
//}
|
||||
} else if (getGameType() == GType_SIMON1 && (_subroutine == 2923 || _subroutine == 2926)) {
|
||||
// Allow one section of Simon the Sorcerer 1 introduction to be displayed
|
||||
// in lower half of screen
|
||||
xoffs = state->x * 8;
|
||||
yoffs = state->y;
|
||||
} else {
|
||||
xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8;
|
||||
yoffs = (vlut[1] - _videoWindows[17] + state->y);
|
||||
}
|
||||
|
||||
state->surf2_addr += xoffs + yoffs * state->surf_pitch;
|
||||
state->surf_addr += xoffs + yoffs * state->surf2_pitch;
|
||||
|
||||
if (state->flags & kDFMasked) {
|
||||
byte *mask, *src, *dst;
|
||||
byte h;
|
||||
uint w;
|
||||
|
||||
state->x_skip *= 4;
|
||||
state->dl = state->width;
|
||||
state->dh = state->height;
|
||||
|
||||
vc10_skip_cols(state);
|
||||
|
||||
w = 0;
|
||||
do {
|
||||
mask = vc10_depackColumn(state); /* esi */
|
||||
src = state->surf2_addr + w * 2; /* ebx */
|
||||
dst = state->surf_addr + w * 2; /* edi */
|
||||
|
||||
h = state->draw_height;
|
||||
if ((getGameType() == GType_SIMON1) && getBitFlag(88)) {
|
||||
/* transparency */
|
||||
do {
|
||||
if (mask[0] & 0xF0) {
|
||||
if ((dst[0] & 0x0F0) == 0x20)
|
||||
dst[0] = src[0];
|
||||
}
|
||||
if (mask[0] & 0x0F) {
|
||||
if ((dst[1] & 0x0F0) == 0x20)
|
||||
dst[1] = src[1];
|
||||
}
|
||||
mask++;
|
||||
dst += state->surf_pitch;
|
||||
src += state->surf2_pitch;
|
||||
} while (--h);
|
||||
} else {
|
||||
/* no transparency */
|
||||
do {
|
||||
if (mask[0] & 0xF0)
|
||||
dst[0] = src[0];
|
||||
if (mask[0] & 0x0F)
|
||||
dst[1] = src[1];
|
||||
mask++;
|
||||
dst += state->surf_pitch;
|
||||
src += state->surf2_pitch;
|
||||
} while (--h);
|
||||
}
|
||||
} while (++w != state->draw_width);
|
||||
} else if ((((_lockWord & 0x20) && state->palette == 0) || state->palette == 0xC0) &&
|
||||
(getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) &&
|
||||
getPlatform() != Common::kPlatformAmiga) {
|
||||
const byte *src;
|
||||
byte *dst;
|
||||
uint h, i;
|
||||
|
||||
if (state->flags & kDFCompressed) {
|
||||
byte *dstPtr = state->surf_addr;
|
||||
src = state->depack_src;
|
||||
/* AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD EEEEEEEE
|
||||
* aaaaabbb bbcccccd ddddeeee efffffgg ggghhhhh
|
||||
*/
|
||||
|
||||
do {
|
||||
uint count = state->draw_width / 4;
|
||||
|
||||
dst = dstPtr;
|
||||
do {
|
||||
uint32 bits = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | (src[3]);
|
||||
byte color;
|
||||
|
||||
color = (byte)((bits >> (32 - 5)) & 31);
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[0] = color;
|
||||
color = (byte)((bits >> (32 - 10)) & 31);
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[1] = color;
|
||||
color = (byte)((bits >> (32 - 15)) & 31);
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[2] = color;
|
||||
color = (byte)((bits >> (32 - 20)) & 31);
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[3] = color;
|
||||
color = (byte)((bits >> (32 - 25)) & 31);
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[4] = color;
|
||||
color = (byte)((bits >> (32 - 30)) & 31);
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[5] = color;
|
||||
|
||||
bits = (bits << 8) | src[4];
|
||||
|
||||
color = (byte)((bits >> (40 - 35)) & 31);
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[6] = color;
|
||||
color = (byte)((bits) & 31);
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[7] = color;
|
||||
|
||||
dst += 8;
|
||||
src += 5;
|
||||
} while (--count);
|
||||
dstPtr += _screenWidth;
|
||||
} while (--state->draw_height);
|
||||
} else {
|
||||
src = state->depack_src + (state->width * state->y_skip * 16) + (state->x_skip * 8);
|
||||
dst = state->surf_addr;
|
||||
|
||||
state->draw_width *= 2;
|
||||
|
||||
h = state->draw_height;
|
||||
do {
|
||||
for (i = 0; i != state->draw_width; i++)
|
||||
if ((state->flags & kDFNonTrans) || src[i])
|
||||
dst[i] = src[i];
|
||||
dst += _screenWidth;
|
||||
src += state->width * 16;
|
||||
} while (--h);
|
||||
}
|
||||
} else {
|
||||
if (getGameType() == GType_SIMON2 && state->flags & kDFUseFrontBuf && getBitFlag(171)) {
|
||||
state->surf_addr = state->surf2_addr;
|
||||
state->surf_pitch = state->surf2_pitch;
|
||||
}
|
||||
|
||||
if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW)
|
||||
state->palette = state->surf_addr[0] & 0xF0;
|
||||
|
||||
if (state->flags & kDFCompressed) {
|
||||
uint w, h;
|
||||
byte *src, *dst, *dstPtr;
|
||||
|
||||
state->x_skip *= 4; /* reached */
|
||||
|
||||
state->dl = state->width;
|
||||
state->dh = state->height;
|
||||
|
||||
vc10_skip_cols(state);
|
||||
|
||||
dstPtr = state->surf_addr;
|
||||
if (!(state->flags & kDFNonTrans) && (state->flags & 0x40)) { /* reached */
|
||||
dstPtr += vcReadVar(252);
|
||||
}
|
||||
w = 0;
|
||||
do {
|
||||
byte color;
|
||||
|
||||
src = vc10_depackColumn(state);
|
||||
dst = dstPtr;
|
||||
|
||||
h = 0;
|
||||
do {
|
||||
color = (*src / 16);
|
||||
if ((state->flags & kDFNonTrans) || color != 0)
|
||||
dst[0] = color | state->palette;
|
||||
color = (*src & 15);
|
||||
if ((state->flags & kDFNonTrans) || color != 0)
|
||||
dst[1] = color | state->palette;
|
||||
dst += _screenWidth;
|
||||
src++;
|
||||
} while (++h != state->draw_height);
|
||||
dstPtr += 2;
|
||||
} while (++w != state->draw_width);
|
||||
} else {
|
||||
const byte *src;
|
||||
byte *dst;
|
||||
uint count;
|
||||
|
||||
src = state->depack_src + (state->width * state->y_skip) * 8;
|
||||
dst = state->surf_addr;
|
||||
state->x_skip *= 4;
|
||||
|
||||
do {
|
||||
for (count = 0; count != state->draw_width; count++) {
|
||||
byte color;
|
||||
color = (src[count + state->x_skip] / 16);
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[count * 2] = color | state->palette;
|
||||
color = (src[count + state->x_skip] & 15);
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[count * 2 + 1] = color | state->palette;
|
||||
}
|
||||
dst += _screenWidth;
|
||||
src += state->width * 8;
|
||||
} while (--state->draw_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::horizontalScroll(VC10_state *state) {
|
||||
const byte *src;
|
||||
byte *dst;
|
||||
int w;
|
||||
|
||||
if (getGameType() == GType_FF)
|
||||
_scrollXMax = state->width - 640;
|
||||
else
|
||||
_scrollXMax = state->width * 2 - 40;
|
||||
_scrollYMax = 0;
|
||||
_scrollImage = state->depack_src;
|
||||
_scrollHeight = state->height;
|
||||
if (_variableArrayPtr[34] < 0)
|
||||
state->x = _variableArrayPtr[251];
|
||||
|
||||
_scrollX = state->x;
|
||||
|
||||
vcWriteVar(251, _scrollX);
|
||||
|
||||
dst = getBackBuf();
|
||||
|
||||
if (getGameType() == GType_FF)
|
||||
src = state->depack_src + _scrollX / 2;
|
||||
else
|
||||
src = state->depack_src + _scrollX * 4;
|
||||
|
||||
for (w = 0; w < _screenWidth; w += 8) {
|
||||
decodeColumn(dst, src + readUint32Wrapper(src), state->height);
|
||||
dst += 8;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::verticalScroll(VC10_state *state) {
|
||||
const byte *src;
|
||||
byte *dst;
|
||||
int h;
|
||||
|
||||
_scrollXMax = 0;
|
||||
_scrollYMax = state->height - 480;
|
||||
_scrollImage = state->depack_src;
|
||||
_scrollWidth = state->width;
|
||||
if (_variableArrayPtr[34] < 0)
|
||||
state->y = _variableArrayPtr[250];
|
||||
|
||||
_scrollY = state->y;
|
||||
|
||||
vcWriteVar(250, _scrollY);
|
||||
|
||||
dst = getBackBuf();
|
||||
src = state->depack_src + _scrollY / 2;
|
||||
|
||||
for (h = 0; h < _screenHeight; h += 8) {
|
||||
decodeRow(dst, src + READ_LE_UINT32(src), state->width);
|
||||
dst += 8 * state->width;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::scaleClip(int16 h, int16 w, int16 y, int16 x, int16 scrollY) {
|
||||
Common::Rect srcRect, dstRect;
|
||||
float factor, xscale;
|
||||
|
||||
srcRect.left = 0;
|
||||
srcRect.top = 0;
|
||||
srcRect.right = w;
|
||||
srcRect.bottom = h;
|
||||
|
||||
if (scrollY > _baseY)
|
||||
factor = 1 + ((scrollY - _baseY) * _scale);
|
||||
else
|
||||
factor = 1 - ((_baseY - scrollY) * _scale);
|
||||
|
||||
xscale = ((w * factor) / 2);
|
||||
|
||||
dstRect.left = (int16)(x - xscale);
|
||||
if (dstRect.left > _screenWidth - 1)
|
||||
return;
|
||||
dstRect.top = (int16)(y - (h * factor));
|
||||
if (dstRect.top > _screenHeight - 1)
|
||||
return;
|
||||
|
||||
dstRect.right = (int16)(x + xscale);
|
||||
dstRect.bottom = y;
|
||||
|
||||
_feebleRect = dstRect;
|
||||
|
||||
_variableArray[20] = _feebleRect.top;
|
||||
_variableArray[21] = _feebleRect.left;
|
||||
_variableArray[22] = _feebleRect.bottom;
|
||||
_variableArray[23] = _feebleRect.right;
|
||||
|
||||
debug(5, "Left %d Right %d Top %d Bottom %d", dstRect.left, dstRect.right, dstRect.top, dstRect.bottom);
|
||||
|
||||
// Unlike normal rectangles in ScummVM, it seems that in the case of
|
||||
// the destination rectangle the bottom and right coordinates are
|
||||
// considered to be inside the rectangle. For the source rectangle,
|
||||
// I believe that they are not.
|
||||
|
||||
int scaledW = dstRect.width() + 1;
|
||||
int scaledH = dstRect.height() + 1;
|
||||
|
||||
byte *src = getScaleBuf();
|
||||
byte *dst = getBackBuf();
|
||||
|
||||
dst += _dxSurfacePitch * dstRect.top + dstRect.left;
|
||||
|
||||
for (int dstY = 0; dstY < scaledH; dstY++) {
|
||||
if (dstRect.top + dstY >= 0 && dstRect.top + dstY < _screenHeight) {
|
||||
int srcY = (dstY * h) / scaledH;
|
||||
byte *srcPtr = src + _dxSurfacePitch * srcY;
|
||||
byte *dstPtr = dst + _dxSurfacePitch * dstY;
|
||||
for (int dstX = 0; dstX < scaledW; dstX++) {
|
||||
if (dstRect.left + dstX >= 0 && dstRect.left + dstX < _screenWidth) {
|
||||
int srcX = (dstX * w) / scaledW;
|
||||
if (srcPtr[srcX])
|
||||
dstPtr[dstX] = srcPtr[srcX];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace AGOS
|
|
@ -557,7 +557,7 @@ void AGOSEngine::defineArrowBoxes(WindowBlock *window) {
|
|||
ha->verb = 1;
|
||||
|
||||
stopAnimateSimon1(128);
|
||||
loadSprite(0, 1, 128, 0, 0, 14);
|
||||
animate(0, 1, 128, 0, 0, 14);
|
||||
} else if (getGameType() == GType_WW) {
|
||||
ha->x = 255;
|
||||
ha->y = 170;
|
||||
|
|
518
engines/agos/input.cpp
Normal file
518
engines/agos/input.cpp
Normal file
|
@ -0,0 +1,518 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 Ludvig Strigeus
|
||||
* Copyright (C) 2001-2006 The ScummVM project
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stdafx.h"
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
#include "agos/intern.h"
|
||||
#include "agos/agos.h"
|
||||
#include "agos/vga.h"
|
||||
|
||||
namespace AGOS {
|
||||
|
||||
void AGOSEngine::setup_cond_c_helper() {
|
||||
HitArea *last;
|
||||
uint id;
|
||||
|
||||
_noRightClick = 1;
|
||||
|
||||
if (getGameType() == GType_WW)
|
||||
clearMenuStrip();
|
||||
|
||||
if (getGameType() == GType_FF) {
|
||||
int cursor = 5;
|
||||
int animMax = 16;
|
||||
|
||||
if (getBitFlag(200)) {
|
||||
cursor = 11;
|
||||
animMax = 5;
|
||||
} else if (getBitFlag(201)) {
|
||||
cursor = 12;
|
||||
animMax = 5;
|
||||
} else if (getBitFlag(202)) {
|
||||
cursor = 13;
|
||||
animMax = 5;
|
||||
} else if (getBitFlag(203)) {
|
||||
cursor = 14;
|
||||
animMax = 9;
|
||||
} else if (getBitFlag(205)) {
|
||||
cursor = 17;
|
||||
animMax = 11;
|
||||
} else if (getBitFlag(206)) {
|
||||
cursor = 16;
|
||||
animMax = 2;
|
||||
} else if (getBitFlag(208)) {
|
||||
cursor = 26;
|
||||
animMax = 2;
|
||||
} else if (getBitFlag(209)) {
|
||||
cursor = 27;
|
||||
animMax = 9;
|
||||
} else if (getBitFlag(210)) {
|
||||
cursor = 28;
|
||||
animMax = 9;
|
||||
}
|
||||
|
||||
_animatePointer = 0;
|
||||
_mouseCursor = cursor;
|
||||
_mouseAnimMax = animMax;
|
||||
_mouseAnim = 1;
|
||||
_needHitAreaRecalc++;
|
||||
}
|
||||
|
||||
if (getGameType() == GType_SIMON2) {
|
||||
_mouseCursor = 0;
|
||||
if (_defaultVerb != 999) {
|
||||
_mouseCursor = 9;
|
||||
_needHitAreaRecalc++;
|
||||
_defaultVerb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_lastHitArea = 0;
|
||||
_hitAreaObjectItem = NULL;
|
||||
_nameLocked = 0;
|
||||
|
||||
last = _lastNameOn;
|
||||
clearName();
|
||||
_lastNameOn = last;
|
||||
|
||||
for (;;) {
|
||||
_lastHitArea = NULL;
|
||||
_lastHitArea3 = 0;
|
||||
_leftButtonDown = 0;
|
||||
|
||||
do {
|
||||
if (_exitCutscene && getBitFlag(9)) {
|
||||
endCutscene();
|
||||
goto out_of_here;
|
||||
}
|
||||
|
||||
if (getGameType() == GType_FF) {
|
||||
if (_variableArray[254] == 63) {
|
||||
hitarea_stuff_helper_2();
|
||||
} else if (_variableArray[254] == 75) {
|
||||
hitarea_stuff_helper_2();
|
||||
_variableArray[60] = 9999;
|
||||
goto out_of_here;
|
||||
}
|
||||
}
|
||||
|
||||
delay(100);
|
||||
} while (_lastHitArea3 == (HitArea *) -1 || _lastHitArea3 == 0);
|
||||
|
||||
if (_lastHitArea == NULL) {
|
||||
} else if (_lastHitArea->id == 0x7FFB) {
|
||||
inventoryUp(_lastHitArea->window);
|
||||
} else if (_lastHitArea->id == 0x7FFC) {
|
||||
inventoryDown(_lastHitArea->window);
|
||||
} else if (_lastHitArea->item_ptr != NULL) {
|
||||
_hitAreaObjectItem = _lastHitArea->item_ptr;
|
||||
id = 0xFFFF;
|
||||
if (_lastHitArea->flags & kBFTextBox) {
|
||||
if (getGameType() == GType_PP)
|
||||
id = _lastHitArea->id;
|
||||
else if (getGameType() == GType_FF && (_lastHitArea->flags & kBFHyperBox))
|
||||
id = _lastHitArea->data;
|
||||
else
|
||||
id = _lastHitArea->flags / 256;
|
||||
}
|
||||
if (getGameType() == GType_PP)
|
||||
_variableArray[199] = id;
|
||||
else if (getGameType() == GType_WW)
|
||||
_variableArray[10] = id;
|
||||
else
|
||||
_variableArray[60] = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out_of_here:
|
||||
_lastHitArea3 = 0;
|
||||
_lastHitArea = 0;
|
||||
_lastNameOn = NULL;
|
||||
_mouseCursor = 0;
|
||||
_noRightClick = 0;
|
||||
}
|
||||
|
||||
void AGOSEngine::waitForInput() {
|
||||
HitArea *ha;
|
||||
uint id;
|
||||
|
||||
_leftButtonDown = 0;
|
||||
_lastHitArea = 0;
|
||||
_verbHitArea = 0;
|
||||
_hitAreaSubjectItem = NULL;
|
||||
_hitAreaObjectItem = NULL;
|
||||
_nameLocked = 0;
|
||||
|
||||
if (getGameType() == GType_WW) {
|
||||
_mouseCursor = 0;
|
||||
_needHitAreaRecalc++;
|
||||
clearMenuStrip();
|
||||
} else {
|
||||
resetVerbs();
|
||||
}
|
||||
|
||||
startOver:
|
||||
for (;;) {
|
||||
_lastHitArea = NULL;
|
||||
_lastHitArea3 = NULL;
|
||||
|
||||
for (;;) {
|
||||
if (getGameType() != GType_FF && getGameType() != GType_PP && _keyPressed == 35)
|
||||
displayBoxStars();
|
||||
if (processSpecialKeys() != 0) {
|
||||
goto out_of_here;
|
||||
}
|
||||
if (_lastHitArea3 == (HitArea *) -1)
|
||||
goto startOver;
|
||||
if (_lastHitArea3 != 0)
|
||||
break;
|
||||
hitarea_stuff_helper();
|
||||
delay(100);
|
||||
}
|
||||
|
||||
ha = _lastHitArea;
|
||||
|
||||
if (ha == NULL) {
|
||||
} else if (ha->id == 0x7FFB) {
|
||||
inventoryUp(ha->window);
|
||||
} else if (ha->id == 0x7FFC) {
|
||||
inventoryDown(ha->window);
|
||||
} else if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) &&
|
||||
(ha->id >= 101 && ha->id < 113)) {
|
||||
_verbHitArea = ha->verb;
|
||||
setVerb(ha);
|
||||
_defaultVerb = 0;
|
||||
} else {
|
||||
if (getGameType() == GType_WW) {
|
||||
if (_mouseCursor == 3)
|
||||
_verbHitArea = 236;
|
||||
|
||||
if (ha->id == 98) {
|
||||
animate(2, 0, 110, 0, 0, 0);
|
||||
waitForSync(34);
|
||||
} else if (ha->id == 108) {
|
||||
animate(2, 0, 106, 0, 0, 0);
|
||||
waitForSync(34);
|
||||
} else if (ha->id == 109) {
|
||||
animate(2, 0, 107, 0, 0, 0);
|
||||
waitForSync(34);
|
||||
} else if (ha->id == 115) {
|
||||
animate(2, 0, 109, 0, 0, 0);
|
||||
waitForSync(34);
|
||||
} else if (ha->id == 116) {
|
||||
animate(2, 0, 113, 0, 0, 0);
|
||||
waitForSync(34);
|
||||
} else if (ha->id == 117) {
|
||||
animate(2, 0, 112, 0, 0, 0);
|
||||
waitForSync(34);
|
||||
} else if (ha->id == 118) {
|
||||
animate(2, 0, 108, 0, 0, 0);
|
||||
waitForSync(34);
|
||||
} else if (ha->id == 119) {
|
||||
animate(2, 0, 111, 0, 0, 0);
|
||||
waitForSync(34);
|
||||
}
|
||||
}
|
||||
if ((_verbHitArea != 0 || _hitAreaSubjectItem != ha->item_ptr && ha->flags & kBFBoxItem) &&
|
||||
ha->item_ptr) {
|
||||
if_1:;
|
||||
_hitAreaSubjectItem = ha->item_ptr;
|
||||
id = 0xFFFF;
|
||||
if (ha->flags & kBFTextBox) {
|
||||
if (getGameType() == GType_PP)
|
||||
id = _lastHitArea->id;
|
||||
else if (getGameType() == GType_FF && (ha->flags & kBFHyperBox))
|
||||
id = ha->data;
|
||||
else
|
||||
id = ha->flags / 256;
|
||||
}
|
||||
if (getGameType() == GType_PP)
|
||||
_variableArray[199] = id;
|
||||
else if (getGameType() == GType_WW)
|
||||
_variableArray[10] = id;
|
||||
else
|
||||
_variableArray[60] = id;
|
||||
|
||||
_nameLocked = 2;
|
||||
displayName(ha);
|
||||
_nameLocked = 1;
|
||||
|
||||
if (_verbHitArea != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (getGameType() == GType_ELVIRA2)
|
||||
doMenuStrip(menuFor_e2(ha->item_ptr, id));
|
||||
else if (getGameType() == GType_WW)
|
||||
doMenuStrip(menuFor_ww(ha->item_ptr, id));
|
||||
} else {
|
||||
// else 1
|
||||
if (ha->verb == 0) {
|
||||
if (ha->item_ptr)
|
||||
goto if_1;
|
||||
} else {
|
||||
if (getGameType() == GType_WW && _mouseCursor != 0 && _mouseCursor < 4) {
|
||||
_hitAreaSubjectItem = ha->item_ptr;
|
||||
break;
|
||||
}
|
||||
|
||||
_verbHitArea = ha->verb & 0xBFFF;
|
||||
if (ha->verb & 0x4000) {
|
||||
_hitAreaSubjectItem = ha->item_ptr;
|
||||
break;
|
||||
}
|
||||
if (_hitAreaSubjectItem != NULL)
|
||||
break;
|
||||
|
||||
if (getGameType() == GType_WW) {
|
||||
if (ha->id == 109) {
|
||||
_mouseCursor = 2;
|
||||
_needHitAreaRecalc++;
|
||||
} else if (ha->id == 117) {
|
||||
_mouseCursor = 3;
|
||||
_needHitAreaRecalc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out_of_here:
|
||||
if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW)
|
||||
clearMenuStrip();
|
||||
|
||||
_nameLocked = 0;
|
||||
_needHitAreaRecalc++;
|
||||
}
|
||||
|
||||
void AGOSEngine::hitarea_stuff_helper() {
|
||||
time_t cur_time;
|
||||
|
||||
if (getGameType() == GType_SIMON2 || getGameType() == GType_FF ||
|
||||
getGameType() == GType_PP) {
|
||||
if (_variableArray[254] || _variableArray[249]) {
|
||||
hitarea_stuff_helper_2();
|
||||
}
|
||||
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW ||
|
||||
getGameType() == GType_SIMON1) {
|
||||
uint subr_id = (uint16)_variableArray[254];
|
||||
if (subr_id != 0) {
|
||||
Subroutine *sub = getSubroutineByID(subr_id);
|
||||
if (sub != NULL) {
|
||||
startSubroutineEx(sub);
|
||||
permitInput();
|
||||
}
|
||||
_variableArray[254] = 0;
|
||||
_runScriptReturn1 = false;
|
||||
}
|
||||
}
|
||||
|
||||
time(&cur_time);
|
||||
if ((uint) cur_time != _lastTime) {
|
||||
_lastTime = cur_time;
|
||||
if (kickoffTimeEvents())
|
||||
permitInput();
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::hitarea_stuff_helper_2() {
|
||||
uint subr_id;
|
||||
Subroutine *sub;
|
||||
|
||||
subr_id = (uint16)_variableArray[249];
|
||||
if (subr_id != 0) {
|
||||
sub = getSubroutineByID(subr_id);
|
||||
if (sub != NULL) {
|
||||
_variableArray[249] = 0;
|
||||
startSubroutineEx(sub);
|
||||
permitInput();
|
||||
}
|
||||
_variableArray[249] = 0;
|
||||
}
|
||||
|
||||
subr_id = (uint16)_variableArray[254];
|
||||
if (subr_id != 0) {
|
||||
sub = getSubroutineByID(subr_id);
|
||||
if (sub != NULL) {
|
||||
_variableArray[254] = 0;
|
||||
startSubroutineEx(sub);
|
||||
permitInput();
|
||||
}
|
||||
_variableArray[254] = 0;
|
||||
}
|
||||
|
||||
_runScriptReturn1 = false;
|
||||
}
|
||||
|
||||
void AGOSEngine::permitInput() {
|
||||
if (!_mortalFlag) {
|
||||
_mortalFlag = true;
|
||||
showmessage_print_char(0);
|
||||
_curWindow = 0;
|
||||
if (_windowArray[0] != 0) {
|
||||
_textWindow = _windowArray[0];
|
||||
if (getGameType() == GType_FF || getGameType() == GType_PP)
|
||||
showmessage_helper_3(_textWindow->textColumn, _textWindow->width);
|
||||
else
|
||||
showmessage_helper_3(_textWindow->textLength, _textWindow->textMaxLength);
|
||||
}
|
||||
_mortalFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool AGOSEngine::processSpecialKeys() {
|
||||
switch (_keyPressed) {
|
||||
case 17: // Up
|
||||
if (getGameType() == GType_PP)
|
||||
_verbHitArea = 302;
|
||||
else if (getGameType() == GType_WW)
|
||||
_verbHitArea = 239;
|
||||
break;
|
||||
case 18: // Down
|
||||
if (getGameType() == GType_PP)
|
||||
_verbHitArea = 304;
|
||||
else if (getGameType() == GType_WW)
|
||||
_verbHitArea = 241;
|
||||
break;
|
||||
case 19: // Right
|
||||
if (getGameType() == GType_PP)
|
||||
_verbHitArea = 303;
|
||||
else if (getGameType() == GType_WW)
|
||||
_verbHitArea = 240;
|
||||
break;
|
||||
case 20: // Left
|
||||
if (getGameType() == GType_PP)
|
||||
_verbHitArea = 301;
|
||||
else if (getGameType() == GType_WW)
|
||||
_verbHitArea = 242;
|
||||
break;
|
||||
case 27: // escape
|
||||
_exitCutscene = true;
|
||||
break;
|
||||
case 59: // F1
|
||||
if (getGameType() == GType_SIMON1) {
|
||||
vcWriteVar(5, 40);
|
||||
} else {
|
||||
vcWriteVar(5, 50);
|
||||
}
|
||||
vcWriteVar(86, 0);
|
||||
break;
|
||||
case 60: // F2
|
||||
if (getGameType() == GType_SIMON1) {
|
||||
vcWriteVar(5, 60);
|
||||
} else {
|
||||
vcWriteVar(5, 75);
|
||||
}
|
||||
vcWriteVar(86, 1);
|
||||
break;
|
||||
case 61: // F3
|
||||
if (getGameType() == GType_SIMON1) {
|
||||
vcWriteVar(5, 100);
|
||||
} else {
|
||||
vcWriteVar(5, 125);
|
||||
}
|
||||
vcWriteVar(86, 2);
|
||||
break;
|
||||
case 63: // F5
|
||||
if (getGameType() == GType_SIMON2 || getGameType() == GType_FF)
|
||||
_exitCutscene = true;
|
||||
break;
|
||||
case 65: // F7
|
||||
if (getGameType() == GType_FF && getBitFlag(76))
|
||||
_variableArray[254] = 70;
|
||||
break;
|
||||
case 67: // F9
|
||||
if (getGameType() == GType_FF)
|
||||
setBitFlag(73, !getBitFlag(73));
|
||||
break;
|
||||
case 'p':
|
||||
pause();
|
||||
break;
|
||||
case 't':
|
||||
if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE)) ||
|
||||
((getFeatures() & GF_TALKIE) && _language != Common::EN_ANY && _language != Common::DE_DEU)) {
|
||||
if (_speech)
|
||||
_subtitles ^= 1;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE))) {
|
||||
if (_subtitles)
|
||||
_speech ^= 1;
|
||||
}
|
||||
case '+':
|
||||
midi.set_volume(midi.get_volume() + 16);
|
||||
break;
|
||||
case '-':
|
||||
midi.set_volume(midi.get_volume() - 16);
|
||||
break;
|
||||
case 'm':
|
||||
midi.pause(_musicPaused ^= 1);
|
||||
break;
|
||||
case 's':
|
||||
if (getGameId() == GID_SIMON1DOS)
|
||||
midi._enable_sfx ^= 1;
|
||||
else
|
||||
_sound->effectsPause(_effectsPaused ^= 1);
|
||||
break;
|
||||
case 'b':
|
||||
_sound->ambientPause(_ambientPaused ^= 1);
|
||||
break;
|
||||
case 'r':
|
||||
if (_debugMode)
|
||||
_startMainScript ^= 1;
|
||||
break;
|
||||
case 'o':
|
||||
if (_debugMode)
|
||||
_continousMainScript ^= 1;
|
||||
break;
|
||||
case 'a':
|
||||
if (_debugMode)
|
||||
_startVgaScript ^= 1;
|
||||
break;
|
||||
case 'g':
|
||||
if (_debugMode)
|
||||
_continousVgaScript ^= 1;
|
||||
break;
|
||||
case 'i':
|
||||
if (_debugMode)
|
||||
_drawImagesDebug ^= 1;
|
||||
break;
|
||||
case 'd':
|
||||
if (_debugMode)
|
||||
_dumpImages ^=1;
|
||||
break;
|
||||
}
|
||||
|
||||
bool result = (_keyPressed != 0);
|
||||
_keyPressed = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // End of namespace AGOS
|
||||
|
||||
|
418
engines/agos/items.cpp
Normal file
418
engines/agos/items.cpp
Normal file
|
@ -0,0 +1,418 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 Ludvig Strigeus
|
||||
* Copyright (C) 2001-2006 The ScummVM project
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stdafx.h"
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
#include "agos/intern.h"
|
||||
#include "agos/agos.h"
|
||||
#include "agos/vga.h"
|
||||
|
||||
namespace AGOS {
|
||||
|
||||
Child *AGOSEngine::allocateChildBlock(Item *i, uint type, uint size) {
|
||||
Child *child = (Child *)allocateItem(size);
|
||||
child->next = i->children;
|
||||
i->children = child;
|
||||
child->type = type;
|
||||
return child;
|
||||
}
|
||||
|
||||
byte *AGOSEngine::allocateItem(uint size) {
|
||||
byte *org = _itemHeapPtr;
|
||||
size = (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
|
||||
|
||||
_itemHeapPtr += size;
|
||||
_itemHeapCurPos += size;
|
||||
|
||||
if (_itemHeapCurPos > _itemHeapSize)
|
||||
error("allocateItem: Itemheap overflow");
|
||||
|
||||
return org;
|
||||
}
|
||||
|
||||
void AGOSEngine::allocItemHeap() {
|
||||
_itemHeapSize = _itemMemSize;
|
||||
_itemHeapCurPos = 0;
|
||||
_itemHeapPtr = (byte *)calloc(_itemMemSize, 1);
|
||||
if (!_itemHeapPtr)
|
||||
error("Out Of Memory - Items");
|
||||
}
|
||||
|
||||
uint AGOSEngine::itemGetIconNumber(Item *item) {
|
||||
if (getGameType() == GType_ELVIRA1) {
|
||||
return getUserFlag(item, 7);
|
||||
} else {
|
||||
SubObject *child = (SubObject *)findChildOfType(item, 2);
|
||||
uint offs;
|
||||
|
||||
if (child == NULL || !(child->objectFlags & kOFIcon))
|
||||
return 0;
|
||||
|
||||
offs = getOffsetOfChild2Param(child, 0x10);
|
||||
return child->objectFlagValue[offs];
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::setItemState(Item *item, int value) {
|
||||
item->state = value;
|
||||
}
|
||||
|
||||
void AGOSEngine::createPlayer() {
|
||||
SubPlayer *p;
|
||||
|
||||
_currentPlayer = _itemArrayPtr[1];
|
||||
_currentPlayer->adjective = -1;
|
||||
_currentPlayer->noun = 10000;
|
||||
|
||||
p = (SubPlayer *)allocateChildBlock(_currentPlayer, 3, sizeof(SubPlayer));
|
||||
if (p == NULL)
|
||||
error("createPlayer: player create failure");
|
||||
|
||||
p->size = 0;
|
||||
p->weight = 0;
|
||||
p->strength = 6000;
|
||||
//p->flag = xxx;
|
||||
p->level = 1;
|
||||
p->score = 0;
|
||||
|
||||
setUserFlag(_currentPlayer, 0, 0);
|
||||
}
|
||||
|
||||
Child *AGOSEngine::findChildOfType(Item *i, uint type) {
|
||||
Child *child = i->children;
|
||||
for (; child; child = child->next)
|
||||
if (child->type == type)
|
||||
return child;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int AGOSEngine::getUserFlag(Item *item, int a) {
|
||||
SubUserFlag *subUserFlag;
|
||||
|
||||
subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
|
||||
if (subUserFlag == NULL)
|
||||
return 0;
|
||||
|
||||
if (a < 0 || a > 7)
|
||||
return 0;
|
||||
|
||||
return subUserFlag->userFlags[a];
|
||||
}
|
||||
|
||||
void AGOSEngine::setUserFlag(Item *item, int a, int b) {
|
||||
SubUserFlag *subUserFlag;
|
||||
|
||||
subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
|
||||
if (subUserFlag == NULL) {
|
||||
subUserFlag = (SubUserFlag *) allocateChildBlock(item, 9, sizeof(SubUserFlag));
|
||||
}
|
||||
|
||||
if (a < 0 || a > 7)
|
||||
return;
|
||||
|
||||
subUserFlag->userFlags[a] = b;
|
||||
}
|
||||
|
||||
int AGOSEngine::getUserItem(Item *item, int n) {
|
||||
SubUserFlag *subUserFlag;
|
||||
|
||||
subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
|
||||
if (subUserFlag == NULL)
|
||||
return 0;
|
||||
|
||||
if (n < 0 || n > 0)
|
||||
return 0;
|
||||
|
||||
return subUserFlag->userItems[n];
|
||||
}
|
||||
|
||||
void AGOSEngine::setUserItem(Item *item, int n, int m) {
|
||||
SubUserFlag *subUserFlag;
|
||||
|
||||
subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
|
||||
if (subUserFlag == NULL) {
|
||||
subUserFlag = (SubUserFlag *) allocateChildBlock(item, 9, sizeof(SubUserFlag));
|
||||
}
|
||||
|
||||
if (n == 0)
|
||||
subUserFlag->userItems[n] = m;
|
||||
}
|
||||
|
||||
bool AGOSEngine::isRoom(Item *item) {
|
||||
return findChildOfType(item, 1) != NULL;
|
||||
}
|
||||
|
||||
bool AGOSEngine::isObject(Item *item) {
|
||||
return findChildOfType(item, 2) != NULL;
|
||||
}
|
||||
|
||||
bool AGOSEngine::isPlayer(Item *item) {
|
||||
return findChildOfType(item, 3) != NULL;
|
||||
}
|
||||
|
||||
uint AGOSEngine::getOffsetOfChild2Param(SubObject *child, uint prop) {
|
||||
uint m = 1;
|
||||
uint offset = 0;
|
||||
while (m != prop) {
|
||||
if (child->objectFlags & m)
|
||||
offset++;
|
||||
m *= 2;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
Item *AGOSEngine::me() {
|
||||
if (_currentPlayer)
|
||||
return _currentPlayer;
|
||||
return _dummyItem1;
|
||||
}
|
||||
|
||||
Item *AGOSEngine::actor() {
|
||||
error("actor: is this code ever used?");
|
||||
//if (_actorPlayer)
|
||||
// return _actorPlayer;
|
||||
return _dummyItem1;
|
||||
}
|
||||
|
||||
Item *AGOSEngine::getNextItemPtr() {
|
||||
int a = getNextWord();
|
||||
switch (a) {
|
||||
case -1:
|
||||
return _subjectItem;
|
||||
case -3:
|
||||
return _objectItem;
|
||||
case -5:
|
||||
return me();
|
||||
case -7:
|
||||
return actor();
|
||||
case -9:
|
||||
return derefItem(me()->parent);
|
||||
default:
|
||||
return derefItem(a);
|
||||
}
|
||||
}
|
||||
|
||||
Item *AGOSEngine::getNextItemPtrStrange() {
|
||||
int a = getNextWord();
|
||||
switch (a) {
|
||||
case -1:
|
||||
return _subjectItem;
|
||||
case -3:
|
||||
return _objectItem;
|
||||
case -5:
|
||||
return _dummyItem2;
|
||||
case -7:
|
||||
return NULL;
|
||||
case -9:
|
||||
return _dummyItem3;
|
||||
default:
|
||||
return derefItem(a);
|
||||
}
|
||||
}
|
||||
|
||||
uint AGOSEngine::getNextItemID() {
|
||||
int a = getNextWord();
|
||||
switch (a) {
|
||||
case -1:
|
||||
return itemPtrToID(_subjectItem);
|
||||
case -3:
|
||||
return itemPtrToID(_objectItem);
|
||||
case -5:
|
||||
return getItem1ID();
|
||||
case -7:
|
||||
return 0;
|
||||
case -9:
|
||||
return me()->parent;
|
||||
default:
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::setItemParent(Item *item, Item *parent) {
|
||||
Item *old_parent = derefItem(item->parent);
|
||||
|
||||
if (item == parent)
|
||||
error("setItemParent: Trying to set item as its own parent");
|
||||
|
||||
// unlink it if it has a parent
|
||||
if (old_parent)
|
||||
unlinkItem(item);
|
||||
itemChildrenChanged(old_parent);
|
||||
linkItem(item, parent);
|
||||
itemChildrenChanged(parent);
|
||||
}
|
||||
|
||||
void AGOSEngine::itemChildrenChanged(Item *item) {
|
||||
int i;
|
||||
WindowBlock *window;
|
||||
|
||||
if (_noParentNotify)
|
||||
return;
|
||||
|
||||
mouseOff();
|
||||
|
||||
for (i = 0; i != 8; i++) {
|
||||
window = _windowArray[i];
|
||||
if (window && window->iconPtr && window->iconPtr->itemRef == item) {
|
||||
if (_fcsData1[i]) {
|
||||
_fcsData2[i] = true;
|
||||
} else {
|
||||
_fcsData2[i] = false;
|
||||
drawIconArray(i, item, window->iconPtr->line, window->iconPtr->classMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mouseOn();
|
||||
}
|
||||
|
||||
void AGOSEngine::unlinkItem(Item *item) {
|
||||
Item *first, *parent, *next;
|
||||
|
||||
// can't unlink item without parent
|
||||
if (item->parent == 0)
|
||||
return;
|
||||
|
||||
// get parent and first child of parent
|
||||
parent = derefItem(item->parent);
|
||||
first = derefItem(parent->child);
|
||||
|
||||
// the node to remove is first in the parent's children?
|
||||
if (first == item) {
|
||||
parent->child = item->next;
|
||||
item->parent = 0;
|
||||
item->next = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!first)
|
||||
error("unlinkItem: parent empty");
|
||||
if (first->next == 0)
|
||||
error("unlinkItem: parent does not contain child");
|
||||
|
||||
next = derefItem(first->next);
|
||||
if (next == item) {
|
||||
first->next = next->next;
|
||||
item->parent = 0;
|
||||
item->next = 0;
|
||||
return;
|
||||
}
|
||||
first = next;
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::linkItem(Item *item, Item *parent) {
|
||||
uint id;
|
||||
// Don't allow that an item that is already linked is relinked
|
||||
if (item->parent)
|
||||
return;
|
||||
|
||||
id = itemPtrToID(parent);
|
||||
item->parent = id;
|
||||
|
||||
if (parent != 0) {
|
||||
item->next = parent->child;
|
||||
parent->child = itemPtrToID(item);
|
||||
} else {
|
||||
item->next = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool AGOSEngine::has_item_childflag_0x10(Item *item) {
|
||||
SubObject *child = (SubObject *)findChildOfType(item, 2);
|
||||
return child && (child->objectFlags & kOFIcon) != 0;
|
||||
}
|
||||
|
||||
int AGOSEngine::wordMatch(Item *item, int16 a, int16 n) {
|
||||
if ((a == -1) && (n == item->noun))
|
||||
return 1;
|
||||
if ((a == item->adjective) && (n == item->noun))
|
||||
return 1 ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Item *AGOSEngine::derefItem(uint item) {
|
||||
if (item >= _itemArraySize) {
|
||||
debug(1, "derefItem: invalid item %d", item);
|
||||
return 0;
|
||||
}
|
||||
return _itemArrayPtr[item];
|
||||
}
|
||||
|
||||
Item *AGOSEngine::findInByClass(Item *i, int16 m) {
|
||||
i = derefItem(i->child);
|
||||
|
||||
while (i) {
|
||||
if (i->classFlags & m) {
|
||||
//_findNextPtr = derefItem(i->next);
|
||||
return i;
|
||||
}
|
||||
if (m == 0) {
|
||||
//_findNextPtr = derefItem(i->next);
|
||||
return i;
|
||||
}
|
||||
i = derefItem(i->next);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Item *AGOSEngine::findMaster(int16 a, int16 n) {
|
||||
uint j;
|
||||
|
||||
for (j = 1; j < _itemArraySize; j++) {
|
||||
Item *item = derefItem(j);
|
||||
if (wordMatch(item, a, n))
|
||||
return item;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Item *AGOSEngine::nextMaster(Item *i, int16 a, int16 n) {
|
||||
uint j;
|
||||
uint first = itemPtrToID(i) + 1;
|
||||
|
||||
for (j = first; j < _itemArraySize; j++) {
|
||||
Item *item = derefItem(j);
|
||||
if (wordMatch(item, a, n))
|
||||
return item;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint AGOSEngine::itemPtrToID(Item *id) {
|
||||
uint i;
|
||||
for (i = 0; i != _itemArraySize; i++)
|
||||
if (_itemArrayPtr[i] == id)
|
||||
return i;
|
||||
error("itemPtrToID: not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace AGOS
|
|
@ -11,7 +11,10 @@ MODULE_OBJS := \
|
|||
draw.o \
|
||||
event.o \
|
||||
game.o \
|
||||
gfx.o \
|
||||
icons.o \
|
||||
input.o \
|
||||
items.o \
|
||||
menus.o \
|
||||
midi.o \
|
||||
midiparser_s1d.o \
|
||||
|
@ -33,7 +36,11 @@ MODULE_OBJS := \
|
|||
subroutine.o \
|
||||
verb.o \
|
||||
vga.o \
|
||||
window.o
|
||||
vga_s1.o \
|
||||
vga_s2.o \
|
||||
vga_ff.o \
|
||||
window.o \
|
||||
zones.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifdef BUILD_PLUGINS
|
||||
|
|
|
@ -1333,6 +1333,87 @@ void AGOSEngine::o_unfreezeZones() {
|
|||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
byte AGOSEngine::getByte() {
|
||||
return *_codePtr++;
|
||||
}
|
||||
|
||||
int AGOSEngine::getNextWord() {
|
||||
int16 a = (int16)READ_BE_UINT16(_codePtr);
|
||||
_codePtr += 2;
|
||||
return a;
|
||||
}
|
||||
|
||||
uint AGOSEngine::getNextStringID() {
|
||||
return (uint16)getNextWord();
|
||||
}
|
||||
|
||||
uint AGOSEngine::getVarOrByte() {
|
||||
if (getGameType() == GType_ELVIRA1) {
|
||||
return getVarOrWord();
|
||||
} else {
|
||||
uint a = *_codePtr++;
|
||||
if (a != 255)
|
||||
return a;
|
||||
return readVariable(*_codePtr++);
|
||||
}
|
||||
}
|
||||
|
||||
uint AGOSEngine::getVarOrWord() {
|
||||
uint a = READ_BE_UINT16(_codePtr);
|
||||
_codePtr += 2;
|
||||
if (getGameType() == GType_PP) {
|
||||
if (a >= 60000 && a < 62048) {
|
||||
return readVariable(a - 60000);
|
||||
}
|
||||
} else {
|
||||
if (a >= 30000 && a < 30512) {
|
||||
return readVariable(a - 30000);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
uint AGOSEngine::getVarWrapper() {
|
||||
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_PP)
|
||||
return getVarOrWord();
|
||||
else
|
||||
return getVarOrByte();
|
||||
}
|
||||
|
||||
uint AGOSEngine::getNextVarContents() {
|
||||
return (uint16)readVariable(getVarWrapper());
|
||||
}
|
||||
|
||||
uint AGOSEngine::readVariable(uint variable) {
|
||||
if (variable >= _numVars)
|
||||
error("readVariable: Variable %d out of range", variable);
|
||||
|
||||
if (getGameType() == GType_PP) {
|
||||
return (uint16)_variableArray[variable];
|
||||
} else if (getGameType() == GType_FF) {
|
||||
if (getBitFlag(83))
|
||||
return (uint16)_variableArray2[variable];
|
||||
else
|
||||
return (uint16)_variableArray[variable];
|
||||
} else {
|
||||
return _variableArray[variable];
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::writeNextVarContents(uint16 contents) {
|
||||
writeVariable(getVarWrapper(), contents);
|
||||
}
|
||||
|
||||
void AGOSEngine::writeVariable(uint variable, uint16 contents) {
|
||||
if (variable >= _numVars)
|
||||
error("writeVariable: Variable %d out of range", variable);
|
||||
|
||||
if (getGameType() == GType_FF && getBitFlag(83))
|
||||
_variableArray2[variable] = contents;
|
||||
else
|
||||
_variableArray[variable] = contents;
|
||||
}
|
||||
|
||||
int AGOSEngine::runScript() {
|
||||
int opcode;
|
||||
bool flag;
|
||||
|
|
|
@ -46,7 +46,6 @@ void AGOSEngine::setupFeebleOpcodes(OpcodeProc *op) {
|
|||
op[122] = &AGOSEngine::o3_oracleTextDown;
|
||||
op[123] = &AGOSEngine::o3_oracleTextUp;
|
||||
op[124] = &AGOSEngine::o3_ifTime;
|
||||
op[127] = NULL;
|
||||
op[131] = &AGOSEngine::o3_setTime;
|
||||
op[132] = &AGOSEngine::o3_saveUserGame;
|
||||
op[133] = &AGOSEngine::o3_loadUserGame;
|
||||
|
|
|
@ -49,7 +49,6 @@ void AGOSEngine::setupPuzzleOpcodes(OpcodeProc *op) {
|
|||
op[122] = &AGOSEngine::o3_oracleTextDown;
|
||||
op[123] = &AGOSEngine::o3_oracleTextUp;
|
||||
op[124] = &AGOSEngine::o3_ifTime;
|
||||
op[127] = NULL;
|
||||
op[131] = &AGOSEngine::o3_setTime;
|
||||
op[132] = &AGOSEngine::o4_saveUserGame;
|
||||
op[133] = &AGOSEngine::o4_loadUserGame;
|
||||
|
|
|
@ -79,14 +79,19 @@ void AGOSEngine::o1_rescan() {
|
|||
|
||||
void AGOSEngine::o1_animate() {
|
||||
// 98: start vga
|
||||
uint vga_res, vgaSpriteId, windowNum, x, y, palette;
|
||||
vgaSpriteId = getVarOrWord();
|
||||
vga_res = vgaSpriteId / 100;
|
||||
windowNum = getVarOrByte();
|
||||
x = getVarOrWord();
|
||||
y = getVarOrWord();
|
||||
palette = getVarOrWord();
|
||||
loadSprite(windowNum, vga_res, vgaSpriteId, x, y, palette);
|
||||
uint vgaSpriteId = getVarOrWord();
|
||||
uint windowNum = getVarOrByte();
|
||||
uint x = getVarOrWord();
|
||||
uint y = getVarOrWord();
|
||||
uint palette = getVarOrWord();
|
||||
|
||||
if (getGameType() == GType_SIMON1 && (getFeatures() & GF_TALKIE) && vgaSpriteId >= 400) {
|
||||
_lastVgaWaitFor = 0;
|
||||
}
|
||||
|
||||
_lockWord |= 0x40;
|
||||
animate(windowNum, vgaSpriteId / 100, vgaSpriteId, x, y, palette);
|
||||
_lockWord &= ~0x40;
|
||||
}
|
||||
|
||||
void AGOSEngine::o1_stopAnimate() {
|
||||
|
|
|
@ -87,13 +87,16 @@ void AGOSEngine::o2_rescan() {
|
|||
|
||||
void AGOSEngine::o2_animate() {
|
||||
// 98: start vga
|
||||
uint vga_res = getVarOrWord();
|
||||
uint zoneNum = getVarOrWord();
|
||||
uint vgaSpriteId = getVarOrWord();
|
||||
uint windowNum = getVarOrByte();
|
||||
uint x = getVarOrWord();
|
||||
uint y = getVarOrWord();
|
||||
uint palette = getVarOrWord();
|
||||
loadSprite(windowNum, vga_res, vgaSpriteId, x, y, palette);
|
||||
|
||||
_lockWord |= 0x40;
|
||||
animate(windowNum, zoneNum, vgaSpriteId, x, y, palette);
|
||||
_lockWord &= ~0x40;
|
||||
}
|
||||
|
||||
void AGOSEngine::o2_stopAnimate() {
|
||||
|
|
|
@ -54,6 +54,22 @@ const byte *AGOSEngine::getLocalStringByID(uint stringId) {
|
|||
return _localStringtable[stringId - _stringIdLocalMin];
|
||||
}
|
||||
|
||||
TextLocation *AGOSEngine::getTextLocation(uint a) {
|
||||
switch (a) {
|
||||
case 1:
|
||||
return &_textLocation1;
|
||||
case 2:
|
||||
return &_textLocation2;
|
||||
case 101:
|
||||
return &_textLocation3;
|
||||
case 102:
|
||||
return &_textLocation4;
|
||||
default:
|
||||
error("getTextLocation: Invalid text location %d", a);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AGOSEngine::allocateStringTable(int num) {
|
||||
_stringTabPtr = (byte **)calloc(num, sizeof(byte *));
|
||||
_stringTabPos = 0;
|
||||
|
@ -319,7 +335,7 @@ void AGOSEngine::printInteractText(uint16 num, const char *string) {
|
|||
|
||||
stopAnimateSimon2(2, num + 6);
|
||||
renderString(num, 0, w, height, convertedString);
|
||||
loadSprite(4, 2, num + 6, x, _interactY, 12);
|
||||
animate(4, 2, num + 6, x, _interactY, 12);
|
||||
|
||||
_interactY += height;
|
||||
}
|
||||
|
@ -463,9 +479,9 @@ void AGOSEngine::printScreenText(uint vgaSpriteId, uint color, const char *strin
|
|||
}
|
||||
|
||||
if (getGameType() == GType_SIMON1)
|
||||
loadSprite(b, 2, vgaSpriteId + 199, x, y, 12);
|
||||
animate(b, 2, vgaSpriteId + 199, x, y, 12);
|
||||
else
|
||||
loadSprite(b, 2, vgaSpriteId, x, y, 12);
|
||||
animate(b, 2, vgaSpriteId, x, y, 12);
|
||||
}
|
||||
|
||||
// String code for boxes in Waxworks
|
||||
|
@ -665,7 +681,7 @@ void AGOSEngine::printBox() {
|
|||
stopAnimateSimon1(105);
|
||||
BoxSize = getBoxSize();
|
||||
_variableArray[53] = BoxSize;
|
||||
loadSprite(3, 1, 100, 0, 0, 0);
|
||||
animate(3, 1, 100, 0, 0, 0);
|
||||
changeWindow(5);
|
||||
|
||||
switch (BoxSize) {
|
||||
|
|
|
@ -241,6 +241,26 @@ byte *AGOSEngine::allocateTable(uint size) {
|
|||
return org;
|
||||
}
|
||||
|
||||
void AGOSEngine::allocTablesHeap() {
|
||||
_tablesHeapSize = _tableMemSize;
|
||||
_tablesHeapCurPos = 0;
|
||||
_tablesHeapPtr = (byte *)calloc(_tableMemSize, 1);
|
||||
if (!_tablesHeapPtr)
|
||||
error("Out Of Memory - Tables");
|
||||
}
|
||||
|
||||
void AGOSEngine::endCutscene() {
|
||||
Subroutine *sub;
|
||||
|
||||
_sound->stopVoice();
|
||||
|
||||
sub = getSubroutineByID(170);
|
||||
if (sub != NULL)
|
||||
startSubroutineEx(sub);
|
||||
|
||||
_runScriptReturn1 = true;
|
||||
}
|
||||
|
||||
File *AGOSEngine::openTablesFile(const char *filename) {
|
||||
if (getFeatures() & GF_OLD_BUNDLE)
|
||||
return openTablesFile_simon1(filename);
|
||||
|
|
|
@ -606,14 +606,14 @@ void AGOSEngine::checkUp(WindowBlock *window) {
|
|||
if (!isBoxDead(j + 201)) {
|
||||
uint index = getWindowNum(window);
|
||||
drawIconArray(index, window->iconPtr->itemRef, 0, window->iconPtr->classMask);
|
||||
loadSprite(4, 9, k + 34, 0, 0, 0);
|
||||
animate(4, 9, k + 34, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
if ((_variableArray[31] - _variableArray[30]) == 76) {
|
||||
k = ((_variableArray[31] / 52) % 3);
|
||||
j = k * 6;
|
||||
if (isBoxDead(j + 201)) {
|
||||
loadSprite(4, 9, k + 31, 0, 0, 0);
|
||||
animate(4, 9, k + 31, 0, 0, 0);
|
||||
undefineBox(j + 201);
|
||||
undefineBox(j + 202);
|
||||
undefineBox(j + 203);
|
||||
|
@ -633,14 +633,14 @@ void AGOSEngine::checkDown(WindowBlock *window) {
|
|||
uint index = getWindowNum(window);
|
||||
drawIconArray(index, window->iconPtr->itemRef, 0, window->iconPtr->classMask);
|
||||
k = ((_variableArray[31] / 52) % 3);
|
||||
loadSprite(4, 9, k + 25, 0, 0, 0);
|
||||
animate(4, 9, k + 25, 0, 0, 0);
|
||||
_variableArray[31] += 52;
|
||||
}
|
||||
if (((_variableArray[31] - _variableArray[30]) == 40) && (_variableArray[30] > 52)) {
|
||||
k = (((_variableArray[31] / 52) + 1) % 3);
|
||||
j = k * 6;
|
||||
if (isBoxDead(j + 201)) {
|
||||
loadSprite(4, 9, k + 28, 0, 0, 0);
|
||||
animate(4, 9, k + 28, 0, 0, 0);
|
||||
undefineBox(j + 201);
|
||||
undefineBox(j + 202);
|
||||
undefineBox(j + 203);
|
||||
|
@ -655,7 +655,7 @@ void AGOSEngine::inventoryUp(WindowBlock *window) {
|
|||
if (getGameType() == GType_FF) {
|
||||
_marks = 0;
|
||||
checkUp(window);
|
||||
loadSprite(4, 9, 21, 0 ,0, 0);
|
||||
animate(4, 9, 21, 0 ,0, 0);
|
||||
while (1) {
|
||||
if (_currentBoxNumber != 0x7FFB || !getBitFlag(89))
|
||||
break;
|
||||
|
@ -682,7 +682,7 @@ void AGOSEngine::inventoryDown(WindowBlock *window) {
|
|||
if (getGameType() == GType_FF) {
|
||||
_marks = 0;
|
||||
checkDown(window);
|
||||
loadSprite(4, 9, 23, 0, 0, 0);
|
||||
animate(4, 9, 23, 0, 0, 0);
|
||||
while (1) {
|
||||
if (_currentBoxNumber != 0x7FFC || !getBitFlag(89))
|
||||
break;
|
||||
|
|
1928
engines/agos/vga.cpp
1928
engines/agos/vga.cpp
File diff suppressed because it is too large
Load diff
437
engines/agos/vga_ff.cpp
Normal file
437
engines/agos/vga_ff.cpp
Normal file
|
@ -0,0 +1,437 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 Ludvig Strigeus
|
||||
* Copyright (C) 2001-2006 The ScummVM project
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stdafx.h"
|
||||
|
||||
#include "agos/agos.h"
|
||||
#include "agos/intern.h"
|
||||
#include "agos/vga.h"
|
||||
|
||||
namespace AGOS {
|
||||
|
||||
void AGOSEngine::setupFeebleVideoOpcodes(VgaOpcodeProc *op) {
|
||||
setupSimon2VideoOpcodes(op);
|
||||
|
||||
op[53] = &AGOSEngine::vc53_panSFX;
|
||||
op[75] = &AGOSEngine::vc75_setScale;
|
||||
op[76] = &AGOSEngine::vc76_setScaleXOffs;
|
||||
op[77] = &AGOSEngine::vc77_setScaleYOffs;
|
||||
op[78] = &AGOSEngine::vc78_computeXY;
|
||||
op[79] = &AGOSEngine::vc79_computePosNum;
|
||||
op[80] = &AGOSEngine::vc80_setOverlayImage;
|
||||
op[81] = &AGOSEngine::vc81_setRandom;
|
||||
op[82] = &AGOSEngine::vc82_getPathValue;
|
||||
op[83] = &AGOSEngine::vc83_playSoundLoop;
|
||||
op[84] = &AGOSEngine::vc84_stopSoundLoop;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc53_panSFX() {
|
||||
VgaSprite *vsp = findCurSprite();
|
||||
int pan;
|
||||
|
||||
uint16 sound = vcReadNextWord();
|
||||
int16 xoffs = vcReadNextWord();
|
||||
int16 vol = vcReadNextWord();
|
||||
|
||||
pan = (vsp->x - _scrollX + xoffs) * 8 - 2560;
|
||||
if (pan < -10000)
|
||||
pan = -10000;
|
||||
if (pan > 10000)
|
||||
pan = 10000;
|
||||
|
||||
loadSound(sound, 0, vol, 1);
|
||||
|
||||
if (xoffs != 2)
|
||||
xoffs |= 0x10;
|
||||
|
||||
addVgaEvent(10, NULL, _vgaCurSpriteId, _vgaCurZoneNum, xoffs); /* pan event */
|
||||
debug(0, "vc53_panSFX: snd %d xoffs %d vol %d", sound, xoffs, vol);
|
||||
}
|
||||
|
||||
int AGOSEngine::getScale(int16 y, int16 x) {
|
||||
int16 z;
|
||||
|
||||
if (y > _baseY) {
|
||||
return((int16)(x * (1 + ((y - _baseY) * _scale))));
|
||||
} else {
|
||||
if (x == 0)
|
||||
return(0);
|
||||
if (x < 0) {
|
||||
z = ((int16)((x * (1 - ((_baseY - y)* _scale))) - 0.5));
|
||||
if (z >- 2)
|
||||
return(-2);
|
||||
return(z);
|
||||
}
|
||||
|
||||
z = ((int16)((x * (1 - ((_baseY - y) * _scale))) + 0.5));
|
||||
if (z < 2)
|
||||
return(2);
|
||||
|
||||
return(z);
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::vc75_setScale() {
|
||||
_baseY = vcReadNextWord();
|
||||
_scale = (float)vcReadNextWord() / 1000000.;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc76_setScaleXOffs() {
|
||||
if (getGameType() == GType_PP && getBitFlag(120)) {
|
||||
VgaSprite *vsp1, *vsp2;
|
||||
uint16 old_file_1, tmp1, tmp2;
|
||||
|
||||
old_file_1 = _vgaCurSpriteId;
|
||||
|
||||
_vgaCurSpriteId = vcReadVar(vcReadNextWord());
|
||||
vsp1 = findCurSprite();
|
||||
_vgaCurSpriteId = vcReadVar(vcReadNextWord());
|
||||
vsp2 = findCurSprite();
|
||||
|
||||
tmp1 = vsp1->x;
|
||||
tmp2 = vsp2->x;
|
||||
vsp1->x = tmp2;
|
||||
vsp2->x = tmp1;
|
||||
tmp1 = vsp1->y;
|
||||
tmp2 = vsp2->y;
|
||||
vsp1->y = tmp2;
|
||||
vsp2->y = tmp1;
|
||||
|
||||
_vgaCurSpriteId = old_file_1;
|
||||
_vcPtr += 2;
|
||||
} else {
|
||||
VgaSprite *vsp = findCurSprite();
|
||||
|
||||
vsp->image = vcReadNextWord();
|
||||
int16 x = vcReadNextWord();
|
||||
uint16 var = vcReadNextWord();
|
||||
|
||||
vsp->x += getScale(vsp->y, x);
|
||||
_variableArrayPtr[var] = vsp->x;
|
||||
|
||||
checkScrollX(x, vsp->x);
|
||||
|
||||
vsp->flags = kDFScaled;
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::vc77_setScaleYOffs() {
|
||||
VgaSprite *vsp = findCurSprite();
|
||||
|
||||
vsp->image = vcReadNextWord();
|
||||
int16 y = vcReadNextWord();
|
||||
uint16 var = vcReadNextWord();
|
||||
|
||||
vsp->y += getScale(vsp->y, y);
|
||||
_variableArrayPtr[var] = vsp->y;
|
||||
|
||||
if (y != 0)
|
||||
checkScrollY(y, vsp->y);
|
||||
|
||||
vsp->flags = kDFScaled;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc78_computeXY() {
|
||||
VgaSprite *vsp = findCurSprite();
|
||||
|
||||
uint16 a = (uint16)_variableArrayPtr[12];
|
||||
uint16 b = (uint16)_variableArrayPtr[13];
|
||||
|
||||
const uint16 *p = _pathFindArray[a - 1];
|
||||
p += b * 2;
|
||||
|
||||
uint16 posx = readUint16Wrapper(p);
|
||||
_variableArrayPtr[15] = posx;
|
||||
vsp->x = posx;
|
||||
|
||||
uint16 posy = readUint16Wrapper(p + 1);
|
||||
_variableArrayPtr[16] = posy;
|
||||
vsp->y = posy;
|
||||
|
||||
if (getGameType() == GType_FF) {
|
||||
setBitFlag(85, false);
|
||||
if (getBitFlag(74)) {
|
||||
centreScroll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::vc79_computePosNum() {
|
||||
uint a = (uint16)_variableArrayPtr[12];
|
||||
const uint16 *p = _pathFindArray[a - 1];
|
||||
uint pos = 0;
|
||||
|
||||
int16 y = _variableArrayPtr[16];
|
||||
while (y >= (int16)readUint16Wrapper(p + 1)) {
|
||||
p += 2;
|
||||
pos++;
|
||||
}
|
||||
|
||||
_variableArrayPtr[13] = pos;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc80_setOverlayImage() {
|
||||
VgaSprite *vsp = findCurSprite();
|
||||
|
||||
vsp->image = vcReadVarOrWord();
|
||||
|
||||
vsp->x += vcReadNextWord();
|
||||
vsp->y += vcReadNextWord();
|
||||
vsp->flags = kDFOverlayed;
|
||||
|
||||
_vgaSpriteChanged++;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc81_setRandom() {
|
||||
uint16 var = vcReadNextWord();
|
||||
uint16 value = vcReadNextWord();
|
||||
|
||||
_variableArray[var] = _rnd.getRandomNumber(value - 1);
|
||||
}
|
||||
|
||||
void AGOSEngine::vc82_getPathValue() {
|
||||
uint8 val;
|
||||
|
||||
uint16 var = vcReadNextWord();
|
||||
|
||||
if (getGameType() == GType_FF && getBitFlag(82)) {
|
||||
val = _pathValues1[_GPVCount1++];
|
||||
} else {
|
||||
val = _pathValues[_GPVCount++];
|
||||
}
|
||||
|
||||
vcWriteVar(var, val);
|
||||
}
|
||||
|
||||
void AGOSEngine::vc83_playSoundLoop() {
|
||||
uint16 sound = vcReadNextWord();
|
||||
int16 vol = vcReadNextWord();
|
||||
int16 pan = vcReadNextWord();
|
||||
|
||||
loadSound(sound, pan, vol, 3);
|
||||
}
|
||||
|
||||
void AGOSEngine::vc84_stopSoundLoop() {
|
||||
_sound->stopSfx5();
|
||||
}
|
||||
|
||||
// Scrolling functions for Feeble Files
|
||||
void AGOSEngine::checkScrollX(int16 x, int16 xpos) {
|
||||
if (_scrollXMax == 0 || x == 0)
|
||||
return;
|
||||
|
||||
if ((getGameType() == GType_FF) && (getBitFlag(80) || getBitFlag(82)))
|
||||
return;
|
||||
|
||||
int16 tmp;
|
||||
if (x > 0) {
|
||||
if (_scrollCount != 0) {
|
||||
if (_scrollCount >= 0)
|
||||
return;
|
||||
_scrollCount = 0;
|
||||
} else {
|
||||
if (_scrollFlag != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (xpos - _scrollX >= 480) {
|
||||
_scrollCount = 320;
|
||||
tmp = _scrollXMax - _scrollX;
|
||||
if (tmp < 320)
|
||||
_scrollCount = tmp;
|
||||
}
|
||||
} else {
|
||||
if (_scrollCount != 0) {
|
||||
if (_scrollCount < 0)
|
||||
return;
|
||||
_scrollCount = 0;
|
||||
} else {
|
||||
if (_scrollFlag != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (xpos - _scrollX < 161) {
|
||||
_scrollCount = -320;
|
||||
if (_scrollX < 320)
|
||||
_scrollCount = -_scrollX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::checkScrollY(int16 y, int16 ypos) {
|
||||
if (_scrollYMax == 0)
|
||||
return;
|
||||
|
||||
if (getGameType() == GType_FF && getBitFlag(80))
|
||||
return;
|
||||
|
||||
int16 tmp;
|
||||
if (y >= 0) {
|
||||
if (_scrollCount != 0) {
|
||||
if (_scrollCount >= 0)
|
||||
return;
|
||||
} else {
|
||||
if (_scrollFlag != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ypos - _scrollY >= 440) {
|
||||
_scrollCount = 240;
|
||||
tmp = _scrollYMax - _scrollY;
|
||||
if (tmp < 240)
|
||||
_scrollCount = tmp;
|
||||
}
|
||||
} else {
|
||||
if (_scrollCount != 0) {
|
||||
if (_scrollCount < 0)
|
||||
return;
|
||||
} else {
|
||||
if (_scrollFlag != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ypos - _scrollY < 100) {
|
||||
_scrollCount = -240;
|
||||
if (_scrollY < 240)
|
||||
_scrollCount = -_scrollY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::centreScroll() {
|
||||
int16 x, y, tmp;
|
||||
|
||||
if (_scrollXMax != 0) {
|
||||
_scrollCount = 0;
|
||||
x = _variableArray[15] - _scrollX;
|
||||
if (x < 17 || (getBitFlag(85) && x < 320)) {
|
||||
x -= 320;
|
||||
if (_scrollX < -x)
|
||||
x = -_scrollX;
|
||||
_scrollCount = x;
|
||||
} else if ((getBitFlag(85) && x >= 320) || x >= 624) {
|
||||
x -= 320;
|
||||
tmp = _scrollXMax - _scrollX;
|
||||
if (tmp < x)
|
||||
x = tmp;
|
||||
_scrollCount = x;
|
||||
}
|
||||
} else if (_scrollYMax != 0) {
|
||||
_scrollCount = 0;
|
||||
y = _variableArray[16] - _scrollY;
|
||||
if (y < 30) {
|
||||
y -= 240;
|
||||
if (_scrollY < -y)
|
||||
y = -_scrollY;
|
||||
_scrollCount = y;
|
||||
} else if (y >= 460) {
|
||||
y -= 240;
|
||||
tmp = _scrollYMax - _scrollY;
|
||||
if (tmp < y)
|
||||
y = tmp;
|
||||
_scrollCount = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::startOverlayAnims() {
|
||||
VgaSprite *vsp = _vgaSprites;
|
||||
uint16 zoneNum;
|
||||
int i;
|
||||
|
||||
zoneNum = _variableArray[999];
|
||||
|
||||
for (i = 0; i < 600; i++) {
|
||||
if (_variableArray[1000 + i] < 100)
|
||||
continue;
|
||||
|
||||
while (vsp->id)
|
||||
vsp++;
|
||||
|
||||
vsp->windowNum = 4;
|
||||
vsp->priority = 4;
|
||||
vsp->flags = 0;
|
||||
vsp->palette = 0;
|
||||
vsp->image = _variableArray[1000 + i];
|
||||
if (i >= 300) {
|
||||
vsp->y = ((i - 300) / 20) * 32;
|
||||
vsp->x = ((i - 300) % 20) * 32;
|
||||
} else {
|
||||
vsp->y = (i / 20) * 32;
|
||||
vsp->x = (i % 20) * 32;
|
||||
}
|
||||
vsp->id = 1000 + i;
|
||||
vsp->zoneNum = zoneNum;
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::startAnOverlayAnim() {
|
||||
VgaSprite *vsp = _vgaSprites;
|
||||
const byte *vcPtrOrg;
|
||||
uint16 a, sprite, file, tmp, zoneNum;
|
||||
int16 x;
|
||||
|
||||
zoneNum = _variableArray[999];
|
||||
|
||||
_vcPtr += 4;
|
||||
a = vcReadNextWord();
|
||||
_vcPtr += 6;
|
||||
|
||||
while (vsp->id)
|
||||
vsp++;
|
||||
|
||||
vsp->windowNum = 4;
|
||||
vsp->priority = 20;
|
||||
vsp->flags = 0;
|
||||
vsp->palette = 0;
|
||||
vsp->image = vcReadVar(vcReadVar(a));
|
||||
|
||||
x = vcReadVar(a) - 1300;
|
||||
if (x < 0) {
|
||||
x += 300;
|
||||
vsp->priority = 10;
|
||||
}
|
||||
|
||||
vsp->y = x / 20 * 32;
|
||||
vsp->x = x % 20 * 32;;
|
||||
vsp->id = vcReadVar(a);
|
||||
vsp->zoneNum = zoneNum;
|
||||
|
||||
sprite = _vgaCurSpriteId;
|
||||
file = _vgaCurZoneNum;
|
||||
|
||||
_vgaCurZoneNum = vsp->zoneNum;
|
||||
_vgaCurSpriteId = vsp->id;
|
||||
|
||||
tmp = to16Wrapper(vsp->priority);
|
||||
|
||||
vcPtrOrg = _vcPtr;
|
||||
_vcPtr = (byte *)&tmp;
|
||||
vc23_setPriority();
|
||||
|
||||
_vcPtr = vcPtrOrg;
|
||||
_vgaCurSpriteId = sprite;
|
||||
_vgaCurZoneNum = file;
|
||||
}
|
||||
|
||||
} // End of namespace AGOS
|
215
engines/agos/vga_s1.cpp
Normal file
215
engines/agos/vga_s1.cpp
Normal file
|
@ -0,0 +1,215 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 Ludvig Strigeus
|
||||
* Copyright (C) 2001-2006 The ScummVM project
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stdafx.h"
|
||||
|
||||
#include "agos/agos.h"
|
||||
#include "agos/intern.h"
|
||||
#include "agos/vga.h"
|
||||
|
||||
namespace AGOS {
|
||||
|
||||
void AGOSEngine::setupSimon1VideoOpcodes(VgaOpcodeProc *op) {
|
||||
setupCommonVideoOpcodes(op);
|
||||
|
||||
op[11] = &AGOSEngine::vc11_clearPathFinder;
|
||||
op[17] = &AGOSEngine::vc17_setPathfinderItem;
|
||||
op[22] = &AGOSEngine::vc22_setPaletteNew;
|
||||
op[32] = &AGOSEngine::vc32_copyVar;
|
||||
op[37] = &AGOSEngine::vc37_addToSpriteY;
|
||||
op[48] = &AGOSEngine::vc48_setPathFinder;
|
||||
op[59] = &AGOSEngine::vc59_skipIfSpeechEnded;
|
||||
op[60] = &AGOSEngine::vc60_stopAnimation;
|
||||
op[61] = &AGOSEngine::vc61_setMaskImage;
|
||||
op[62] = &AGOSEngine::vc62_fastFadeOut;
|
||||
op[63] = &AGOSEngine::vc63_fastFadeIn;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc11_clearPathFinder() {
|
||||
memset(&_pathFindArray, 0, sizeof(_pathFindArray));
|
||||
}
|
||||
|
||||
void AGOSEngine::vc17_setPathfinderItem() {
|
||||
uint16 a = vcReadNextWord();
|
||||
_pathFindArray[a - 1] = (const uint16 *)_vcPtr;
|
||||
|
||||
int end = (getGameType() == GType_FF || getGameType() == GType_PP) ? 9999 : 999;
|
||||
while (readUint16Wrapper(_vcPtr) != end)
|
||||
_vcPtr += 4;
|
||||
_vcPtr += 2;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc22_setPaletteNew() {
|
||||
byte *offs, *palptr, *src;
|
||||
uint16 a = 0, b, num, palSize;
|
||||
|
||||
a = vcReadNextWord();
|
||||
b = vcReadNextWord();
|
||||
|
||||
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
||||
num = 256;
|
||||
palSize = 768;
|
||||
|
||||
palptr = _displayPalette;
|
||||
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
|
||||
num = a == 0 ? 32 : 16;
|
||||
palSize = 96;
|
||||
|
||||
palptr = &_displayPalette[(a * 64)];
|
||||
}
|
||||
|
||||
offs = _curVgaFile1 + 6;
|
||||
src = offs + b * palSize;
|
||||
|
||||
do {
|
||||
palptr[0] = src[0] * 4;
|
||||
palptr[1] = src[1] * 4;
|
||||
palptr[2] = src[2] * 4;
|
||||
palptr[3] = 0;
|
||||
|
||||
palptr += 4;
|
||||
src += 3;
|
||||
} while (--num);
|
||||
|
||||
_paletteFlag = 2;
|
||||
_vgaSpriteChanged++;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc32_copyVar() {
|
||||
uint16 a = vcReadVar(vcReadNextWord());
|
||||
vcWriteVar(vcReadNextWord(), a);
|
||||
}
|
||||
|
||||
void AGOSEngine::vc37_addToSpriteY() {
|
||||
VgaSprite *vsp = findCurSprite();
|
||||
vsp->y += vcReadVar(vcReadNextWord());
|
||||
_vgaSpriteChanged++;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc45_setSpriteX() {
|
||||
VgaSprite *vsp = findCurSprite();
|
||||
vsp->x = vcReadVar(vcReadNextWord());
|
||||
_vgaSpriteChanged++;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc46_setSpriteY() {
|
||||
VgaSprite *vsp = findCurSprite();
|
||||
vsp->y = vcReadVar(vcReadNextWord());
|
||||
_vgaSpriteChanged++;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc47_addToVar() {
|
||||
uint16 var = vcReadNextWord();
|
||||
vcWriteVar(var, vcReadVar(var) + vcReadVar(vcReadNextWord()));
|
||||
}
|
||||
|
||||
void AGOSEngine::vc48_setPathFinder() {
|
||||
uint16 a = (uint16)_variableArrayPtr[12];
|
||||
const uint16 *p = _pathFindArray[a - 1];
|
||||
|
||||
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
||||
VgaSprite *vsp = findCurSprite();
|
||||
int16 x, y, ydiff;
|
||||
int16 x1, y1, x2, y2;
|
||||
uint pos = 0;
|
||||
|
||||
x = vsp->x;
|
||||
while (x >= (int16)readUint16Wrapper(p + 2)) {
|
||||
p += 2;
|
||||
pos++;
|
||||
}
|
||||
|
||||
x1 = readUint16Wrapper(p);
|
||||
y1 = readUint16Wrapper(p + 1);
|
||||
x2 = readUint16Wrapper(p + 2);
|
||||
y2 = readUint16Wrapper(p + 3);
|
||||
|
||||
if (x2 != 9999) {
|
||||
ydiff = y2 - y1;
|
||||
if (ydiff < 0) {
|
||||
ydiff = -ydiff;
|
||||
x = vsp->x & 7;
|
||||
ydiff *= x;
|
||||
ydiff /= 8;
|
||||
ydiff = -ydiff;
|
||||
} else {
|
||||
x = vsp->x & 7;
|
||||
ydiff *= x;
|
||||
ydiff /= 8;
|
||||
}
|
||||
y1 += ydiff;
|
||||
}
|
||||
|
||||
y = vsp->y;
|
||||
vsp->y = y1;
|
||||
checkScrollY(y1 - y, y1);
|
||||
|
||||
_variableArrayPtr[11] = x1;
|
||||
_variableArrayPtr[13] = pos;
|
||||
} else {
|
||||
uint b = (uint16)_variableArray[13];
|
||||
p += b * 2 + 1;
|
||||
int c = _variableArray[14];
|
||||
|
||||
int step;
|
||||
int y1, y2;
|
||||
int16 *vp;
|
||||
|
||||
step = 2;
|
||||
if (c < 0) {
|
||||
c = -c;
|
||||
step = -2;
|
||||
}
|
||||
|
||||
vp = &_variableArray[20];
|
||||
|
||||
do {
|
||||
y2 = readUint16Wrapper(p);
|
||||
p += step;
|
||||
y1 = readUint16Wrapper(p) - y2;
|
||||
|
||||
vp[0] = y1 / 2;
|
||||
vp[1] = y1 - (y1 / 2);
|
||||
|
||||
vp += 2;
|
||||
} while (--c);
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::vc59_skipIfSpeechEnded() {
|
||||
if (!_sound->isVoiceActive())
|
||||
vcSkipNextInstruction();
|
||||
}
|
||||
|
||||
void AGOSEngine::vc61_setMaskImage() {
|
||||
VgaSprite *vsp = findCurSprite();
|
||||
|
||||
vsp->image = vcReadVarOrWord();
|
||||
vsp->x += vcReadNextWord();
|
||||
vsp->y += vcReadNextWord();
|
||||
vsp->flags = kDFMasked | kDFUseFrontBuf;
|
||||
|
||||
_vgaSpriteChanged++;
|
||||
}
|
||||
|
||||
} // End of namespace AGOS
|
211
engines/agos/vga_s2.cpp
Normal file
211
engines/agos/vga_s2.cpp
Normal file
|
@ -0,0 +1,211 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 Ludvig Strigeus
|
||||
* Copyright (C) 2001-2006 The ScummVM project
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stdafx.h"
|
||||
|
||||
#include "agos/agos.h"
|
||||
#include "agos/intern.h"
|
||||
#include "agos/vga.h"
|
||||
|
||||
namespace AGOS {
|
||||
|
||||
void AGOSEngine::setupSimon2VideoOpcodes(VgaOpcodeProc *op) {
|
||||
setupSimon1VideoOpcodes(op);
|
||||
|
||||
op[56] = &AGOSEngine::vc56_delayLong;
|
||||
op[58] = &AGOSEngine::vc58_changePriority;
|
||||
op[59] = &AGOSEngine::vc59_stopAnimations;
|
||||
op[64] = &AGOSEngine::vc64_skipIfSpeechEnded;
|
||||
op[65] = &AGOSEngine::vc65_slowFadeIn;
|
||||
op[66] = &AGOSEngine::vc66_skipIfNotEqual;
|
||||
op[67] = &AGOSEngine::vc67_skipIfGE;
|
||||
op[68] = &AGOSEngine::vc68_skipIfLE;
|
||||
op[69] = &AGOSEngine::vc69_playTrack;
|
||||
op[70] = &AGOSEngine::vc70_queueMusic;
|
||||
op[71] = &AGOSEngine::vc71_checkMusicQueue;
|
||||
op[72] = &AGOSEngine::vc72_play_track_2;
|
||||
op[73] = &AGOSEngine::vc73_setMark;
|
||||
op[74] = &AGOSEngine::vc74_clearMark;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc56_delayLong() {
|
||||
uint16 num = vcReadVarOrWord() * _frameRate;
|
||||
|
||||
addVgaEvent(num + _vgaBaseDelay, _vcPtr, _vgaCurSpriteId, _vgaCurZoneNum);
|
||||
_vcPtr = (byte *)&_vc_get_out_of_code;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc58_changePriority() {
|
||||
uint16 sprite = _vgaCurSpriteId;
|
||||
uint16 file = _vgaCurZoneNum;
|
||||
const byte *vcPtrOrg;
|
||||
uint16 tmp;
|
||||
|
||||
_vgaCurZoneNum = vcReadNextWord();
|
||||
_vgaCurSpriteId = vcReadNextWord();
|
||||
|
||||
tmp = to16Wrapper(vcReadNextWord());
|
||||
|
||||
vcPtrOrg = _vcPtr;
|
||||
_vcPtr = (byte *)&tmp;
|
||||
vc23_setPriority();
|
||||
|
||||
_vcPtr = vcPtrOrg;
|
||||
_vgaCurSpriteId = sprite;
|
||||
_vgaCurZoneNum = file;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc59_stopAnimations() {
|
||||
uint16 file = vcReadNextWord();
|
||||
uint16 start = vcReadNextWord();
|
||||
uint16 end = vcReadNextWord() + 1;
|
||||
|
||||
do {
|
||||
vc_kill_sprite(file, start);
|
||||
} while (++start != end);
|
||||
}
|
||||
|
||||
void AGOSEngine::vc64_skipIfSpeechEnded() {
|
||||
if ((getGameType() == GType_SIMON2 && _subtitles && _language != Common::HB_ISR) ||
|
||||
!_sound->isVoiceActive()) {
|
||||
vcSkipNextInstruction();
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::vc65_slowFadeIn() {
|
||||
_fastFadeInFlag = 624;
|
||||
_fastFadeCount = 208;
|
||||
if (_windowNum != 4) {
|
||||
_fastFadeInFlag = 768;
|
||||
_fastFadeCount = 256;
|
||||
}
|
||||
_fastFadeInFlag |= 0x8000;
|
||||
_fastFadeOutFlag = false;
|
||||
}
|
||||
|
||||
void AGOSEngine::vc66_skipIfNotEqual() {
|
||||
uint16 a = vcReadNextWord();
|
||||
uint16 b = vcReadNextWord();
|
||||
|
||||
if (vcReadVar(a) != vcReadVar(b))
|
||||
vcSkipNextInstruction();
|
||||
}
|
||||
|
||||
void AGOSEngine::vc67_skipIfGE() {
|
||||
uint16 a = vcReadNextWord();
|
||||
uint16 b = vcReadNextWord();
|
||||
|
||||
if (vcReadVar(a) >= vcReadVar(b))
|
||||
vcSkipNextInstruction();
|
||||
}
|
||||
|
||||
void AGOSEngine::vc68_skipIfLE() {
|
||||
uint16 a = vcReadNextWord();
|
||||
uint16 b = vcReadNextWord();
|
||||
|
||||
if (vcReadVar(a) <= vcReadVar(b))
|
||||
vcSkipNextInstruction();
|
||||
}
|
||||
|
||||
void AGOSEngine::vc69_playTrack() {
|
||||
int16 track = vcReadNextWord();
|
||||
int16 loop = vcReadNextWord();
|
||||
|
||||
// Jamieson630:
|
||||
// This is a "play track". The original
|
||||
// design stored the track to play if one was
|
||||
// already in progress, so that the next time a
|
||||
// "fill MIDI stream" event occured, the MIDI
|
||||
// player would find the change and switch
|
||||
// tracks. We use a different architecture that
|
||||
// allows for an immediate response here, but
|
||||
// we'll simulate the variable changes so other
|
||||
// scripts don't get thrown off.
|
||||
// NOTE: This opcode looks very similar in function
|
||||
// to vc72(), except that vc72() may allow for
|
||||
// specifying a non-valid track number (999 or -1)
|
||||
// as a means of stopping what music is currently
|
||||
// playing.
|
||||
midi.setLoop(loop != 0);
|
||||
midi.startTrack(track);
|
||||
}
|
||||
|
||||
void AGOSEngine::vc70_queueMusic() {
|
||||
// Simon2
|
||||
uint16 track = vcReadNextWord();
|
||||
uint16 loop = vcReadNextWord();
|
||||
|
||||
// Jamieson630:
|
||||
// This sets the "on end of track" action.
|
||||
// It specifies whether to loop the current
|
||||
// track and, if not, whether to switch to
|
||||
// a different track upon completion.
|
||||
if (track != 0xFFFF && track != 999)
|
||||
midi.queueTrack(track, loop != 0);
|
||||
else
|
||||
midi.setLoop(loop != 0);
|
||||
}
|
||||
|
||||
void AGOSEngine::vc71_checkMusicQueue() {
|
||||
// Jamieson630:
|
||||
// This command skips the next instruction
|
||||
// unless (1) there is a track playing, AND
|
||||
// (2) there is a track queued to play after it.
|
||||
if (!midi.isPlaying (true))
|
||||
vcSkipNextInstruction();
|
||||
}
|
||||
|
||||
void AGOSEngine::vc72_play_track_2() {
|
||||
// Jamieson630:
|
||||
// This is a "play or stop track". Note that
|
||||
// this opcode looks very similar in function
|
||||
// to vc69(), except that this opcode may allow
|
||||
// for specifying a track of 999 or -1 in order to
|
||||
// stop the music. We'll code it that way for now.
|
||||
|
||||
// NOTE: It's possible that when "stopping" a track,
|
||||
// we're supposed to just go on to the next queued
|
||||
// track, if any. Must find out if there is ANY
|
||||
// case where this is used to stop a track in the
|
||||
// first place.
|
||||
|
||||
int16 track = vcReadNextWord();
|
||||
int16 loop = vcReadNextWord();
|
||||
|
||||
if (track == -1 || track == 999) {
|
||||
midi.stop();
|
||||
} else {
|
||||
midi.setLoop (loop != 0);
|
||||
midi.startTrack (track);
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::vc73_setMark() {
|
||||
_marks |= (1 << vcReadNextWord());
|
||||
}
|
||||
|
||||
void AGOSEngine::vc74_clearMark() {
|
||||
_marks &= ~(1 << vcReadNextWord());
|
||||
}
|
||||
|
||||
} // End of namespace AGOS
|
196
engines/agos/zones.cpp
Normal file
196
engines/agos/zones.cpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 Ludvig Strigeus
|
||||
* Copyright (C) 2001-2006 The ScummVM project
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stdafx.h"
|
||||
|
||||
#include "common/file.h"
|
||||
|
||||
#include "agos/intern.h"
|
||||
#include "agos/agos.h"
|
||||
#include "agos/vga.h"
|
||||
|
||||
namespace AGOS {
|
||||
|
||||
void AGOSEngine::loadZone(uint zoneNum) {
|
||||
VgaPointersEntry *vpe;
|
||||
|
||||
CHECK_BOUNDS(zoneNum, _vgaBufferPointers);
|
||||
|
||||
vpe = _vgaBufferPointers + zoneNum;
|
||||
if (vpe->vgaFile1 != NULL)
|
||||
return;
|
||||
|
||||
// Loading order is important
|
||||
// due to resource managment
|
||||
|
||||
loadVGAVideoFile(zoneNum, 2);
|
||||
vpe->vgaFile2 = _block;
|
||||
vpe->vgaFile2End = _blockEnd;
|
||||
|
||||
loadVGAVideoFile(zoneNum, 1);
|
||||
vpe->vgaFile1 = _block;
|
||||
vpe->vgaFile1End = _blockEnd;
|
||||
|
||||
vpe->sfxFile = NULL;
|
||||
if (!(getFeatures() & GF_ZLIBCOMP)) {
|
||||
if (loadVGASoundFile(zoneNum, 3)) {
|
||||
vpe->sfxFile = _block;
|
||||
vpe->sfxFileEnd = _blockEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::setZoneBuffers() {
|
||||
_zoneBuffers = (byte *)malloc(_vgaMemSize);
|
||||
|
||||
_vgaMemPtr = _zoneBuffers;
|
||||
_vgaMemBase = _zoneBuffers;
|
||||
_vgaFrozenBase = _zoneBuffers;
|
||||
_vgaRealBase = _zoneBuffers;
|
||||
_vgaMemEnd = _zoneBuffers + _vgaMemSize;
|
||||
}
|
||||
|
||||
byte *AGOSEngine::allocBlock(uint32 size) {
|
||||
for (;;) {
|
||||
_block = _vgaMemPtr;
|
||||
_blockEnd = _block + size;
|
||||
|
||||
if (_blockEnd >= _vgaMemEnd) {
|
||||
_vgaMemPtr = _vgaMemBase;
|
||||
} else {
|
||||
_rejectBlock = false;
|
||||
checkNoOverWrite();
|
||||
if (_rejectBlock)
|
||||
continue;
|
||||
checkRunningAnims();
|
||||
if (_rejectBlock)
|
||||
continue;
|
||||
checkZonePtrs();
|
||||
_vgaMemPtr = _blockEnd;
|
||||
return _block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::checkNoOverWrite() {
|
||||
VgaPointersEntry *vpe;
|
||||
|
||||
if (_noOverWrite == 0xFFFF)
|
||||
return;
|
||||
|
||||
vpe = &_vgaBufferPointers[_noOverWrite];
|
||||
|
||||
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
||||
if (vpe->vgaFile1 < _blockEnd && vpe->vgaFile1End > _block) {
|
||||
_rejectBlock = true;
|
||||
_vgaMemPtr = vpe->vgaFile1End;
|
||||
} else if (vpe->vgaFile2 < _blockEnd && vpe->vgaFile2End > _block) {
|
||||
_rejectBlock = true;
|
||||
_vgaMemPtr = vpe->vgaFile2End;
|
||||
} else if (vpe->sfxFile && vpe->sfxFile < _blockEnd && vpe->sfxFileEnd > _block) {
|
||||
_rejectBlock = true;
|
||||
_vgaMemPtr = vpe->sfxFileEnd;
|
||||
} else {
|
||||
_rejectBlock = false;
|
||||
}
|
||||
} else {
|
||||
if (_block <= vpe->vgaFile1 && _blockEnd >= vpe->vgaFile1 ||
|
||||
_vgaMemPtr <= vpe->vgaFile2 && _blockEnd >= vpe->vgaFile2) {
|
||||
_rejectBlock = true;
|
||||
_vgaMemPtr = vpe->vgaFile1 + 0x5000;
|
||||
} else {
|
||||
_rejectBlock = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::checkRunningAnims() {
|
||||
VgaSprite *vsp;
|
||||
if (getGameType() != GType_FF && getGameType() != GType_PP && (_lockWord & 0x20)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (vsp = _vgaSprites; vsp->id; vsp++) {
|
||||
checkAnims(vsp->zoneNum);
|
||||
if (_rejectBlock == true)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::checkAnims(uint a) {
|
||||
VgaPointersEntry *vpe;
|
||||
|
||||
vpe = &_vgaBufferPointers[a];
|
||||
|
||||
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
||||
if (vpe->vgaFile1 < _blockEnd && vpe->vgaFile1End > _block) {
|
||||
_rejectBlock = true;
|
||||
_vgaMemPtr = vpe->vgaFile1End;
|
||||
} else if (vpe->vgaFile2 < _blockEnd && vpe->vgaFile2End > _block) {
|
||||
_rejectBlock = true;
|
||||
_vgaMemPtr = vpe->vgaFile2End;
|
||||
} else if (vpe->sfxFile && vpe->sfxFile < _blockEnd && vpe->sfxFileEnd > _block) {
|
||||
_rejectBlock = true;
|
||||
_vgaMemPtr = vpe->sfxFileEnd;
|
||||
} else {
|
||||
_rejectBlock = false;
|
||||
}
|
||||
} else {
|
||||
if (_block <= vpe->vgaFile1 && _blockEnd >= vpe->vgaFile1 ||
|
||||
_block <= vpe->vgaFile2 && _blockEnd >= vpe->vgaFile2) {
|
||||
_rejectBlock = true;
|
||||
_vgaMemPtr = vpe->vgaFile1 + 0x5000;
|
||||
} else {
|
||||
_rejectBlock = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::checkZonePtrs() {
|
||||
uint count = ARRAYSIZE(_vgaBufferPointers);
|
||||
VgaPointersEntry *vpe = _vgaBufferPointers;
|
||||
do {
|
||||
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
||||
if (vpe->vgaFile1 < _blockEnd && vpe->vgaFile1End > _block ||
|
||||
vpe->vgaFile2 < _blockEnd && vpe->vgaFile2End > _block ||
|
||||
vpe->sfxFile < _blockEnd && vpe->sfxFileEnd > _block) {
|
||||
vpe->vgaFile1 = NULL;
|
||||
vpe->vgaFile1End = NULL;
|
||||
vpe->vgaFile2 = NULL;
|
||||
vpe->vgaFile2End = NULL;
|
||||
vpe->sfxFile = NULL;
|
||||
vpe->sfxFileEnd = NULL;
|
||||
}
|
||||
} else {
|
||||
if (_block <= vpe->vgaFile1 && _blockEnd >= vpe->vgaFile1 ||
|
||||
_block <= vpe->vgaFile2 && _blockEnd >= vpe->vgaFile2) {
|
||||
vpe->vgaFile1 = NULL;
|
||||
vpe->vgaFile2 = NULL;
|
||||
}
|
||||
}
|
||||
} while (++vpe, --count);
|
||||
}
|
||||
|
||||
} // End of namespace AGOS
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue