/* 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" #include "agos/intern.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