/* 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/system.h" #include "agos/agos.h" #include "agos/intern.h" namespace AGOS { byte *AGOSEngine::getFrontBuf() { _dxSurfacePitch = _screenWidth; return _frontBuf; } byte *AGOSEngine::getBackBuf() { _dxSurfacePitch = _screenWidth; return _useBackGround ? _backGroundBuf : _backBuf; } byte *AGOSEngine::getBackGround() { _dxSurfacePitch = _screenWidth; return _backGroundBuf; } byte *AGOSEngine::getScaleBuf() { _dxSurfacePitch = _screenWidth; return _scaleBuf; } void AGOSEngine::animateSprites() { VgaSprite *vsp; VgaPointersEntry *vpe; const byte *vc_ptr_org = _vcPtr; uint16 params[5]; // parameters to vc10 if (_paletteFlag == 2) _paletteFlag = 1; if (getGameType() == GType_FF && _scrollCount) { scrollEvent(); } if (getGameType() == GType_SIMON2 && _scrollFlag) { scrollScreen(); } if (getGameType() == GType_FF && getBitFlag(84)) { animateSpritesByY(); return; } vsp = _vgaSprites; while (vsp->id != 0) { vsp->windowNum &= 0x7FFF; vpe = &_vgaBufferPointers[vsp->zoneNum]; _curVgaFile1 = vpe->vgaFile1; _curVgaFile2 = vpe->vgaFile2; _curSfxFile = vpe->sfxFile; _windowNum = vsp->windowNum; _vgaCurSpriteId = vsp->id; _vgaCurSpritePriority = vsp->priority; params[0] = readUint16Wrapper(&vsp->image); if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) { params[1] = readUint16Wrapper(&vsp->x); params[2] = readUint16Wrapper(&vsp->y); params[3] = READ_BE_UINT16(&vsp->flags); } else { params[1] = readUint16Wrapper(&vsp->palette); params[2] = readUint16Wrapper(&vsp->x); params[3] = readUint16Wrapper(&vsp->y); if (getGameType() == GType_SIMON1) { params[4] = READ_BE_UINT16(&vsp->flags); } else { *(byte *)(¶ms[4]) = (byte)vsp->flags; } } _vcPtr = (const byte *)params; vc10_draw(); vsp++; } if (_drawImagesDebug) memset(_backBuf, 0, _screenWidth * _screenHeight); _updateScreen = true; _vcPtr = vc_ptr_org; } void AGOSEngine::animateSpritesDebug() { VgaSprite *vsp; VgaPointersEntry *vpe; const byte *vc_ptr_org = _vcPtr; uint16 params[5]; // parameters to vc10_draw if (_paletteFlag == 2) _paletteFlag = 1; vsp = _vgaSprites; while (vsp->id != 0) { vsp->windowNum &= 0x7FFF; vpe = &_vgaBufferPointers[vsp->zoneNum]; _curVgaFile1 = vpe->vgaFile1; _curVgaFile2 = vpe->vgaFile2; _curSfxFile = vpe->sfxFile; _windowNum = vsp->windowNum; _vgaCurSpriteId = vsp->id; if (vsp->image) printf("id:%5d image:%3d base-color:%3d x:%3d y:%3d flags:%x\n", vsp->id, vsp->image, vsp->palette, vsp->x, vsp->y, vsp->flags); params[0] = readUint16Wrapper(&vsp->image); if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) { params[1] = readUint16Wrapper(&vsp->x); params[2] = readUint16Wrapper(&vsp->y); params[3] = READ_BE_UINT16(&vsp->flags); } else { params[1] = readUint16Wrapper(&vsp->palette); params[2] = readUint16Wrapper(&vsp->x); params[3] = readUint16Wrapper(&vsp->y); if (getGameType() == GType_SIMON1) { params[4] = READ_BE_UINT16(&vsp->flags); } else { *(byte *)(¶ms[4]) = (byte)vsp->flags; } } _vcPtr = (const byte *)params; vc10_draw(); vsp++; } _updateScreen = true; _vcPtr = vc_ptr_org; } void AGOSEngine::animateSpritesByY() { VgaSprite *vsp; VgaPointersEntry *vpe; const byte *vc_ptr_org = _vcPtr; uint16 params[5]; // parameters to vc10 int16 spriteTable[180][2]; byte *src; int height, slot, y; uint i, numSprites = 0; vsp = _vgaSprites; while (vsp->id != 0) { if (vsp->flags & kDFScaled) { y = vsp->y; } else if (vsp->flags & kDFMasked) { vpe = &_vgaBufferPointers[vsp->zoneNum]; src = vpe->vgaFile2 + vsp->image * 8; height = READ_LE_UINT16(src + 4) & 0x7FFF; y = vsp->y + height; } else { y = vsp->priority; } spriteTable[numSprites][0] = y; spriteTable[numSprites][1] = numSprites; numSprites++; vsp++; } while (1) { y = spriteTable[0][0]; slot = spriteTable[0][1]; for (i = 0; i < numSprites; i++) { if (y >= spriteTable[i][0]) { y = spriteTable[i][0]; slot = spriteTable[i][1]; } } if (y == 9999) break; for (i = 0; i < numSprites; i++) { if (slot == spriteTable[i][1]) { spriteTable[i][0] = 9999; break; } } vsp = &_vgaSprites[slot]; vsp->windowNum &= 0x7FFF; vpe = &_vgaBufferPointers[vsp->zoneNum]; _curVgaFile1 = vpe->vgaFile1; _curVgaFile2 = vpe->vgaFile2; _curSfxFile = vpe->sfxFile; _windowNum = vsp->windowNum; _vgaCurSpriteId = vsp->id; _vgaCurSpritePriority = vsp->priority; params[0] = readUint16Wrapper(&vsp->image); params[1] = readUint16Wrapper(&vsp->palette); params[2] = readUint16Wrapper(&vsp->x); params[3] = readUint16Wrapper(&vsp->y); *(byte *)(¶ms[4]) = (byte)vsp->flags; _vcPtr = (const byte *)params; vc10_draw(); } _updateScreen = true; _vcPtr = vc_ptr_org; } void AGOSEngine::displayBoxStars() { HitArea *ha, *dha; uint count; uint y_, x_; byte *dst; uint b, color; _lockWord |= 0x8000; if (getGameType() == GType_SIMON2) color = 236; else color = 225; uint limit = (getGameType() == GType_SIMON2) ? 200 : 134; for (int i = 0; i < 5; i++) { ha = _hitAreas; count = ARRAYSIZE(_hitAreas); animateSprites(); do { if (ha->id != 0 && ha->flags & kBFBoxInUse && !(ha->flags & kBFBoxDead)) { dha = _hitAreas; if (ha->flags & kBFTextBox) { while (dha != ha && dha->flags != ha->flags) ++dha; if (dha != ha && dha->flags == ha->flags) continue; } else { dha = _hitAreas; while (dha != ha && dha->item_ptr != ha->item_ptr) ++dha; if (dha != ha && dha->item_ptr == ha->item_ptr) continue; } if (ha->y >= limit || ((getGameType() == GType_SIMON2) && ha->y >= _boxStarHeight)) continue; y_ = (ha->height / 2) - 4 + ha->y; x_ = (ha->width / 2) - 4 + ha->x - (_scrollX * 8); if (x_ >= 311) continue; dst = getBackBuf(); dst += (((_dxSurfacePitch / 4) * y_) * 4) + x_; b = _dxSurfacePitch; dst[4] = color; dst[b+1] = color; dst[b+4] = color; dst[b+7] = color; b += _dxSurfacePitch; dst[b+2] = color; dst[b+4] = color; dst[b+6] = color; b += _dxSurfacePitch; dst[b+3] = color; dst[b+5] = color; b += _dxSurfacePitch; dst[b] = color; dst[b+1] = color; dst[b+2] = color; dst[b+6] = color; dst[b+7] = color; dst[b+8] = color; b += _dxSurfacePitch; dst[b+3] = color; dst[b+5] = color; b += _dxSurfacePitch; dst[b+2] = color; dst[b+4] = color; dst[b+6] = color; b += _dxSurfacePitch; dst[b+1] = color; dst[b+4] = color; dst[b+7] = color; b += _dxSurfacePitch; dst[b+4] = color; } } while (ha++, --count); updateScreen(); delay(100); animateSprites(); updateScreen(); delay(100); } _lockWord &= ~0x8000; } void AGOSEngine::scrollScreen() { byte *dst = getFrontBuf(); const byte *src; uint x, y; if (_scrollXMax == 0) { uint screenSize = 8 * _screenWidth; if (_scrollFlag < 0) { memmove(dst + screenSize, dst, _scrollWidth * _screenHeight - screenSize); } else { memmove(dst, dst + screenSize, _scrollWidth * _screenHeight - screenSize); } y = _scrollY - 8; if (_scrollFlag > 0) { dst += _screenHeight * _screenWidth - screenSize; y += 488; } src = _scrollImage + y / 2; decodeRow(dst, src + readUint32Wrapper(src), _scrollWidth); _scrollY += _scrollFlag; vcWriteVar(250, _scrollY); memcpy(_backBuf, _frontBuf, _screenWidth * _screenHeight); memcpy(_backGroundBuf, _backBuf, _screenHeight * _scrollWidth); } else { if (_scrollFlag < 0) { memmove(dst + 8, dst, _screenWidth * _scrollHeight - 8); } else { memmove(dst, dst + 8, _screenWidth * _scrollHeight - 8); } x = _scrollX; x -= (getGameType() == GType_FF) ? 8 : 1; if (_scrollFlag > 0) { dst += _screenWidth - 8; x += (getGameType() == GType_FF) ? 648 : 41; } if (getGameType() == GType_FF) src = _scrollImage + x / 2; else src = _scrollImage + x * 4; decodeColumn(dst, src + readUint32Wrapper(src), _scrollHeight); _scrollX += _scrollFlag; vcWriteVar(251, _scrollX); memcpy(_backBuf, _frontBuf, _screenWidth * _screenHeight); memcpy(_backGroundBuf, _backBuf, _scrollHeight * _screenWidth); } _scrollFlag = 0; } void AGOSEngine::clearBackFromTop(uint lines) { memset(_backBuf, 0, lines * _screenWidth); } void AGOSEngine::clearSurfaces(uint num_lines) { memset(_backBuf, 0, num_lines * _screenWidth); _system->copyRectToScreen(_backBuf, _screenWidth, 0, 0, _screenWidth, num_lines); if (_useBackGround) { memset(_frontBuf, 0, num_lines * _screenWidth); memset(_backGroundBuf, 0, num_lines * _screenWidth); } } void AGOSEngine::fillFrontFromBack(uint x, uint y, uint w, uint h) { uint offs = x + y * _screenWidth; byte *s = _backBuf + offs; byte *d = _frontBuf + offs; do { memcpy(d, s, w); d += _screenWidth; s += _screenWidth; } while (--h); } void AGOSEngine::fillBackFromFront(uint x, uint y, uint w, uint h) { uint offs = x + y * _screenWidth; byte *s = _frontBuf + offs; byte *d = _backBuf + offs; do { memcpy(d, s, w); d += _screenWidth; s += _screenWidth; } while (--h); } void AGOSEngine::fillBackGroundFromBack(uint lines) { memcpy(_backGroundBuf, _backBuf, lines * _screenWidth); } void AGOSEngine::updateScreen() { if (_fastFadeInFlag == 0 && _paletteFlag == 1) { _paletteFlag = 0; if (memcmp(_displayPalette, _currentPalette, 1024)) { memcpy(_currentPalette, _displayPalette, 1024); _system->setPalette(_displayPalette, 0, 256); } } _system->copyRectToScreen(_backBuf, _screenWidth, 0, 0, _screenWidth, _screenHeight); _system->updateScreen(); if (getGameId() != GID_DIMP) memcpy(_backBuf, _frontBuf, _screenWidth * _screenHeight); if (getGameType() == GType_FF && _scrollFlag) { scrollScreen(); } if (_fastFadeInFlag) { if (getGameType() == GType_SIMON1 && _usePaletteDelay) { delay(100); _usePaletteDelay = false; } fastFadeIn(); } } void AGOSEngine::fastFadeIn() { if (_fastFadeInFlag & 0x8000) { slowFadeIn(); } else { _paletteFlag = false; memcpy(_currentPalette, _displayPalette, 1024); _system->setPalette(_displayPalette, 0, _fastFadeInFlag); _fastFadeInFlag = 0; } } void AGOSEngine::slowFadeIn() { uint8 *src, *dst; int c, p; _fastFadeInFlag &= 0x7fff; _paletteFlag = false; memset(_videoBuf1, 0, 1024); memcpy(_currentPalette, _displayPalette, 1024); memcpy(_videoBuf1 + 1024, _displayPalette, 1024); for (c = 255; c >= 0; c -= 4) { src = _videoBuf1 + 1024; dst = _videoBuf1; for (p = _fastFadeInFlag; p !=0 ; p -= 3) { if (src[0] >= c) dst[0] += 4; if (src[1] >= c) dst[1] += 4; if (src[2] >= c) dst[2] += 4; src += 4; dst += 4; } _system->setPalette(_videoBuf1, 0, _fastFadeCount); delay(5); } _fastFadeInFlag = 0; } } // End of namespace AGOS