mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-20 16:59:06 +00:00
370107c953
This is a left-over vestige of when the gob engine recorded the size of each variable currently in use, because it byte-swapped all variables on save/load depending on the machine ScummVM ran on. The gob engine doesn't do that all anymore (instead, the variables are always stored in the endianness of the original game), so getAddressOff8() doesn't store "this is an 8-bit variable" anymore, making the call a NOP. This fixes Coverity Scan issue #1267142.
286 lines
7.5 KiB
C++
286 lines
7.5 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/stream.h"
|
|
|
|
#include "gob/gob.h"
|
|
#include "gob/map.h"
|
|
#include "gob/global.h"
|
|
#include "gob/goblin.h"
|
|
#include "gob/inter.h"
|
|
#include "gob/game.h"
|
|
#include "gob/script.h"
|
|
#include "gob/resources.h"
|
|
#include "gob/mult.h"
|
|
|
|
namespace Gob {
|
|
|
|
Map_v2::Map_v2(GobEngine *vm) : Map_v1(vm) {
|
|
_screenHeight = 200;
|
|
}
|
|
|
|
Map_v2::~Map_v2() {
|
|
_passMap = 0;
|
|
}
|
|
|
|
void Map_v2::loadMapObjects(const char *avjFile) {
|
|
uint8 wayPointsCount;
|
|
uint16 var;
|
|
int16 id;
|
|
int16 mapWidth, mapHeight;
|
|
int16 tmp;
|
|
byte *variables;
|
|
uint32 tmpPos;
|
|
uint32 passPos;
|
|
|
|
var = _vm->_game->_script->readVarIndex();
|
|
variables = _vm->_inter->_variables->getAddressOff8(var);
|
|
|
|
id = _vm->_game->_script->readInt16();
|
|
|
|
if (((uint16) id) >= 65520) {
|
|
switch ((uint16) id) {
|
|
case 65530:
|
|
for (int i = 0; i < _mapWidth * _mapHeight; i++)
|
|
_passMap[i] -= READ_VARO_UINT8(var + i);
|
|
break;
|
|
case 65531:
|
|
for (int i = 0; i < _mapWidth * _mapHeight; i++)
|
|
_passMap[i] += READ_VARO_UINT8(var + i);
|
|
break;
|
|
case 65532:
|
|
for (int i = 0; i < _mapWidth * _mapHeight; i++)
|
|
WRITE_VARO_UINT8(var + i, 0x00);
|
|
break;
|
|
case 65533: {
|
|
int index = READ_VARO_UINT16(var);
|
|
// _vm->_mult->_objects[index].field_6E = 0;
|
|
// _vm->_mult->_objects[index].field_6A = variables;
|
|
warning("Map_v2::loadMapObjects(): ID == 65533 (%d)", index);
|
|
break;
|
|
}
|
|
case 65534:
|
|
_tilesWidth = READ_VARO_UINT8(var);
|
|
_tilesHeight = READ_VARO_UINT8(var + 1);
|
|
_mapWidth = READ_VARO_UINT8(var + 2);
|
|
_mapHeight = READ_VARO_UINT8(var + 3);
|
|
_mapUnknownBool = READ_VARO_UINT8(var + 4) ? true : false;
|
|
if (_mapUnknownBool)
|
|
warning("Map_v2::loadMapObjects(): _mapUnknownBool == true");
|
|
break;
|
|
case 65535:
|
|
_passMap = (int8 *)_vm->_inter->_variables->getAddressOff8(var);
|
|
break;
|
|
default:
|
|
warning("Map_v2::loadMapObjects(): ID == %d", (uint16) id);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
Resource *resource = _vm->_game->_resources->getResource(id);
|
|
if (!resource)
|
|
return;
|
|
|
|
Common::SeekableReadStream &mapData = *resource->stream();
|
|
|
|
_mapVersion = mapData.readByte();
|
|
if (_mapVersion == 4) {
|
|
_screenWidth = 640;
|
|
_screenHeight = 400;
|
|
} else if (_mapVersion == 3) {
|
|
_passWidth = 65;
|
|
_screenWidth = 640;
|
|
_screenHeight = 200;
|
|
} else {
|
|
_passWidth = 40;
|
|
_screenWidth = 320;
|
|
_screenHeight = 200;
|
|
}
|
|
|
|
_wayPointCount = mapData.readByte();
|
|
_tilesWidth = mapData.readSint16LE();
|
|
_tilesHeight = mapData.readSint16LE();
|
|
|
|
_bigTiles = !(_tilesHeight & 0xFF00);
|
|
_tilesHeight &= 0xFF;
|
|
|
|
if (_mapVersion == 4) {
|
|
_screenWidth = mapData.readSint16LE();
|
|
_screenHeight = mapData.readSint16LE();
|
|
}
|
|
|
|
_mapWidth = _screenWidth / _tilesWidth;
|
|
_mapHeight = _screenHeight / _tilesHeight;
|
|
|
|
passPos = mapData.pos();
|
|
mapData.skip(_mapWidth * _mapHeight);
|
|
|
|
if (resource->getData()[0] == 1)
|
|
wayPointsCount = _wayPointCount = 40;
|
|
else
|
|
wayPointsCount = _wayPointCount == 0 ? 1 : _wayPointCount;
|
|
|
|
delete[] _wayPoints;
|
|
_wayPoints = new WayPoint[wayPointsCount];
|
|
for (int i = 0; i < _wayPointCount; i++) {
|
|
_wayPoints[i].x = mapData.readSByte();
|
|
_wayPoints[i].y = mapData.readSByte();
|
|
_wayPoints[i].notWalkable = mapData.readSByte();
|
|
}
|
|
|
|
if (_mapVersion == 4) {
|
|
_mapWidth = VAR(17);
|
|
_passWidth = _mapWidth;
|
|
}
|
|
|
|
// In the original asm, this writes byte-wise into the variables-array
|
|
tmpPos = mapData.pos();
|
|
mapData.seek(passPos);
|
|
if ((variables != 0) &&
|
|
(variables != _vm->_inter->_variables->getAddressOff8(0))) {
|
|
|
|
_passMap = (int8 *)variables;
|
|
mapHeight = _screenHeight / _tilesHeight;
|
|
mapWidth = _screenWidth / _tilesWidth;
|
|
|
|
for (int i = 0; i < mapHeight; i++)
|
|
for (int j = 0; j < mapWidth; j++)
|
|
setPass(j, i, mapData.readSByte());
|
|
}
|
|
mapData.seek(tmpPos);
|
|
|
|
tmp = mapData.readSint16LE();
|
|
mapData.skip(tmp * 14);
|
|
tmp = mapData.readSint16LE();
|
|
mapData.skip(tmp * 14 + 28);
|
|
tmp = mapData.readSint16LE();
|
|
mapData.skip(tmp * 14);
|
|
|
|
_vm->_goblin->_gobsCount = tmp;
|
|
for (int i = 0; i < _vm->_goblin->_gobsCount; i++)
|
|
loadGoblinStates(mapData, i);
|
|
|
|
_vm->_goblin->_soundSlotsCount = _vm->_game->_script->readInt16();
|
|
for (int i = 0; i < _vm->_goblin->_soundSlotsCount; i++)
|
|
_vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1);
|
|
|
|
delete resource;
|
|
}
|
|
|
|
void Map_v2::loadGoblinStates(Common::SeekableReadStream &data, int index) {
|
|
Mult::Mult_GobState *statesPtr;
|
|
Mult::Mult_GobState *gobState;
|
|
int8 indices[102];
|
|
uint8 statesCount;
|
|
uint8 dataCount;
|
|
int16 state;
|
|
uint32 tmpPos;
|
|
|
|
memset(indices, -1, 101);
|
|
_vm->_mult->_objects[index].goblinStates = new Mult::Mult_GobState*[101];
|
|
memset(_vm->_mult->_objects[index].goblinStates, 0,
|
|
101 * sizeof(Mult::Mult_GobState *));
|
|
|
|
data.read(indices, 100);
|
|
tmpPos = data.pos();
|
|
statesCount = 0;
|
|
for (int i = 0; i < 100; i++) {
|
|
if (indices[i] != -1) {
|
|
statesCount++;
|
|
data.skip(4);
|
|
dataCount = data.readByte();
|
|
statesCount += dataCount;
|
|
data.skip(dataCount * 9);
|
|
}
|
|
}
|
|
|
|
data.seek(tmpPos);
|
|
|
|
statesPtr = new Mult::Mult_GobState[statesCount];
|
|
_vm->_mult->_objects[index].goblinStates[0] = statesPtr;
|
|
for (int i = 0; i < 100; i++) {
|
|
state = indices[i];
|
|
if (state != -1) {
|
|
_vm->_mult->_objects[index].goblinStates[state] = statesPtr++;
|
|
gobState = _vm->_mult->_objects[index].goblinStates[state];
|
|
|
|
gobState[0].animation = data.readSint16LE();
|
|
gobState[0].layer = data.readSint16LE();
|
|
dataCount = data.readByte();
|
|
gobState[0].dataCount = dataCount;
|
|
for (uint8 j = 1; j <= dataCount; j++) {
|
|
data.skip(1);
|
|
gobState[j].sndItem = data.readSByte();
|
|
data.skip(1);
|
|
gobState[j].sndFrame = data.readByte();
|
|
data.skip(1);
|
|
gobState[j].freq = data.readSint16LE();
|
|
gobState[j].repCount = data.readSByte();
|
|
gobState[j].speaker = data.readByte();
|
|
statesPtr++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Map_v2::findNearestToGob(Mult::Mult_Object *obj) {
|
|
int16 wayPoint = findNearestWayPoint(obj->goblinX, obj->goblinY);
|
|
|
|
if (wayPoint != -1)
|
|
obj->nearestWayPoint = wayPoint;
|
|
}
|
|
|
|
void Map_v2::findNearestToDest(Mult::Mult_Object *obj) {
|
|
int16 wayPoint = findNearestWayPoint(obj->destX, obj->destY);
|
|
|
|
if (wayPoint != -1)
|
|
obj->nearestDest = wayPoint;
|
|
}
|
|
|
|
void Map_v2::optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y) {
|
|
if (!_wayPoints)
|
|
return;
|
|
|
|
if (obj->nearestWayPoint < obj->nearestDest) {
|
|
|
|
for (int i = obj->nearestWayPoint; i <= obj->nearestDest; i++) {
|
|
if (checkDirectPath(obj, x, y, _wayPoints[i].x, _wayPoints[i].y) == 1)
|
|
obj->nearestWayPoint = i;
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i = obj->nearestWayPoint; i >= obj->nearestDest; i--) {
|
|
if (_wayPoints[i].notWalkable == 1)
|
|
break;
|
|
|
|
if (checkDirectPath(obj, x, y, _wayPoints[i].x, _wayPoints[i].y) == 1)
|
|
obj->nearestWayPoint = i;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // End of namespace Gob
|