Initial commit
This commit is contained in:
733
engines/kyra/engine/scene_rpg.cpp
Normal file
733
engines/kyra/engine/scene_rpg.cpp
Normal file
@@ -0,0 +1,733 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(ENABLE_EOB) || defined(ENABLE_LOL)
|
||||
|
||||
#include "kyra/engine/kyra_rpg.h"
|
||||
#include "kyra/resource/resource.h"
|
||||
#include "kyra/engine/timer.h"
|
||||
#include "kyra/sound/sound.h"
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
void KyraRpgEngine::setLevelShapesDim(int index, int16 &x1, int16 &x2, int dim) {
|
||||
if (_lvlShapeLeftRight[index << 1] == -1) {
|
||||
x1 = 0;
|
||||
x2 = 22;
|
||||
|
||||
int16 y1 = 0;
|
||||
int16 y2 = 120;
|
||||
|
||||
int m = index * 18;
|
||||
|
||||
for (int i = 0; i < 18; i++) {
|
||||
uint8 d = _visibleBlocks[i]->walls[_sceneDrawVarDown];
|
||||
uint8 a = _wllWallFlags[d];
|
||||
|
||||
if (a & 8) {
|
||||
int t = _dscDim2[(m + i) << 1];
|
||||
|
||||
if (t > x1) {
|
||||
x1 = t;
|
||||
if (!(a & 0x10))
|
||||
setDoorShapeDim(index, y1, y2, -1);
|
||||
}
|
||||
|
||||
t = _dscDim2[((m + i) << 1) + 1];
|
||||
|
||||
if (t < x2) {
|
||||
x2 = t;
|
||||
if (!(a & 0x10))
|
||||
setDoorShapeDim(index, y1, y2, -1);
|
||||
}
|
||||
} else {
|
||||
int t = _dscDim1[m + i];
|
||||
|
||||
if (!_wllVmpMap[d] || t == -40)
|
||||
continue;
|
||||
|
||||
if (t == -41) {
|
||||
x1 = 22;
|
||||
x2 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (t > 0 && x2 > t)
|
||||
x2 = t;
|
||||
|
||||
if (t < 0 && x1 < -t)
|
||||
x1 = -t;
|
||||
}
|
||||
|
||||
if (x2 < x1)
|
||||
break;
|
||||
}
|
||||
|
||||
x1 += (_sceneXoffset >> 3);
|
||||
x2 += (_sceneXoffset >> 3);
|
||||
|
||||
_lvlShapeTop[index] = y1;
|
||||
_lvlShapeBottom[index] = y2;
|
||||
_lvlShapeLeftRight[index << 1] = x1;
|
||||
_lvlShapeLeftRight[(index << 1) + 1] = x2;
|
||||
} else {
|
||||
x1 = _lvlShapeLeftRight[index << 1];
|
||||
x2 = _lvlShapeLeftRight[(index << 1) + 1];
|
||||
}
|
||||
|
||||
drawLevelModifyScreenDim(dim, x1, 0, x2, 15);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::setDoorShapeDim(int index, int16 &y1, int16 &y2, int dim) {
|
||||
uint8 a = _dscDimMap[index];
|
||||
|
||||
if (_flags.gameID != GI_EOB1 && dim == -1 && a != 3)
|
||||
a++;
|
||||
|
||||
uint8 b = a;
|
||||
if (_flags.gameID == GI_EOB1) {
|
||||
a += _dscDoorFrameIndex1[_currentLevel - 1];
|
||||
b += _dscDoorFrameIndex2[_currentLevel - 1];
|
||||
}
|
||||
|
||||
y1 = _dscDoorFrameY1[a];
|
||||
y2 = _dscDoorFrameY2[b];
|
||||
|
||||
if (dim == -1)
|
||||
return;
|
||||
|
||||
const ScreenDim *cDim = screen()->getScreenDim(dim);
|
||||
|
||||
screen()->modifyScreenDim(dim, cDim->sx, y1, cDim->w, y2 - y1);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::drawLevelModifyScreenDim(int dim, int16 x1, int16 y1, int16 x2, int16 y2) {
|
||||
screen()->modifyScreenDim(dim, x1, y1 << 3, x2 - x1, (y2 - y1) << 3);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::generateBlockDrawingBuffer() {
|
||||
_sceneDrawVarDown = _dscBlockMap[_currentDirection];
|
||||
_sceneDrawVarRight = _dscBlockMap[_currentDirection + 4];
|
||||
_sceneDrawVarLeft = _dscBlockMap[_currentDirection + 8];
|
||||
|
||||
/*******************************************
|
||||
* _visibleBlocks map *
|
||||
* *
|
||||
* | | | | | | *
|
||||
* 00 | 01 | 02 | 03 | 04 | 05 | 06 *
|
||||
* ____|_____|_____|_____|_____|_____|_____ *
|
||||
* | | | | | | *
|
||||
* | 07 | 08 | 09 | 10 | 11 | *
|
||||
* |_____|_____|_____|_____|_____| *
|
||||
* | | | | *
|
||||
* | 12 | 13 | 14 | *
|
||||
* |_____|_____|_____| *
|
||||
* | | *
|
||||
* 15 | 16 | 17 *
|
||||
* | (P) | *
|
||||
********************************************/
|
||||
|
||||
memset(_blockDrawingBuffer, 0, 660 * sizeof(uint16));
|
||||
|
||||
_wllProcessFlag = ((_currentBlock >> 5) + (_currentBlock & 0x1F) + _currentDirection) & 1;
|
||||
|
||||
if (_wllProcessFlag) // floor and ceiling
|
||||
generateVmpTileDataFlipped(0, 15, 1, -330, 22, 15);
|
||||
else
|
||||
generateVmpTileData(0, 15, 1, -330, 22, 15);
|
||||
|
||||
assignVisibleBlocks(_currentBlock, _currentDirection);
|
||||
|
||||
uint8 t = _visibleBlocks[0]->walls[_sceneDrawVarRight];
|
||||
if (t)
|
||||
generateVmpTileData(-2, 3, t, _vmpVisOffs[0], 3, 5);
|
||||
|
||||
t = _visibleBlocks[6]->walls[_sceneDrawVarLeft];
|
||||
if (t)
|
||||
generateVmpTileDataFlipped(21, 3, t, _vmpVisOffs[0], 3, 5);
|
||||
|
||||
t = _visibleBlocks[1]->walls[_sceneDrawVarRight];
|
||||
uint8 t2 = _visibleBlocks[2]->walls[_sceneDrawVarDown];
|
||||
|
||||
if (hasWall(t) && !(_wllWallFlags[t2] & 8))
|
||||
generateVmpTileData(2, 3, t, _vmpVisOffs[0], 3, 5);
|
||||
else if (t && (_wllWallFlags[t2] & 8))
|
||||
generateVmpTileData(2, 3, t2, _vmpVisOffs[0], 3, 5);
|
||||
|
||||
t = _visibleBlocks[5]->walls[_sceneDrawVarLeft];
|
||||
t2 = _visibleBlocks[4]->walls[_sceneDrawVarDown];
|
||||
|
||||
if (hasWall(t) && !(_wllWallFlags[t2] & 8))
|
||||
generateVmpTileDataFlipped(17, 3, t, _vmpVisOffs[0], 3, 5);
|
||||
else if (t && (_wllWallFlags[t2] & 8))
|
||||
generateVmpTileDataFlipped(17, 3, t2, _vmpVisOffs[0], 3, 5);
|
||||
|
||||
t = _visibleBlocks[2]->walls[_sceneDrawVarRight];
|
||||
if (t)
|
||||
generateVmpTileData(8, 3, t, _vmpVisOffs[1], 1, 5);
|
||||
|
||||
t = _visibleBlocks[4]->walls[_sceneDrawVarLeft];
|
||||
if (t)
|
||||
generateVmpTileDataFlipped(13, 3, t, _vmpVisOffs[1], 1, 5);
|
||||
|
||||
t = _visibleBlocks[1]->walls[_sceneDrawVarDown];
|
||||
if (hasWall(t))
|
||||
generateVmpTileData(-4, 3, t, _vmpVisOffs[2], 6, 5);
|
||||
|
||||
t = _visibleBlocks[5]->walls[_sceneDrawVarDown];
|
||||
if (hasWall(t))
|
||||
generateVmpTileData(20, 3, t, _vmpVisOffs[2], 6, 5);
|
||||
|
||||
t = _visibleBlocks[2]->walls[_sceneDrawVarDown];
|
||||
if (hasWall(t))
|
||||
generateVmpTileData(2, 3, t, _vmpVisOffs[2], 6, 5);
|
||||
|
||||
t = _visibleBlocks[4]->walls[_sceneDrawVarDown];
|
||||
if (hasWall(t))
|
||||
generateVmpTileData(14, 3, t, _vmpVisOffs[2], 6, 5);
|
||||
|
||||
t = _visibleBlocks[3]->walls[_sceneDrawVarDown];
|
||||
if (t)
|
||||
generateVmpTileData(8, 3, t, _vmpVisOffs[2], 6, 5);
|
||||
|
||||
t = _visibleBlocks[7]->walls[_sceneDrawVarRight];
|
||||
if (t)
|
||||
generateVmpTileData(0, 3, t, _vmpVisOffs[3], 2, 6);
|
||||
|
||||
t = _visibleBlocks[11]->walls[_sceneDrawVarLeft];
|
||||
if (t)
|
||||
generateVmpTileDataFlipped(20, 3, t, _vmpVisOffs[3], 2, 6);
|
||||
|
||||
t = _visibleBlocks[8]->walls[_sceneDrawVarRight];
|
||||
if (t)
|
||||
generateVmpTileData(6, 2, t, _vmpVisOffs[4], 2, 8);
|
||||
|
||||
t = _visibleBlocks[10]->walls[_sceneDrawVarLeft];
|
||||
if (t)
|
||||
generateVmpTileDataFlipped(14, 2, t, _vmpVisOffs[4], 2, 8);
|
||||
|
||||
t = _visibleBlocks[8]->walls[_sceneDrawVarDown];
|
||||
if (hasWall(t))
|
||||
generateVmpTileData(-4, 2, t, _vmpVisOffs[5], 10, 8);
|
||||
|
||||
t = _visibleBlocks[10]->walls[_sceneDrawVarDown];
|
||||
if (hasWall(t))
|
||||
generateVmpTileData(16, 2, t, _vmpVisOffs[5], 10, 8);
|
||||
|
||||
t = _visibleBlocks[9]->walls[_sceneDrawVarDown];
|
||||
if (t)
|
||||
generateVmpTileData(6, 2, t, _vmpVisOffs[5], 10, 8);
|
||||
|
||||
t = _visibleBlocks[12]->walls[_sceneDrawVarRight];
|
||||
if (t)
|
||||
generateVmpTileData(3, 1, t, _vmpVisOffs[6], 3, 12);
|
||||
|
||||
t = _visibleBlocks[14]->walls[_sceneDrawVarLeft];
|
||||
if (t)
|
||||
generateVmpTileDataFlipped(16, 1, t, _vmpVisOffs[6], 3, 12);
|
||||
|
||||
t = _visibleBlocks[12]->walls[_sceneDrawVarDown];
|
||||
if (!(_wllWallFlags[t] & 8))
|
||||
generateVmpTileData(-13, 1, t, _vmpVisOffs[7], 16, 12);
|
||||
|
||||
t = _visibleBlocks[14]->walls[_sceneDrawVarDown];
|
||||
if (!(_wllWallFlags[t] & 8))
|
||||
generateVmpTileData(19, 1, t, _vmpVisOffs[7], 16, 12);
|
||||
|
||||
t = _visibleBlocks[13]->walls[_sceneDrawVarDown];
|
||||
if (t)
|
||||
generateVmpTileData(3, 1, t, _vmpVisOffs[7], 16, 12);
|
||||
|
||||
t = _visibleBlocks[15]->walls[_sceneDrawVarRight];
|
||||
t2 = _visibleBlocks[17]->walls[_sceneDrawVarLeft];
|
||||
if (t)
|
||||
generateVmpTileData(0, 0, t, _vmpVisOffs[8], 3, 15);
|
||||
if (t2)
|
||||
generateVmpTileDataFlipped(19, 0, t2, _vmpVisOffs[8], 3, 15);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::generateVmpTileData(int16 startBlockX, uint8 startBlockY, uint8 vmpMapIndex, int16 vmpOffset, uint8 numBlocksX, uint8 numBlocksY) {
|
||||
if (!_wllVmpMap[vmpMapIndex])
|
||||
return;
|
||||
|
||||
uint16 *vmp = &_vmpPtr[(_wllVmpMap[vmpMapIndex] - 1) * 431 + vmpOffset + 330];
|
||||
|
||||
for (int i = 0; i < numBlocksY; i++) {
|
||||
uint16 *bl = &_blockDrawingBuffer[(startBlockY + i) * 22 + startBlockX];
|
||||
for (int ii = 0; ii < numBlocksX; ii++) {
|
||||
if ((startBlockX + ii >= 0) && (startBlockX + ii < 22) && *vmp)
|
||||
*bl = *vmp;
|
||||
bl++;
|
||||
vmp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KyraRpgEngine::generateVmpTileDataFlipped(int16 startBlockX, uint8 startBlockY, uint8 vmpMapIndex, int16 vmpOffset, uint8 numBlocksX, uint8 numBlocksY) {
|
||||
if (!_wllVmpMap[vmpMapIndex])
|
||||
return;
|
||||
|
||||
uint16 *vmp = &_vmpPtr[(_wllVmpMap[vmpMapIndex] - 1) * 431 + vmpOffset + 330] + (numBlocksX - 1);
|
||||
uint16 *bl = &_blockDrawingBuffer[startBlockY * 22 + startBlockX];
|
||||
|
||||
for (int i = 0; i < numBlocksY; i++) {
|
||||
uint16 *bl2 = bl;
|
||||
uint16 *vmpb = vmp;
|
||||
for (int ii = 0; ii < numBlocksX; ii++) {
|
||||
if ((startBlockX + ii >= 0) && (startBlockX + ii < 22) && *vmp)
|
||||
*bl = (*vmp & 0x4000) ? *vmp - 0x4000 : *vmp | 0x4000;
|
||||
bl++;
|
||||
vmp--;
|
||||
}
|
||||
bl = bl2 + 22;
|
||||
vmp = vmpb + numBlocksX;
|
||||
}
|
||||
}
|
||||
|
||||
bool KyraRpgEngine::hasWall(int index) {
|
||||
if (!index || (_wllWallFlags[index] & 8))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::assignVisibleBlocks(int block, int direction) {
|
||||
for (int i = 0; i < 18; i++) {
|
||||
uint16 t = (block + _dscBlockIndex[direction * 18 + i]) & 0x3FF;
|
||||
_visibleBlockIndex[i] = t;
|
||||
_visibleBlocks[i] = &_levelBlockProperties[t];
|
||||
_lvlShapeLeftRight[i] = _lvlShapeLeftRight[18 + i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool KyraRpgEngine::checkSceneUpdateNeed(int block) {
|
||||
if (_sceneUpdateRequired)
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < 15; i++) {
|
||||
if (_visibleBlockIndex[i] == block) {
|
||||
_sceneUpdateRequired = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_currentBlock == block) {
|
||||
_sceneUpdateRequired = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 KyraRpgEngine::calcNewBlockPosition(uint16 curBlock, uint16 direction) {
|
||||
static const int16 blockPosTable[] = { -32, 1, 32, -1 };
|
||||
assert(direction < ARRAYSIZE(blockPosTable));
|
||||
return (curBlock + blockPosTable[direction]) & 0x3FF;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::drawVcnBlocks() {
|
||||
uint8 *d = _sceneWindowBuffer;
|
||||
uint16 *bdb = _blockDrawingBuffer;
|
||||
|
||||
for (int y = 0; y < 15; y++) {
|
||||
for (int x = 0; x < 22; x++) {
|
||||
bool horizontalFlip = false;
|
||||
uint16 vcnOffset = *bdb++;
|
||||
uint16 vcnExtraOffsetWll = 0;
|
||||
_wllVcnOffset2 = 0;
|
||||
_wllVcnRmdOffset = 0;
|
||||
|
||||
if (vcnOffset & 0x8000) {
|
||||
// this renders a wall block over the transparent pixels of a floor/ceiling block
|
||||
vcnExtraOffsetWll = vcnOffset - 0x8000;
|
||||
vcnOffset = 0;
|
||||
_wllVcnRmdOffset = _wllVcnOffset;
|
||||
}
|
||||
|
||||
if (vcnOffset & 0x4000) {
|
||||
horizontalFlip = true;
|
||||
vcnOffset &= 0x3FFF;
|
||||
}
|
||||
|
||||
const uint8 *src = 0;
|
||||
if (vcnOffset) {
|
||||
src = &_vcnBlocks[vcnOffset * (_vcnSrcBitsPerPixel << 3)];
|
||||
_wllVcnOffset2 = _wllVcnOffset;
|
||||
} else {
|
||||
// floor/ceiling blocks
|
||||
vcnOffset = bdb[329];
|
||||
if (vcnOffset & 0x4000) {
|
||||
horizontalFlip = true;
|
||||
vcnOffset &= 0x3FFF;
|
||||
}
|
||||
|
||||
src = (_vcfBlocks ? _vcfBlocks : _vcnBlocks) + (vcnOffset * (_vcnSrcBitsPerPixel << 3));
|
||||
}
|
||||
|
||||
_vcnShiftVal = _vcnShift ? _vcnShift[vcnOffset] : _blockBrightness;
|
||||
|
||||
for (int blockY = 0; blockY < 8; blockY++) {
|
||||
if (horizontalFlip)
|
||||
(*_vcnDrawLine->backwards)(d, src);
|
||||
else
|
||||
(*_vcnDrawLine->forward)(d, src);
|
||||
d += 168 * _vcnBpp;
|
||||
}
|
||||
d -= 1400 * _vcnBpp;
|
||||
|
||||
if (vcnExtraOffsetWll) {
|
||||
d -= (8 * _vcnBpp);
|
||||
horizontalFlip = false;
|
||||
|
||||
if (vcnExtraOffsetWll & 0x4000) {
|
||||
vcnExtraOffsetWll &= 0x3FFF;
|
||||
horizontalFlip = true;
|
||||
}
|
||||
|
||||
_vcnShiftVal = _vcnShift ? _vcnShift[vcnExtraOffsetWll] : _blockBrightness;
|
||||
src = &_vcnBlocks[vcnExtraOffsetWll * (_vcnSrcBitsPerPixel << 3)];
|
||||
_vcnMaskTbl = _vcnTransitionMask ? &_vcnTransitionMask[vcnExtraOffsetWll * (_vcnSrcBitsPerPixel << 3)] : 0;
|
||||
|
||||
for (int blockY = 0; blockY < 8; blockY++) {
|
||||
if (horizontalFlip)
|
||||
(*_vcnDrawLine->backwards_trans)(d, src);
|
||||
else
|
||||
(*_vcnDrawLine->forward_trans)(d, src);
|
||||
d += 168 * _vcnBpp;
|
||||
}
|
||||
d -= 1400 * _vcnBpp;
|
||||
}
|
||||
}
|
||||
d += 1232 * _vcnBpp;
|
||||
}
|
||||
|
||||
screen()->copyBlockToPage(_sceneDrawPage1, _sceneXoffset, 0, 176, 120, _sceneWindowBuffer);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_fw_4bit(uint8 *&dst, const uint8 *&src) {
|
||||
for (int blockX = 0; blockX < 4; blockX++) {
|
||||
uint8 bl = *src++;
|
||||
*dst++ = _vcnColTable[((bl >> 4) + _wllVcnOffset2) | _vcnShiftVal];
|
||||
*dst++ = _vcnColTable[((bl & 0x0F) + _wllVcnOffset2) | _vcnShiftVal];
|
||||
}
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_bw_4bit(uint8 *&dst, const uint8 *&src) {
|
||||
src += 3;
|
||||
for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
|
||||
uint8 bl = *src--;
|
||||
*dst++ = _vcnColTable[((bl & 0x0F) + _wllVcnOffset2) | _vcnShiftVal];
|
||||
*dst++ = _vcnColTable[((bl >> 4) + _wllVcnOffset2) | _vcnShiftVal];
|
||||
}
|
||||
src += 5;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_fw_trans_4bit(uint8 *&dst, const uint8 *&src) {
|
||||
for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
|
||||
uint8 bl = *src++;
|
||||
uint8 mask = _vcnTransitionMask ? *_vcnMaskTbl++ : 0;
|
||||
uint8 h = _vcnColTable[((bl >> 4) + _wllVcnRmdOffset) | _vcnShiftVal];
|
||||
uint8 l = _vcnColTable[((bl & 0x0F) + _wllVcnRmdOffset) | _vcnShiftVal];
|
||||
|
||||
if (_vcnTransitionMask)
|
||||
*dst = (*dst & (mask >> 4)) | h;
|
||||
else if (h)
|
||||
*dst = h;
|
||||
dst++;
|
||||
|
||||
if (_vcnTransitionMask)
|
||||
*dst = (*dst & (mask & 0x0F)) | l;
|
||||
else if (l)
|
||||
*dst = l;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_bw_trans_4bit(uint8 *&dst, const uint8 *&src) {
|
||||
src += 3;
|
||||
_vcnMaskTbl += 3;
|
||||
for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
|
||||
uint8 bl = *src--;
|
||||
uint8 mask = _vcnTransitionMask ? *_vcnMaskTbl-- : 0;
|
||||
uint8 h = _vcnColTable[((bl & 0x0F) + _wllVcnRmdOffset) | _vcnShiftVal];
|
||||
uint8 l = _vcnColTable[((bl >> 4) + _wllVcnRmdOffset) | _vcnShiftVal];
|
||||
|
||||
if (_vcnTransitionMask)
|
||||
*dst = (*dst & (mask & 0x0F)) | h;
|
||||
else if (h)
|
||||
*dst = h;
|
||||
dst++;
|
||||
|
||||
if (_vcnTransitionMask)
|
||||
*dst = (*dst & (mask >> 4)) | l;
|
||||
else if (l)
|
||||
*dst = l;
|
||||
dst++;
|
||||
}
|
||||
src += 5;
|
||||
_vcnMaskTbl += 5;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_fw_hiCol(uint8 *&dst, const uint8 *&src) {
|
||||
const uint16 *hiColorPal = screen()->get16bitPalette();
|
||||
for (int blockX = 0; blockX < 8; blockX++) {
|
||||
*(uint16*)dst = hiColorPal[*src++];
|
||||
dst += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_bw_hiCol(uint8 *&dst, const uint8 *&src) {
|
||||
src += 7;
|
||||
const uint16 *hiColorPal = screen()->get16bitPalette();
|
||||
for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
|
||||
*(uint16*)dst = hiColorPal[*src--];
|
||||
dst += 2;
|
||||
}
|
||||
src += 9;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_fw_trans_hiCol(uint8 *&dst, const uint8 *&src) {
|
||||
const uint16 *hiColorPal = screen()->get16bitPalette();
|
||||
for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
|
||||
uint8 bl = *src++;
|
||||
if (bl)
|
||||
*(uint16*)dst = hiColorPal[bl];
|
||||
dst += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_bw_trans_hiCol(uint8 *&dst, const uint8 *&src) {
|
||||
src += 7;
|
||||
const uint16 *hiColorPal = screen()->get16bitPalette();
|
||||
for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
|
||||
uint8 bl = *src--;
|
||||
if (bl)
|
||||
*(uint16*)dst = hiColorPal[bl];
|
||||
dst += 2;
|
||||
}
|
||||
src += 9;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_fw_planar(uint8 *&dst, const uint8 *&src) {
|
||||
for (int blockX = 0; blockX < 8; blockX++) {
|
||||
uint8 col = 0;
|
||||
for (int i = 0; i < _vcnSrcBitsPerPixel; ++i)
|
||||
col |= ((src[i] >> (7 - blockX)) & 1) << i;
|
||||
*dst++ = col;
|
||||
}
|
||||
src += _vcnSrcBitsPerPixel;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_bw_planar(uint8 *&dst, const uint8 *&src) {
|
||||
for (int blockX = 7; blockX >= 0; blockX--) {
|
||||
uint8 col = 0;
|
||||
for (int i = 0; i < _vcnSrcBitsPerPixel; ++i)
|
||||
col |= ((src[i] >> (7 - blockX)) & 1) << i;
|
||||
*dst++ = col;
|
||||
}
|
||||
src += _vcnSrcBitsPerPixel;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_fw_trans_planar(uint8 *&dst, const uint8 *&src) {
|
||||
for (int blockX = 0; blockX < 8; blockX++) {
|
||||
uint8 col = 0;
|
||||
for (int i = 0; i < _vcnSrcBitsPerPixel; ++i)
|
||||
col |= ((src[i] >> (7 - blockX)) & 1) << i;
|
||||
if (col)
|
||||
*dst = col;
|
||||
dst++;
|
||||
}
|
||||
src += _vcnSrcBitsPerPixel;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::vcnDraw_bw_trans_planar(uint8 *&dst, const uint8 *&src) {
|
||||
for (int blockX = 7; blockX >= 0; blockX--) {
|
||||
uint8 col = 0;
|
||||
for (int i = 0; i < _vcnSrcBitsPerPixel; ++i)
|
||||
col |= ((src[i] >> (7 - blockX)) & 1) << i;
|
||||
if (col)
|
||||
*dst = col;
|
||||
dst++;
|
||||
}
|
||||
src += _vcnSrcBitsPerPixel;
|
||||
}
|
||||
|
||||
int KyraRpgEngine::clickedWallShape(uint16 block, uint16 direction) {
|
||||
uint8 v = _wllShapeMap[_levelBlockProperties[block].walls[direction]];
|
||||
if (!clickedShape(v))
|
||||
return 0;
|
||||
|
||||
snd_stopSpeech(true);
|
||||
runLevelScript(block, 0x40);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int KyraRpgEngine::clickedLeverOn(uint16 block, uint16 direction) {
|
||||
uint8 v = _wllShapeMap[_levelBlockProperties[block].walls[direction]];
|
||||
if (!clickedShape(v))
|
||||
return 0;
|
||||
|
||||
_levelBlockProperties[block].walls[direction]++;
|
||||
_sceneUpdateRequired = true;
|
||||
|
||||
if (_flags.gameID == GI_LOL)
|
||||
snd_playSoundEffect(30, -1);
|
||||
|
||||
runLevelScript(block, _clickedSpecialFlag);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int KyraRpgEngine::clickedLeverOff(uint16 block, uint16 direction) {
|
||||
uint8 v = _wllShapeMap[_levelBlockProperties[block].walls[direction]];
|
||||
if (!clickedShape(v))
|
||||
return 0;
|
||||
|
||||
_levelBlockProperties[block].walls[direction]--;
|
||||
_sceneUpdateRequired = true;
|
||||
|
||||
if (_flags.gameID == GI_LOL)
|
||||
snd_playSoundEffect(29, -1);
|
||||
|
||||
runLevelScript(block, _clickedSpecialFlag);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int KyraRpgEngine::clickedWallOnlyScript(uint16 block) {
|
||||
runLevelScript(block, _clickedSpecialFlag);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void KyraRpgEngine::processDoorSwitch(uint16 block, int openClose) {
|
||||
if (block == _currentBlock)
|
||||
return;
|
||||
|
||||
if ((_flags.gameID == GI_LOL && (_levelBlockProperties[block].assignedObjects & 0x8000)) || (_flags.gameID != GI_LOL && (_levelBlockProperties[block].flags & 7)))
|
||||
return;
|
||||
|
||||
if (openClose == 0) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (_openDoorState[i].block != block)
|
||||
continue;
|
||||
openClose = -_openDoorState[i].state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (openClose == 0) {
|
||||
openClose = (_wllWallFlags[_levelBlockProperties[block].walls[_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8 ? 0 : 1]] & 1) ? 1 : -1;
|
||||
if (_flags.gameID != GI_LOL)
|
||||
openClose *= -1;
|
||||
}
|
||||
|
||||
openCloseDoor(block, openClose);
|
||||
}
|
||||
|
||||
void KyraRpgEngine::openCloseDoor(int block, int openClose) {
|
||||
int s1 = -1;
|
||||
int s2 = -1;
|
||||
|
||||
int c = (_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8) ? 0 : 1;
|
||||
int v = _levelBlockProperties[block].walls[c];
|
||||
int flg = (_flags.gameID == GI_EOB1) ? 1 : ((openClose == 1) ? 0x10 : (openClose == -1 ? 0x20 : 0));
|
||||
|
||||
if ((_flags.gameID == GI_EOB1 && openClose == -1 && !(_wllWallFlags[v] & flg)) || (!(_flags.gameID == GI_EOB1 && openClose == -1) && (_wllWallFlags[v] & flg)))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (_openDoorState[i].block == block) {
|
||||
s1 = i;
|
||||
break;
|
||||
} else if (_openDoorState[i].block == 0 && s2 == -1) {
|
||||
s2 = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (s1 != -1 || s2 != -1) {
|
||||
if (s1 == -1)
|
||||
s1 = s2;
|
||||
|
||||
_openDoorState[s1].block = block;
|
||||
_openDoorState[s1].state = openClose;
|
||||
_openDoorState[s1].wall = c;
|
||||
|
||||
flg = (-openClose == 1) ? 0x10 : (-openClose == -1 ? 0x20 : 0);
|
||||
|
||||
if (_wllWallFlags[v] & flg) {
|
||||
_levelBlockProperties[block].walls[c] += openClose;
|
||||
_levelBlockProperties[block].walls[c ^ 2] += openClose;
|
||||
|
||||
int snd = (openClose == -1) ? 4 : (isSpecialDoor(block) ? 126 : 3);
|
||||
if (_flags.gameID == GI_LOL) {
|
||||
snd_processEnvironmentalSoundEffect(snd + 28, _currentBlock);
|
||||
if (!checkSceneUpdateNeed(block))
|
||||
snd_updateEnvironmentalSfx(0);
|
||||
} else {
|
||||
snd_updateEnvironmentalSfx(snd);
|
||||
}
|
||||
}
|
||||
|
||||
enableTimer(_flags.gameID == GI_LOL ? 0 : 4);
|
||||
|
||||
} else {
|
||||
while (!(flg & _wllWallFlags[v]))
|
||||
v += openClose;
|
||||
|
||||
_levelBlockProperties[block].walls[c] = _levelBlockProperties[block].walls[c ^ 2] = v;
|
||||
checkSceneUpdateNeed(block);
|
||||
}
|
||||
}
|
||||
|
||||
void KyraRpgEngine::completeDoorOperations() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (!_openDoorState[i].block)
|
||||
continue;
|
||||
|
||||
uint16 b = _openDoorState[i].block;
|
||||
|
||||
do {
|
||||
_levelBlockProperties[b].walls[_openDoorState[i].wall] += _openDoorState[i].state;
|
||||
_levelBlockProperties[b].walls[_openDoorState[i].wall ^ 2] += _openDoorState[i].state;
|
||||
} while (!(_wllWallFlags[_levelBlockProperties[b].walls[_openDoorState[i].wall]] & 0x30));
|
||||
|
||||
_openDoorState[i].block = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool KyraRpgEngine::isSpecialDoor(int block) {
|
||||
if (_flags.platform != Common::kPlatformSegaCD || _currentLevel != 2)
|
||||
return false;
|
||||
|
||||
static const uint16 specialBlocks[4] = { 0x122, 0x275, 0x3C8, 0x1E7 };
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (block == specialBlocks[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif // ENABLE_EOB || ENABLE_LOL
|
||||
Reference in New Issue
Block a user