scummvm/engines/agos/icons.cpp
2014-02-18 02:39:32 +01:00

1123 lines
27 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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.
*
*/
#include "common/file.h"
#include "common/system.h"
#include "common/textconsole.h"
#include "graphics/surface.h"
#include "agos/agos.h"
namespace AGOS {
void AGOSEngine::loadIconFile() {
Common::File in;
uint32 srcSize;
in.open(getFileName(GAME_ICONFILE));
if (in.isOpen() == false)
error("Can't open icons file '%s'", getFileName(GAME_ICONFILE));
srcSize = in.size();
if (getGameType() == GType_WW && getPlatform() == Common::kPlatformAmiga) {
byte *srcBuf = (byte *)malloc(srcSize);
in.read(srcBuf, srcSize);
uint32 dstSize = READ_BE_UINT32(srcBuf + srcSize - 4);
_iconFilePtr = (byte *)malloc(dstSize);
if (_iconFilePtr == NULL)
error("Out of icon memory");
decrunchFile(srcBuf, _iconFilePtr, srcSize);
free(srcBuf);
} else if (getGameType() == GType_PN && getPlatform() == Common::kPlatformAtariST) {
// The icon data is hard coded in the program file.
_iconFilePtr = (byte *)malloc(15038);
if (_iconFilePtr == NULL)
error("Out of icon memory");
in.seek(48414);
in.read(_iconFilePtr, 15038);
} else {
_iconFilePtr = (byte *)malloc(srcSize);
if (_iconFilePtr == NULL)
error("Out of icon memory");
in.read(_iconFilePtr, srcSize);
}
in.close();
}
void AGOSEngine::loadIconData() {
loadZone(8);
VgaPointersEntry *vpe = &_vgaBufferPointers[8];
byte *src = vpe->vgaFile2 + READ_LE_UINT32(vpe->vgaFile2 + 8);
_iconFilePtr = (byte *)malloc(43 * 336);
if (_iconFilePtr == NULL)
error("Out of icon memory");
memcpy(_iconFilePtr, src, 43 * 336);
unfreezeBottom();
}
// Thanks to Stuart Caie for providing the original
// C conversion upon which this function is based.
static void decompressIconPlanar(byte *dst, byte *src, uint width, uint height, byte base, uint pitch, bool decompress = true) {
byte *i, *icon_pln, *o, *srcPtr;
byte x, y;
icon_pln = 0;
srcPtr = src;
if (decompress) {
icon_pln = (byte *)calloc(width * height, 1);
// Decode RLE planar icon data
i = src;
o = icon_pln;
while (o < &icon_pln[width * height]) {
x = *i++;
if (x < 128) {
do {
*o++ = *i++;
*o++ = *i++;
*o++ = *i++;
} while (x-- > 0);
} else {
x = 256 - x;
do {
*o++ = i[0];
*o++ = i[1];
*o++ = i[2];
} while (x-- > 0);
i += 3;
}
}
srcPtr = icon_pln;
}
// Translate planar data to chunky (very slow method)
for (y = 0; y < height * 2; y++) {
for (x = 0; x < width; x++) {
byte pixel =
(srcPtr[((height * 0 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 1 : 0)
| (srcPtr[((height * 2 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 2 : 0)
| (srcPtr[((height * 4 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 4 : 0)
| (srcPtr[((height * 6 + y) * 3) + (x >> 3)] & (1 << (7 - (x & 7))) ? 8 : 0);
if (pixel)
dst[x] = pixel | base;
}
dst += pitch;
}
free(icon_pln);
}
static void decompressIcon(byte *dst, byte *src, uint width, uint height, byte base, uint pitch) {
int8 reps;
byte color_1, color_2;
byte *dst_org = dst;
uint h = height;
for (;;) {
reps = *src++;
if (reps < 0) {
reps--;
color_1 = *src >> 4;
if (color_1 != 0)
color_1 |= base;
color_2 = *src++ & 0xF;
if (color_2 != 0)
color_2 |= base;
do {
if (color_1 != 0)
*dst = color_1;
dst += pitch;
if (color_2 != 0)
*dst = color_2;
dst += pitch;
// reached bottom?
if (--h == 0) {
// reached right edge?
if (--width == 0)
return;
dst = ++dst_org;
h = height;
}
} while (++reps != 0);
} else {
do {
color_1 = *src >> 4;
if (color_1 != 0)
*dst = color_1 | base;
dst += pitch;
color_2 = *src++ & 0xF;
if (color_2 != 0)
*dst = color_2 | base;
dst += pitch;
// reached bottom?
if (--h == 0) {
// reached right edge?
if (--width == 0)
return;
dst = ++dst_org;
h = height;
}
} while (--reps >= 0);
}
}
}
void AGOSEngine_Simon2::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
byte *dst;
byte *src;
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
dst = (byte *)screen->getPixels();
dst += 110;
dst += x;
dst += (y + window->y) * screen->pitch;
src = _iconFilePtr;
src += READ_LE_UINT16(src + icon * 4 + 0);
decompressIcon(dst, src, 20, 10, 224, screen->pitch);
src = _iconFilePtr;
src += READ_LE_UINT16(src + icon * 4 + 2);
decompressIcon(dst, src, 20, 10, 208, screen->pitch);
_system->unlockScreen();
_videoLockOut &= ~0x8000;
}
void AGOSEngine_Simon1::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
byte *dst;
byte *src;
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
dst += (y * 25 + window->y) * screen->pitch;
if (getPlatform() == Common::kPlatformAmiga) {
src = _iconFilePtr;
src += READ_BE_UINT32(src + icon * 4);
uint8 color = (getFeatures() & GF_32COLOR) ? 224 : 240;
decompressIconPlanar(dst, src, 24, 12, color, screen->pitch);
} else {
src = _iconFilePtr;
src += READ_LE_UINT16(src + icon * 2);
decompressIcon(dst, src, 24, 12, 224, screen->pitch);
}
_system->unlockScreen();
_videoLockOut &= ~0x8000;
}
void AGOSEngine_Waxworks::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
byte *dst;
byte *src;
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
dst += (y * 20 + window->y) * screen->pitch;
uint8 color = dst[0] & 0xF0;
if (getPlatform() == Common::kPlatformAmiga) {
src = _iconFilePtr;
src += READ_BE_UINT32(src + icon * 4);
decompressIconPlanar(dst, src, 24, 10, color, screen->pitch);
} else {
src = _iconFilePtr;
src += READ_LE_UINT16(src + icon * 2);
decompressIcon(dst, src, 24, 10, color, screen->pitch);
}
_system->unlockScreen();
_videoLockOut &= ~0x8000;
}
void AGOSEngine_Elvira2::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
byte *dst;
byte *src;
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
dst += (y * 8 + window->y) * screen->pitch;
uint color = dst[0] & 0xF0;
if (getFeatures() & GF_PLANAR) {
src = _iconFilePtr;
src += READ_BE_UINT32(src + icon * 4);
decompressIconPlanar(dst, src, 24, 12, color, screen->pitch);
} else {
src = _iconFilePtr;
src += READ_LE_UINT16(src + icon * 2);
decompressIcon(dst, src, 24, 12, color, screen->pitch);
}
_system->unlockScreen();
_videoLockOut &= ~0x8000;
}
void AGOSEngine_Elvira1::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
byte *dst;
byte *src;
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
dst += (y * 8 + window->y) * screen->pitch;
if (getFeatures() & GF_PLANAR) {
src = _iconFilePtr;
src += READ_BE_UINT16(src + icon * 2);
decompressIconPlanar(dst, src, 24, 12, 16, screen->pitch);
} else {
src = _iconFilePtr;
src += icon * 288;
decompressIconPlanar(dst, src, 24, 12, 16, screen->pitch, false);
}
_system->unlockScreen();
_videoLockOut &= ~0x8000;
}
void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
byte *dst;
byte *src;
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
dst = (byte *)screen->getBasePtr(x * 8, y);
src = _iconFilePtr + icon * 146;
if (icon == 0xFF) {
// Draw Blank Icon
for (int yp = 0; yp < 24; yp++) {
memset(dst, 0, 24);
dst += screen->pitch;
}
} else {
uint8 palette[4];
palette[0] = *src >> 4;
palette[1] = *src++ & 0xf;
palette[2] = *src >> 4;
palette[3] = *src++ & 0xf;
for (int yp = 0; yp < 24; ++yp, src += 6) {
// Get bit-set representing the 24 pixels for the line
uint32 v1 = (READ_BE_UINT16(src) << 8) | *(src + 4);
uint32 v2 = (READ_BE_UINT16(src + 2) << 8) | *(src + 5);
for (int xp = 0; xp < 24; ++xp, v1 >>= 1, v2 >>= 1) {
dst[yp * screen->pitch + (23 - xp)] = palette[((v1 & 1) << 1) | (v2 & 1)];
}
}
}
_system->unlockScreen();
_videoLockOut &= ~0x8000;
}
#ifdef ENABLE_AGOS2
void AGOSEngine_Feeble::drawIconArray(uint num, Item *itemRef, int line, int classMask) {
Item *item_ptr_org = itemRef;
WindowBlock *window;
uint16 flagnumber = 201;
uint16 iconperline = 458;
uint16 iconsdown = 384;
uint16 idone = 0;
uint16 icount = 0;
uint16 xp = 188, yp = 306;
int k;
_iOverflow = 0;
line = _variableArray[30];
if (line == 0)
_variableArray[31] = 0;
window = _windowArray[num & 7];
if (window == NULL)
return;
for (k = flagnumber; k <= flagnumber + 18; k++)
_variableArray[k] = 0;
if (window->iconPtr)
removeIconArray(num);
window->iconPtr=(IconBlock *)malloc(sizeof(IconBlock));
window->iconPtr->itemRef = itemRef;
window->iconPtr->upArrow = -1;
window->iconPtr->downArrow = -1;
window->iconPtr->line = line;
window->iconPtr->classMask = classMask;
itemRef = derefItem(itemRef->child);
k = flagnumber;
while (itemRef && (line > 65)) {
uint16 ct = xp;
while (itemRef && ct < iconperline) {
if ((classMask == 0) || ((itemRef->classFlags & classMask) != 0)) {
if (hasIcon(itemRef)) {
ct += 45;
k++;
}
}
itemRef = derefItem(itemRef->next);
}
line -= 52;
if (k == (flagnumber + 18))
k = flagnumber;
}
yp -= line; // Adjust starting y
if (itemRef == NULL) {
window->iconPtr->line = 0;
itemRef = derefItem(item_ptr_org->child);
}
while (itemRef) {
if ((classMask != 0) && ((itemRef->classFlags & classMask) == 0))
goto l1;
if (hasIcon(itemRef) == 0)
goto l1;
if (!idone) {
/*
* Create thee icon and graphics rendering
*/
window->iconPtr->iconArray[icount].item = itemRef;
_variableArray[k] = itemGetIconNumber(itemRef);
window->iconPtr->iconArray[icount++].boxCode =
setupIconHitArea(window, k++, xp, yp, itemRef);
} else {
/*
* Just remember the overflow has occurred
*/
window->iconPtr->iconArray[icount].item = NULL; /* END MARKINGS */
_iOverflow = 1;
}
xp += 45;
if (xp >= iconperline) { /* End of line ? */
if (k == (flagnumber + 18))
k = flagnumber;
xp = 188;
yp += 52; /* Move down */
if (yp >= iconsdown) { /* Full ? */
idone = 1; /* Note completed screen */
}
}
l1:; itemRef = derefItem(itemRef->next);
}
window->iconPtr->iconArray[icount].item = NULL; /* END MARKINGS */
if (_variableArray[30] == 0) {
if (yp != 306)
_variableArray[31] = 52;
if ((xp == 188) && (yp == 358))
_variableArray[31] = 0;
}
/* Plot arrows and add their boxes */
addArrows(window, num);
window->iconPtr->upArrow = _scrollUpHitArea;
window->iconPtr->downArrow = _scrollDownHitArea;
}
#endif
void AGOSEngine::drawIconArray(uint num, Item *itemRef, int line, int classMask) {
Item *item_ptr_org = itemRef;
WindowBlock *window;
uint width, height;
uint k, curWidth;
bool item_again, showArrows;
uint x_pos, y_pos;
const int iconSize = (getGameType() == GType_SIMON2) ? 20 : 1;
window = _windowArray[num & 7];
if (getGameType() == GType_SIMON2) {
width = 100;
height = 40;
} else if (getGameType() == GType_WW) {
width = window->width / 3;
height = window->height / 2;
} else {
width = window->width / 3;
height = window->height / 3;
}
if (window == NULL)
return;
if (window->iconPtr)
removeIconArray(num);
window->iconPtr = (IconBlock *) malloc(sizeof(IconBlock));
window->iconPtr->itemRef = itemRef;
window->iconPtr->upArrow = -1;
window->iconPtr->downArrow = -1;
window->iconPtr->line = line;
window->iconPtr->classMask = classMask;
itemRef = derefItem(itemRef->child);
while (itemRef && line-- != 0) {
curWidth = 0;
while (itemRef && width > curWidth) {
if ((classMask == 0 || itemRef->classFlags & classMask) && hasIcon(itemRef))
curWidth += iconSize;
itemRef = derefItem(itemRef->next);
}
}
if (itemRef == NULL) {
window->iconPtr->line = 0;
itemRef = derefItem(item_ptr_org->child);
}
x_pos = 0;
y_pos = 0;
k = 0;
item_again = false;
showArrows = false;
while (itemRef) {
if ((classMask == 0 || itemRef->classFlags & classMask) && hasIcon(itemRef)) {
if (item_again == false) {
window->iconPtr->iconArray[k].item = itemRef;
if (getGameType() == GType_SIMON2) {
drawIcon(window, itemGetIconNumber(itemRef), x_pos, y_pos);
window->iconPtr->iconArray[k].boxCode =
setupIconHitArea(window, 0, x_pos, y_pos, itemRef);
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_WW) {
drawIcon(window, itemGetIconNumber(itemRef), x_pos * 3, y_pos);
window->iconPtr->iconArray[k].boxCode =
setupIconHitArea(window, 0, x_pos * 3, y_pos, itemRef);
} else {
drawIcon(window, itemGetIconNumber(itemRef), x_pos * 3, y_pos * 3);
window->iconPtr->iconArray[k].boxCode =
setupIconHitArea(window, 0, x_pos * 3, y_pos * 3, itemRef);
}
k++;
} else {
window->iconPtr->iconArray[k].item = NULL;
showArrows = 1;
}
x_pos += iconSize;
if (x_pos >= width) {
x_pos = 0;
y_pos += iconSize;
if (y_pos >= height)
item_again = true;
}
}
itemRef = derefItem(itemRef->next);
}
window->iconPtr->iconArray[k].item = NULL;
if (showArrows != 0 || window->iconPtr->line != 0) {
/* Plot arrows and add their boxes */
addArrows(window, num);
window->iconPtr->upArrow = _scrollUpHitArea;
window->iconPtr->downArrow = _scrollDownHitArea;
}
}
#ifdef ENABLE_AGOS2
uint AGOSEngine_Feeble::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
HitArea *ha = findEmptyHitArea();
ha->x = x;
ha->y = y;
ha->itemPtr = itemPtr;
ha->width = 45;
ha->height = 44;
ha->flags = kBFBoxInUse | kBFBoxItem;
ha->id = num;
ha->priority = 100;
ha->verb = 208;
return ha - _hitAreas;
}
#endif
uint AGOSEngine_Simon2::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
HitArea *ha = findEmptyHitArea();
ha->x = x + 110;
ha->y = window->y + y;
ha->itemPtr = itemPtr;
ha->width = 20;
ha->height = 20;
ha->flags = kBFDragBox | kBFBoxInUse | kBFBoxItem;
ha->id = 0x7FFD;
ha->priority = 100;
ha->verb = 208;
return ha - _hitAreas;
}
uint AGOSEngine_Simon1::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
HitArea *ha = findEmptyHitArea();
ha->x = (x + window->x) * 8;
ha->y = y * 25 + window->y;
ha->itemPtr = itemPtr;
ha->width = 24;
ha->height = 24;
ha->flags = kBFDragBox | kBFBoxInUse | kBFBoxItem;
ha->id = 0x7FFD;
ha->priority = 100;
ha->verb = 208;
return ha - _hitAreas;
}
uint AGOSEngine_Waxworks::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
HitArea *ha = findEmptyHitArea();
ha->x = (x + window->x) * 8;
ha->y = y * 20 + window->y;
ha->itemPtr = itemPtr;
ha->width = 24;
ha->height = 20;
ha->flags = kBFDragBox | kBFBoxInUse | kBFBoxItem;
ha->id = 0x7FFD;
ha->priority = 100;
ha->verb = 208;
return ha - _hitAreas;
}
uint AGOSEngine_Elvira2::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
HitArea *ha = findEmptyHitArea();
ha->x = (x + window->x) * 8;
ha->y = y * 8 + window->y;
ha->itemPtr = itemPtr;
ha->width = 24;
ha->height = 24;
ha->id = 0x7FFD;
ha->priority = 100;
if (window->iconPtr->classMask == 2) {
ha->flags = kBFDragBox | kBFBoxInUse;
ha->verb = 248 + 0x4000;
} else {
ha->flags = kBFDragBox | kBFBoxInUse | kBFBoxItem;
ha->verb = 208;
}
return ha - _hitAreas;
}
uint AGOSEngine::setupIconHitArea(WindowBlock *window, uint num, uint x, uint y, Item *itemPtr) {
HitArea *ha = findEmptyHitArea();
ha->x = (x + window->x) * 8;
ha->y = y * 8 + window->y;
ha->itemPtr = itemPtr;
ha->width = 24;
ha->height = 24;
ha->flags = kBFDragBox | kBFBoxInUse | kBFBoxItem;
ha->id = 0x7FFD;
ha->priority = 100;
ha->verb = 253;
return ha - _hitAreas;
}
#ifdef ENABLE_AGOS2
void AGOSEngine_Feeble::addArrows(WindowBlock *window, uint8 num) {
HitArea *ha;
ha = findEmptyHitArea();
_scrollUpHitArea = ha - _hitAreas;
ha->x = 496;
ha->y = 279;
ha->width = 30;
ha->height = 45;
ha->flags = kBFBoxInUse | kBFNoTouchName;
ha->id = 0x7FFB;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
ha = findEmptyHitArea();
_scrollDownHitArea = ha - _hitAreas;
ha->x = 496;
ha->y = 324;
ha->width = 30;
ha->height = 44;
ha->flags = kBFBoxInUse | kBFNoTouchName;
ha->id = 0x7FFC;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
}
#endif
void AGOSEngine_Simon2::addArrows(WindowBlock *window, uint8 num) {
HitArea *ha;
ha = findEmptyHitArea();
_scrollUpHitArea = ha - _hitAreas;
ha->x = 81;
ha->y = 158;
ha->width = 12;
ha->height = 26;
ha->flags = kBFBoxInUse | kBFNoTouchName;
ha->id = 0x7FFB;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
ha = findEmptyHitArea();
_scrollDownHitArea = ha - _hitAreas;
ha->x = 227;
ha->y = 162;
ha->width = 12;
ha->height = 26;
ha->flags = kBFBoxInUse | kBFNoTouchName;
ha->id = 0x7FFC;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
}
void AGOSEngine_Simon1::addArrows(WindowBlock *window, uint8 num) {
HitArea *ha;
ha = findEmptyHitArea();
_scrollUpHitArea = ha - _hitAreas;
ha->x = 308;
ha->y = 149;
ha->width = 12;
ha->height = 17;
ha->flags = kBFBoxInUse | kBFNoTouchName;
ha->id = 0x7FFB;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
ha = findEmptyHitArea();
_scrollDownHitArea = ha - _hitAreas;
ha->x = 308;
ha->y = 176;
ha->width = 12;
ha->height = 17;
ha->flags = kBFBoxInUse | kBFNoTouchName;
ha->id = 0x7FFC;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
_videoLockOut |= 0x8;
VgaPointersEntry *vpe = &_vgaBufferPointers[1];
byte *curVgaFile2Orig = _curVgaFile2;
uint16 windowNumOrig = _windowNum;
uint8 palette = (getPlatform() == Common::kPlatformAmiga) ? 15 : 14;
_windowNum = 0;
_curVgaFile2 = vpe->vgaFile2;
drawImage_init(1, palette, 38, 150, 4);
_curVgaFile2 = curVgaFile2Orig;
_windowNum = windowNumOrig;
_videoLockOut &= ~0x8;
}
void AGOSEngine_Waxworks::addArrows(WindowBlock *window, uint8 num) {
HitArea *ha;
ha = findEmptyHitArea();
_scrollUpHitArea = ha - _hitAreas;
setBitFlag(22, true);
ha->x = 255;
ha->y = 153;
ha->width = 9;
ha->height = 11;
ha->flags = kBFBoxInUse | kBFNoTouchName;
ha->id = 0x7FFB;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
ha = findEmptyHitArea();
_scrollDownHitArea = ha - _hitAreas;
ha->x = 255;
ha->y = 170;
ha->width = 9;
ha->height = 11;
ha->flags = kBFBoxInUse | kBFNoTouchName;
ha->id = 0x7FFC;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
setWindowImageEx(6, 103);
}
void AGOSEngine_Elvira2::addArrows(WindowBlock *window, uint8 num) {
HitArea *ha;
ha = findEmptyHitArea();
_scrollUpHitArea = ha - _hitAreas;
setBitFlag(21, true);
ha->x = 54;
ha->y = 154;
ha->width = 12;
ha->height = 10;
ha->flags = kBFBoxInUse;
ha->id = 0x7FFB;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
ha = findEmptyHitArea();
_scrollDownHitArea = ha - _hitAreas;
ha->x = 54;
ha->y = 178;
ha->width = 12;
ha->height = 10;
ha->flags = kBFBoxInUse;
ha->id = 0x7FFC;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
setWindowImageEx(6, 106);
}
void AGOSEngine::addArrows(WindowBlock *window, uint8 num) {
HitArea *ha;
uint16 x, y;
x = 30;
y = 151;
if (num != 2) {
y = window->y + window->height * 4 - 19;
x = window->x + window->width;
}
drawArrow(x, y, 16);
ha = findEmptyHitArea();
_scrollUpHitArea = ha - _hitAreas;
ha->x = x * 8;
ha->y = y;
ha->width = 16;
ha->height = 19;
ha->flags = kBFBoxInUse;
ha->id = 0x7FFB;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
x = 30;
y = 170;
if (num != 2) {
y = window->y + window->height * 4;
x = window->x + window->width;
}
drawArrow(x, y, -16);
ha = findEmptyHitArea();
_scrollDownHitArea = ha - _hitAreas;
ha->x = x * 8;
ha->y = y;
ha->width = 16;
ha->height = 19;
ha->flags = kBFBoxInUse;
ha->id = 0x7FFC;
ha->priority = 100;
ha->window = window;
ha->verb = 1;
}
static const byte _arrowImage[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b,
0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a,
0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d,
0x03, 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d, 0x03,
0x04, 0x03, 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00,
0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d, 0x03, 0x04,
0x0f, 0x04, 0x03, 0x0d, 0x0a, 0x0b, 0x0a, 0x00,
0x00, 0x0a, 0x0b, 0x0a, 0x0d, 0x0d, 0x0d, 0x03,
0x04, 0x03, 0x0d, 0x0d, 0x0d, 0x0a, 0x0b, 0x0a,
0x00, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x0d,
0x03, 0x0d, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b,
0x00, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0d,
0x0d, 0x0d, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x00, 0x0a, 0x0a, 0x0a, 0x0e, 0x0b, 0x0b, 0x0c,
0x0e, 0x0c, 0x0b, 0x0b, 0x0e, 0x0a, 0x0a, 0x0a,
0x00, 0x00, 0x02, 0x02, 0x0a, 0x0b, 0x0a, 0x0d,
0x0d, 0x0d, 0x0a, 0x0b, 0x0a, 0x02, 0x02, 0x00,
0x00, 0x00, 0x00, 0x02, 0x0a, 0x0b, 0x0b, 0x0c,
0x0e, 0x0c, 0x0b, 0x0b, 0x0a, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0a, 0x0d,
0x0d, 0x0d, 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0b, 0x0c,
0x0e, 0x0c, 0x0b, 0x0b, 0x0a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x0a, 0x0a,
0x0e, 0x0a, 0x0a, 0x0e, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
};
void AGOSEngine::drawArrow(uint16 x, uint16 y, int8 dir) {
const byte *src;
uint8 w, h;
if (dir < 0) {
src = _arrowImage + 288;
} else {
src = _arrowImage;
}
Graphics::Surface *screen = _system->lockScreen();
byte *dst = (byte *)screen->getBasePtr(x * 8, y);
for (h = 0; h < 19; h++) {
for (w = 0; w < 16; w++) {
if (src[w])
dst[w] = src[w] + 16;
}
src += dir;
dst+= screen->pitch;
}
_system->unlockScreen();
}
void AGOSEngine_Simon1::removeArrows(WindowBlock *window, uint num) {
if (getGameType() == GType_SIMON1) {
restoreBlock(304, 146, 320, 200);
}
}
void AGOSEngine_Waxworks::removeArrows(WindowBlock *window, uint num) {
setBitFlag(22, false);
setWindowImageEx(6, 103);
}
void AGOSEngine_Elvira2::removeArrows(WindowBlock *window, uint num) {
setBitFlag(21, false);
setWindowImageEx(6, 106);
}
void AGOSEngine::removeArrows(WindowBlock *window, uint num) {
if (num != 2) {
uint y = window->y + window->height * 4 - 19;
uint x = (window->x + window->width) * 8;
restoreBlock(x, y, x + 16, y + 38);
} else {
colorBlock(window, 240, 151, 16, 38);
}
}
void AGOSEngine::removeIconArray(uint num) {
WindowBlock *window;
uint16 curWindow;
uint16 i;
window = _windowArray[num & 7];
curWindow = _curWindow;
if (window == NULL || window->iconPtr == NULL)
return;
if (getGameType() != GType_FF && getGameType() != GType_PP) {
changeWindow(num);
sendWindow(12);
changeWindow(curWindow);
}
for (i = 0; window->iconPtr->iconArray[i].item != NULL; i++) {
freeBox(window->iconPtr->iconArray[i].boxCode);
}
if (window->iconPtr->upArrow != -1) {
freeBox(window->iconPtr->upArrow);
}
if (window->iconPtr->downArrow != -1) {
freeBox(window->iconPtr->downArrow);
removeArrows(window, num);
}
free(window->iconPtr);
window->iconPtr = NULL;
_fcsData1[num] = 0;
_fcsData2[num] = 0;
}
static const byte hitBarData[12 * 7] = {
0x3C, 0x00, 0x80, 0x00, 0x88, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00,
0x20, 0x00, 0x04, 0x00, 0xD8, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00, 0x00,
0x20, 0x89, 0x8E, 0x00, 0xA8, 0x86, 0x10, 0x04, 0x08, 0x21, 0x88, 0x00,
0x38, 0x50, 0x84, 0x00, 0x89, 0x49, 0x28, 0x04, 0x08, 0x52, 0x14, 0x00,
0x20, 0x20, 0x84, 0x00, 0x89, 0x48, 0x38, 0x04, 0x08, 0x53, 0x9C, 0x00,
0x20, 0x50, 0x84, 0x00, 0x89, 0x48, 0x20, 0x04, 0x48, 0x50, 0x90, 0x00,
0x3C, 0x89, 0xC3, 0x00, 0x88, 0x88, 0x18, 0x03, 0x86, 0x23, 0x0C, 0x00
};
// Personal Nightmare specific
void AGOSEngine_PN::drawIconHitBar() {
Graphics::Surface *screen = _system->lockScreen();
byte *dst = (byte *)screen->getBasePtr(6 * 8, 3);
const byte *src = hitBarData;
uint8 color = (getPlatform() == Common::kPlatformDOS) ? 7 : 15;
for (int h = 0; h < 7; h++) {
for (int w = 0; w < 12; w++) {
int8 b = *src++;
for (int i = 0; i < 8; i++) {
if (b < 0) {
dst[w * 8 + i] = color;
}
b <<= 1;
}
}
dst += screen->pitch;
}
_system->unlockScreen();
}
void AGOSEngine_PN::iconPage() {
_objectCountS = -1;
mouseOff();
uint8 objRoom = getptr(_quickptr[12] + _variableArray[210] * _quickshort[5] + 20);
uint8 iconNum = getptr(_quickptr[0] + objRoom * _quickshort[0] + 4);
drawIcon(NULL, iconNum, 6, 12);
HitArea *ha = _invHitAreas + 5;
for (uint8 r = 0; r < 5; r++) {
for (uint8 i = 0; i < 7; i++) {
printIcon(ha, i, r);
ha++;
}
}
mouseOn();
}
bool AGOSEngine_PN::ifObjectInInv(uint16 a) {
return _variableArray[210] == getptr(_quickptr[11] + a * _quickshort[4] + 2);
}
bool AGOSEngine_PN::testContainer(uint16 a) {
return bitextract(_quickptr[1] + a * _quickshort[1], 0) != 0;
}
bool AGOSEngine_PN::testObvious(uint16 a) {
return bitextract(_quickptr[1] + a * _quickshort[1], 4) != 0;
}
bool AGOSEngine_PN::testSeen(uint16 a) {
return bitextract(_quickptr[1] + a * _quickshort[1], 3) != 0;
}
void AGOSEngine_PN::printIcon(HitArea *ha, uint8 i, uint8 r) {
if (_objects == _objectCountS) {
ha->flags |= kOBFBoxDisabled;
drawIcon(NULL, 0xFF, 12 + i * 3, 12 + 24 * r);
} else {
_objectCountS++;
if (!ifObjectInInv(_objectCountS) || !testObvious(_objectCountS)) {
printIcon(ha, i, r);
} else {
uint8 iconNum = getptr(_quickptr[0] + _objectCountS * _quickshort[0] + 4);
drawIcon(NULL, iconNum, 12 + i * 3, 12 + 24 * r);
ha->msg1 = _objectCountS | 0x8000;
ha->flags &= ~kOBFBoxDisabled;
}
}
}
} // End of namespace AGOS