scummvm/engines/scumm/room.cpp
2010-10-05 19:04:52 +00:00

807 lines
22 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.
*
* $URL$
* $Id$
*
*/
#include "common/system.h"
#include "scumm/actor.h"
#include "scumm/boxes.h"
#ifdef ENABLE_HE
#include "scumm/he/intern_he.h"
#endif
#include "scumm/object.h"
#include "scumm/resource.h"
#include "scumm/scumm_v3.h"
#include "scumm/sound.h"
#include "scumm/util.h"
namespace Scumm {
/**
* Start a 'scene' by loading the specified room with the given main actor.
* The actor is placed next to the object indicated by objectNr.
*/
void ScummEngine::startScene(int room, Actor *a, int objectNr) {
int i, where;
debugC(DEBUG_GENERAL, "Loading room %d", room);
stopTalk();
fadeOut(_switchRoomEffect2);
_newEffect = _switchRoomEffect;
ScriptSlot *ss = &vm.slot[_currentScript];
if (_currentScript != 0xFF) {
if (ss->where == WIO_ROOM || ss->where == WIO_FLOBJECT) {
if (ss->cutsceneOverride && _game.version >= 5)
error("Object %d stopped with active cutscene/override in exit", ss->number);
nukeArrays(_currentScript);
_currentScript = 0xFF;
} else if (ss->where == WIO_LOCAL) {
if (ss->cutsceneOverride && _game.version >= 5)
error("Script %d stopped with active cutscene/override in exit", ss->number);
nukeArrays(_currentScript);
_currentScript = 0xFF;
}
}
if (VAR_NEW_ROOM != 0xFF)
VAR(VAR_NEW_ROOM) = room;
runExitScript();
killScriptsAndResources();
if (_game.version >= 4 && _game.heversion <= 62)
stopCycle(0);
if (_game.id == GID_SAMNMAX) {
// WORKAROUND bug #85373 SAM: Overlapping music at Bigfoot convention
// Added sound queue processing between execution of exit
// script and entry script. In the case of this bug, the
// entry script required that the iMuse state be fully up
// to date, including last-moment changes from the previous
// exit script.
_sound->processSound();
}
clearDrawQueues();
// For HE80+ games
for (i = 0; i < _numRoomVariables; i++)
_roomVars[i] = 0;
nukeArrays(0xFF);
for (i = 1; i < _numActors; i++) {
_actors[i]->hideActor();
}
if (_game.version >= 7) {
// Set the shadow palette(s) to all black. This fixes
// bug #795940, and actually makes some sense (after all,
// shadows tend to be rather black, don't they? ;-)
memset(_shadowPalette, 0, NUM_SHADOW_PALETTE * 256);
} else {
for (i = 0; i < 256; i++) {
_roomPalette[i] = i;
if (_shadowPalette)
_shadowPalette[i] = i;
}
if (_game.features & GF_SMALL_HEADER)
setDirtyColors(0, 255);
}
VAR(VAR_ROOM) = room;
_fullRedraw = true;
_res->increaseResourceCounter();
_currentRoom = room;
VAR(VAR_ROOM) = room;
if (room >= 0x80 && _game.version < 7 && _game.heversion <= 71)
_roomResource = _resourceMapper[room & 0x7F];
else
_roomResource = room;
if (VAR_ROOM_RESOURCE != 0xFF)
VAR(VAR_ROOM_RESOURCE) = _roomResource;
if (room != 0)
ensureResourceLoaded(rtRoom, room);
clearRoomObjects();
if (_currentRoom == 0) {
_ENCD_offs = _EXCD_offs = 0;
_numObjectsInRoom = 0;
return;
}
setupRoomSubBlocks();
resetRoomSubBlocks();
initBGBuffers(_roomHeight);
resetRoomObjects();
if (VAR_ROOM_WIDTH != 0xFF && VAR_ROOM_HEIGHT != 0xFF) {
VAR(VAR_ROOM_WIDTH) = _roomWidth;
VAR(VAR_ROOM_HEIGHT) = _roomHeight;
}
if (VAR_CAMERA_MIN_X != 0xFF)
VAR(VAR_CAMERA_MIN_X) = _screenWidth / 2;
if (VAR_CAMERA_MAX_X != 0xFF)
VAR(VAR_CAMERA_MAX_X) = _roomWidth - (_screenWidth / 2);
if (_game.version >= 7) {
VAR(VAR_CAMERA_MIN_Y) = _screenHeight / 2;
VAR(VAR_CAMERA_MAX_Y) = _roomHeight - (_screenHeight / 2);
setCameraAt(_screenWidth / 2, _screenHeight / 2);
} else {
camera._mode = kNormalCameraMode;
if (_game.version > 2)
camera._cur.x = camera._dest.x = _screenWidth / 2;
camera._cur.y = camera._dest.y = _screenHeight / 2;
}
if (_roomResource == 0)
return;
memset(gfxUsageBits, 0, sizeof(gfxUsageBits));
if (_game.version >= 5 && a) {
where = whereIsObject(objectNr);
if (where != WIO_ROOM && where != WIO_FLOBJECT)
error("startScene: Object %d is not in room %d", objectNr,
_currentRoom);
int x, y, dir;
getObjectXYPos(objectNr, x, y, dir);
a->putActor(x, y, _currentRoom);
a->setDirection(dir + 180);
a->stopActorMoving();
if (_game.id == GID_SAMNMAX) {
camera._cur.x = camera._dest.x = a->getPos().x;
setCameraAt(a->getPos().x, a->getPos().y);
}
}
showActors();
_egoPositioned = false;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
towns_resetPalCycleFields();
#endif
runEntryScript();
if (_game.version >= 1 && _game.version <= 2) {
runScript(5, 0, 0, 0);
} else if (_game.version >= 5 && _game.version <= 6) {
if (a && !_egoPositioned) {
int x, y;
getObjectXYPos(objectNr, x, y);
a->putActor(x, y, _currentRoom);
a->_moving = 0;
}
} else if (_game.version >= 7) {
if (camera._follows) {
a = derefActor(camera._follows, "startScene: follows");
setCameraAt(a->getPos().x, a->getPos().y);
}
}
_doEffect = true;
// Hint the backend about the virtual keyboard during copy protection screens
if (_game.id == GID_MONKEY2) {
if (_system->getFeatureState(OSystem::kFeatureVirtualKeyboard)) {
if (room != 108)
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
} else if (room == 108)
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
} else if (_game.id == GID_MONKEY_EGA) { // this is my estimation that the room code is 90 (untested)
if (_system->getFeatureState(OSystem::kFeatureVirtualKeyboard)) {
if (room != 90)
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
} else if (room == 90)
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
}
}
/**
* Init some static room data after a room has been loaded.
* E.g. the room dimension, the offset to the graphics data, the room scripts,
* the offset to the room palette and other things which won't be changed
* late on.
* So it is possible to call this after loading a savegame.
*/
void ScummEngine::setupRoomSubBlocks() {
int i;
const byte *ptr;
byte *roomptr, *searchptr, *roomResPtr = 0;
const RoomHeader *rmhd;
_ENCD_offs = 0;
_EXCD_offs = 0;
_EPAL_offs = 0;
_CLUT_offs = 0;
_PALS_offs = 0;
// Determine the room and room script base address
roomResPtr = roomptr = getResourceAddress(rtRoom, _roomResource);
if (_game.version == 8)
roomResPtr = getResourceAddress(rtRoomScripts, _roomResource);
if (!roomptr || !roomResPtr)
error("Room %d: data not found (" __FILE__ ":%d)", _roomResource, __LINE__);
//
// Determine the room dimensions (width/height)
//
rmhd = (const RoomHeader *)findResourceData(MKID_BE('RMHD'), roomptr);
if (_game.version == 8) {
_roomWidth = READ_LE_UINT32(&(rmhd->v8.width));
_roomHeight = READ_LE_UINT32(&(rmhd->v8.height));
_numObjectsInRoom = (byte)READ_LE_UINT32(&(rmhd->v8.numObjects));
} else if (_game.version == 7) {
_roomWidth = READ_LE_UINT16(&(rmhd->v7.width));
_roomHeight = READ_LE_UINT16(&(rmhd->v7.height));
_numObjectsInRoom = (byte)READ_LE_UINT16(&(rmhd->v7.numObjects));
} else {
_roomWidth = READ_LE_UINT16(&(rmhd->old.width));
_roomHeight = READ_LE_UINT16(&(rmhd->old.height));
_numObjectsInRoom = (byte)READ_LE_UINT16(&(rmhd->old.numObjects));
}
//
// Find the room image data
//
if (_game.version == 8) {
_IM00_offs = getObjectImage(roomptr, 1) - roomptr;
} else if (_game.features & GF_SMALL_HEADER) {
_IM00_offs = findResourceData(MKID_BE('IM00'), roomptr) - roomptr;
} else if (_game.heversion >= 70) {
byte *roomImagePtr = getResourceAddress(rtRoomImage, _roomResource);
_IM00_offs = findResource(MKID_BE('IM00'), roomImagePtr) - roomImagePtr;
} else {
_IM00_offs = findResource(MKID_BE('IM00'), findResource(MKID_BE('RMIM'), roomptr)) - roomptr;
}
//
// Look for an exit script
//
ptr = findResourceData(MKID_BE('EXCD'), roomResPtr);
if (ptr)
_EXCD_offs = ptr - roomResPtr;
if (_dumpScripts && _EXCD_offs)
dumpResource("exit-", _roomResource, roomResPtr + _EXCD_offs - _resourceHeaderSize, -1);
//
// Look for an entry script
//
ptr = findResourceData(MKID_BE('ENCD'), roomResPtr);
if (ptr)
_ENCD_offs = ptr - roomResPtr;
if (_dumpScripts && _ENCD_offs)
dumpResource("entry-", _roomResource, roomResPtr + _ENCD_offs - _resourceHeaderSize, -1);
//
// Setup local scripts
//
// Determine the room script base address
roomResPtr = roomptr = getResourceAddress(rtRoom, _roomResource);
if (_game.version == 8)
roomResPtr = getResourceAddress(rtRoomScripts, _roomResource);
searchptr = roomResPtr;
memset(_localScriptOffsets, 0, sizeof(_localScriptOffsets));
if (_game.features & GF_SMALL_HEADER) {
ResourceIterator localScriptIterator(searchptr, true);
while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
id = ptr[0];
if (_dumpScripts) {
char buf[32];
sprintf(buf, "room-%d-", _roomResource);
dumpResource(buf, id, ptr - _resourceHeaderSize);
}
_localScriptOffsets[id - _numGlobalScripts] = ptr + 1 - roomptr;
}
} else if (_game.heversion >= 90) {
ResourceIterator localScriptIterator2(searchptr, false);
while ((ptr = localScriptIterator2.findNext(MKID_BE('LSC2'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
id = READ_LE_UINT32(ptr);
assertRange(_numGlobalScripts, id, _numLocalScripts + _numGlobalScripts, "local script");
_localScriptOffsets[id - _numGlobalScripts] = ptr + 4 - roomResPtr;
if (_dumpScripts) {
char buf[32];
sprintf(buf, "room-%d-", _roomResource);
dumpResource(buf, id, ptr - _resourceHeaderSize);
}
}
ResourceIterator localScriptIterator(searchptr, false);
while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
id = ptr[0];
_localScriptOffsets[id - _numGlobalScripts] = ptr + 1 - roomResPtr;
if (_dumpScripts) {
char buf[32];
sprintf(buf, "room-%d-", _roomResource);
dumpResource(buf, id, ptr - _resourceHeaderSize);
}
}
} else {
ResourceIterator localScriptIterator(searchptr, false);
while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
if (_game.version == 8) {
id = READ_LE_UINT32(ptr);
assertRange(_numGlobalScripts, id, _numLocalScripts + _numGlobalScripts, "local script");
_localScriptOffsets[id - _numGlobalScripts] = ptr + 4 - roomResPtr;
} else if (_game.version == 7) {
id = READ_LE_UINT16(ptr);
assertRange(_numGlobalScripts, id, _numLocalScripts + _numGlobalScripts, "local script");
_localScriptOffsets[id - _numGlobalScripts] = ptr + 2 - roomResPtr;
} else {
id = ptr[0];
_localScriptOffsets[id - _numGlobalScripts] = ptr + 1 - roomResPtr;
}
if (_dumpScripts) {
char buf[32];
sprintf(buf, "room-%d-", _roomResource);
dumpResource(buf, id, ptr - _resourceHeaderSize);
}
}
}
// Locate the EGA palette (currently unused).
ptr = findResourceData(MKID_BE('EPAL'), roomptr);
if (ptr)
_EPAL_offs = ptr - roomptr;
// Locate the standard room palette (for V3-V5 games).
ptr = findResourceData(MKID_BE('CLUT'), roomptr);
if (ptr)
_CLUT_offs = ptr - roomptr;
// Locate the standard room palettes (for V6+ games).
if (_game.version >= 6) {
ptr = findResource(MKID_BE('PALS'), roomptr);
if (ptr) {
_PALS_offs = ptr - roomptr;
}
}
// Transparent color
byte trans;
if (_game.version == 8)
trans = (byte)READ_LE_UINT32(&(rmhd->v8.transparency));
else {
ptr = findResourceData(MKID_BE('TRNS'), roomptr);
if (ptr)
trans = ptr[0];
else
trans = 255;
}
// Actor Palette in HE 70 games
if (_game.heversion == 70) {
ptr = findResourceData(MKID_BE('REMP'), roomptr);
if (ptr) {
for (i = 0; i < 256; i++)
_HEV7ActorPalette[i] = *ptr++;
} else {
for (i = 0; i < 256; i++)
_HEV7ActorPalette[i] = i;
}
}
// WORKAROUND bug #1074444: The dreaded DOTT "Can't get teeth" bug
// makes it impossible to go on playing w/o cheating in some way.
// It's not quite clear what causes it, but the effect is that object
// 182, the teeth, are still in class 32 (kObjectClassUntouchable),
// when they shouldn't be. Luckily, bitvar69 is set to 1 if and only if
// the teeth are trapped and have not yet been taken by the player. So
// we can make use of that fact to fix the object class of obj 182.
if (_game.id == GID_TENTACLE && _roomResource == 26 && readVar(0x8000 + 69)
&& getClass(182, kObjectClassUntouchable)) {
putClass(182, kObjectClassUntouchable, 0);
}
_gdi->roomChanged(roomptr);
_gdi->setTransparentColor(trans);
}
/**
* Init some dynamic room data after a room has been loaded.
* E.g. the initial box data is loaded, the initial palette is set etc.
* All of the things setup in here can be modified later on by scripts.
* So it is not appropriate to call it after loading a savegame.
*/
void ScummEngine::resetRoomSubBlocks() {
int i;
const byte *ptr;
byte *roomptr;
// Determine the room and room script base address
roomptr = getResourceAddress(rtRoom, _roomResource);
if (!roomptr)
error("Room %d: data not found (" __FILE__ ":%d)", _roomResource, __LINE__);
//
// Load box data
//
memset(_extraBoxFlags, 0, sizeof(_extraBoxFlags));
_res->nukeResource(rtMatrix, 1);
_res->nukeResource(rtMatrix, 2);
if (_game.features & GF_SMALL_HEADER) {
ptr = findResourceData(MKID_BE('BOXD'), roomptr);
if (ptr) {
byte numOfBoxes = *ptr;
int size;
if (_game.version == 3)
size = numOfBoxes * SIZEOF_BOX_V3 + 1;
else
size = numOfBoxes * SIZEOF_BOX + 1;
_res->createResource(rtMatrix, 2, size);
memcpy(getResourceAddress(rtMatrix, 2), ptr, size);
ptr += size;
size = getResourceDataSize(ptr - size - _resourceHeaderSize) - size;
if (size > 0) { // do this :)
_res->createResource(rtMatrix, 1, size);
memcpy(getResourceAddress(rtMatrix, 1), ptr, size);
}
}
} else {
ptr = findResourceData(MKID_BE('BOXD'), roomptr);
if (ptr) {
int size = getResourceDataSize(ptr);
_res->createResource(rtMatrix, 2, size);
roomptr = getResourceAddress(rtRoom, _roomResource);
ptr = findResourceData(MKID_BE('BOXD'), roomptr);
memcpy(getResourceAddress(rtMatrix, 2), ptr, size);
}
ptr = findResourceData(MKID_BE('BOXM'), roomptr);
if (ptr) {
int size = getResourceDataSize(ptr);
_res->createResource(rtMatrix, 1, size);
roomptr = getResourceAddress(rtRoom, _roomResource);
ptr = findResourceData(MKID_BE('BOXM'), roomptr);
memcpy(getResourceAddress(rtMatrix, 1), ptr, size);
}
}
//
// Load scale data
//
for (i = 1; i < _res->num[rtScaleTable]; i++)
_res->nukeResource(rtScaleTable, i);
ptr = findResourceData(MKID_BE('SCAL'), roomptr);
if (ptr) {
int s1, s2, y1, y2;
if (_game.version == 8) {
for (i = 1; i < _res->num[rtScaleTable]; i++, ptr += 16) {
s1 = READ_LE_UINT32(ptr);
y1 = READ_LE_UINT32(ptr + 4);
s2 = READ_LE_UINT32(ptr + 8);
y2 = READ_LE_UINT32(ptr + 12);
setScaleSlot(i, 0, y1, s1, 0, y2, s2);
}
} else {
for (i = 1; i < _res->num[rtScaleTable]; i++, ptr += 8) {
s1 = READ_LE_UINT16(ptr);
y1 = READ_LE_UINT16(ptr + 2);
s2 = READ_LE_UINT16(ptr + 4);
y2 = READ_LE_UINT16(ptr + 6);
if (s1 || y1 || s2 || y2) {
setScaleSlot(i, 0, y1, s1, 0, y2, s2);
}
}
}
}
// Color cycling
// HE 7.0 games load resources but don't use them.
if (_game.version >= 4 && _game.heversion <= 62) {
ptr = findResourceData(MKID_BE('CYCL'), roomptr);
if (ptr) {
initCycl(ptr);
}
}
#ifdef ENABLE_HE
// Polygons in HE 80+ games
if (_game.heversion >= 80) {
ptr = findResourceData(MKID_BE('POLD'), roomptr);
if (ptr) {
((ScummEngine_v71he *)this)->_wiz->polygonLoad(ptr);
}
}
#endif
if (_PALS_offs || _CLUT_offs)
setCurrentPalette(0);
}
void ScummEngine_v3old::setupRoomSubBlocks() {
const byte *ptr;
byte *roomptr, *searchptr = 0;
const RoomHeader *rmhd;
_ENCD_offs = 0;
_EXCD_offs = 0;
_EPAL_offs = 0;
_CLUT_offs = 0;
_PALS_offs = 0;
// Determine the room and room script base address
roomptr = getResourceAddress(rtRoom, _roomResource);
if (!roomptr)
error("Room %d: data not found (" __FILE__ ":%d)", _roomResource, __LINE__);
//
// Determine the room dimensions (width/height)
//
rmhd = (const RoomHeader *)(roomptr + 4);
if (_game.version <= 1) {
if (_game.platform == Common::kPlatformNES) {
_roomWidth = READ_LE_UINT16(&(rmhd->old.width)) * 8;
_roomHeight = READ_LE_UINT16(&(rmhd->old.height)) * 8;
// HACK: To let our code work normal with narrow rooms we
// adjust width. It will render garbage on right edge but we do
// not render it anyway
if (_roomWidth < 32 * 8)
_roomWidth = 32 * 8;
} else {
_roomWidth = roomptr[4] * 8;
_roomHeight = roomptr[5] * 8;
}
} else {
_roomWidth = READ_LE_UINT16(&(rmhd->old.width));
_roomHeight = READ_LE_UINT16(&(rmhd->old.height));
}
_numObjectsInRoom = roomptr[20];
//
// Find the room image data
//
if (_game.version <= 1) {
_IM00_offs = 0;
} else {
_IM00_offs = READ_LE_UINT16(roomptr + 0x0A);
}
//
// Look for an exit script
//
int EXCD_len = -1;
if (_game.version <= 2) {
_EXCD_offs = READ_LE_UINT16(roomptr + 0x18);
EXCD_len = READ_LE_UINT16(roomptr + 0x1A) - _EXCD_offs + _resourceHeaderSize; // HACK
} else {
_EXCD_offs = READ_LE_UINT16(roomptr + 0x19);
EXCD_len = READ_LE_UINT16(roomptr + 0x1B) - _EXCD_offs + _resourceHeaderSize; // HACK
}
if (_dumpScripts && _EXCD_offs)
dumpResource("exit-", _roomResource, roomptr + _EXCD_offs - _resourceHeaderSize, EXCD_len);
//
// Look for an entry script
//
int ENCD_len = -1;
if (_game.version <= 2) {
_ENCD_offs = READ_LE_UINT16(roomptr + 0x1A);
ENCD_len = READ_LE_UINT16(roomptr) - _ENCD_offs + _resourceHeaderSize; // HACK
} else {
_ENCD_offs = READ_LE_UINT16(roomptr + 0x1B);
// FIXME - the following is a hack which assumes that immediately after
// the entry script the first local script follows.
int num_objects = *(roomptr + 20);
int num_sounds = *(roomptr + 23);
int num_scripts = *(roomptr + 24);
ptr = roomptr + 29 + num_objects * 4 + num_sounds + num_scripts;
ENCD_len = READ_LE_UINT16(ptr + 1) - _ENCD_offs + _resourceHeaderSize; // HACK
}
if (_dumpScripts && _ENCD_offs)
dumpResource("entry-", _roomResource, roomptr + _ENCD_offs - _resourceHeaderSize, ENCD_len);
//
// Setup local scripts
//
// Determine the room script base address
roomptr = getResourceAddress(rtRoom, _roomResource);
searchptr = roomptr;
memset(_localScriptOffsets, 0, sizeof(_localScriptOffsets));
int num_objects = *(roomptr + 20);
int num_sounds;
int num_scripts;
if (_game.version <= 2) {
num_sounds = *(roomptr + 22);
num_scripts = *(roomptr + 23);
ptr = roomptr + 28 + num_objects * 4;
while (num_sounds--)
loadResource(rtSound, *ptr++);
while (num_scripts--)
loadResource(rtScript, *ptr++);
} else /* if (_game.version == 3) */ {
num_sounds = *(roomptr + 23);
num_scripts = *(roomptr + 24);
ptr = roomptr + 29 + num_objects * 4 + num_sounds + num_scripts;
while (*ptr) {
int id = *ptr;
_localScriptOffsets[id - _numGlobalScripts] = READ_LE_UINT16(ptr + 1);
ptr += 3;
if (_dumpScripts) {
char buf[32];
sprintf(buf, "room-%d-", _roomResource);
// HACK: to determine the sizes of the local scripts, we assume that
// a) their order in the data file is the same as in the index
// b) the last script at the same time is the last item in the room "header"
int len = - (int)_localScriptOffsets[id - _numGlobalScripts] + _resourceHeaderSize;
if (*ptr)
len += READ_LE_UINT16(ptr + 1);
else
len += READ_LE_UINT16(roomptr);
dumpResource(buf, id, roomptr + _localScriptOffsets[id - _numGlobalScripts] - _resourceHeaderSize, len);
}
}
}
_gdi->roomChanged(roomptr);
}
void ScummEngine_v3old::resetRoomSubBlocks() {
int i;
const byte *ptr;
byte *roomptr;
// Determine the room and room script base address
roomptr = getResourceAddress(rtRoom, _roomResource);
if (!roomptr)
error("Room %d: data not found (" __FILE__ ":%d)", _roomResource, __LINE__);
// Reset room color for V1 zak
if (_game.version <= 1)
_roomPalette[0] = 0;
//
// Load box data
//
_res->nukeResource(rtMatrix, 1);
_res->nukeResource(rtMatrix, 2);
if (_game.version <= 2)
ptr = roomptr + *(roomptr + 0x15);
else
ptr = roomptr + READ_LE_UINT16(roomptr + 0x15);
if (ptr) {
byte numOfBoxes = 0;
int size;
if (_game.version == 0) {
// Count number of boxes
while (*ptr != 0xFF) {
numOfBoxes++;
ptr += 5;
}
ptr = roomptr + *(roomptr + 0x15);
size = numOfBoxes * SIZEOF_BOX_C64 + 1;
_res->createResource(rtMatrix, 2, size + 1);
getResourceAddress(rtMatrix, 2)[0] = numOfBoxes;
memcpy(getResourceAddress(rtMatrix, 2) + 1, ptr, size);
} else {
numOfBoxes = *ptr;
if (_game.version <= 2)
size = numOfBoxes * SIZEOF_BOX_V2 + 1;
else
size = numOfBoxes * SIZEOF_BOX_V3 + 1;
_res->createResource(rtMatrix, 2, size);
memcpy(getResourceAddress(rtMatrix, 2), ptr, size);
}
ptr += size;
if (_game.version == 0) {
const byte *tmp = ptr;
size = 0;
// Compute matrix size
for (i = 0; i < numOfBoxes; i++) {
while (*tmp != 0xFF) {
size++;
tmp++;
}
size++;
tmp++;
}
} else if (_game.version <= 2) {
size = numOfBoxes * (numOfBoxes + 1);
} else {
// FIXME. This is an evil HACK!!!
size = (READ_LE_UINT16(roomptr + 0x0A) - READ_LE_UINT16(roomptr + 0x15)) - size;
}
if (size > 0) { // do this :)
_res->createResource(rtMatrix, 1, size);
memcpy(getResourceAddress(rtMatrix, 1), ptr, size);
}
}
//
// No scale data in old bundle games
//
for (i = 1; i < _res->num[rtScaleTable]; i++)
_res->nukeResource(rtScaleTable, i);
}
} // End of namespace Scumm