scummvm/engines/nancy/enginedata.cpp
Kaloyan Chehlarski 1781a1e140 NANCY: Fix SliderPuzzle for pre-nancy9 games
The last changes to the class broke older titles
which use the SPUZ chunk.
Fixes #15097
2024-05-05 21:03:05 +02:00

821 lines
25 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 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/>.
*
*/
#include "engines/nancy/enginedata.h"
#include "engines/nancy/nancy.h"
#include "engines/nancy/util.h"
#include "engines/nancy/graphics.h"
#include "common/serializer.h"
namespace Nancy {
EngineData::EngineData(Common::SeekableReadStream *chunkStream) {
assert(chunkStream);
chunkStream->seek(0);
}
BSUM::BSUM(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
Common::Serializer s(chunkStream, nullptr);
s.setVersion(g_nancy->getGameType());
// The header is used to verify savegames
s.syncBytes(header, 90);
s.skip(0x17, kGameTypeVampire, kGameTypeVampire);
s.skip(0x49, kGameTypeNancy1, kGameTypeNancy1);
s.skip(0x43, kGameTypeNancy2);
readFilename(s, conversationTextsFilename, kGameTypeNancy6);
readFilename(s, autotextFilename, kGameTypeNancy6);
s.syncAsUint16LE(firstScene.sceneID);
s.skip(0xC, kGameTypeVampire, kGameTypeVampire); // Palette name + unknown 2 bytes
s.syncAsUint16LE(firstScene.frameID);
s.syncAsUint16LE(firstScene.verticalOffset);
s.syncAsUint16LE(startTimeHours);
s.syncAsUint16LE(startTimeMinutes);
s.syncAsUint16LE(adScene.sceneID, kGameTypeNancy7);
s.syncAsUint16LE(adScene.frameID, kGameTypeNancy7);
s.syncAsUint16LE(adScene.verticalOffset, kGameTypeNancy7);
s.skip(0xA4, kGameTypeVampire, kGameTypeNancy2);
s.skip(3); // Number of object, frame, and logo images
if (g_nancy->getEngineData("PLG0")) {
// Parner logos were introduced with nancy4, but at least one nancy3 release
// had one as well. For some reason they didn't port over the code from the
// later games, but implemented it the same way the other BSUM images work.
// Hence, we skip an extra byte indicating the number of partner logos.
s.skip(1);
}
s.skip(8, kGameTypeVampire, kGameTypeVampire);
readRect(s, extraButtonHotspot, kGameTypeVampire, kGameTypeVampire);
readRect(s, extraButtonHotspot, kGameTypeNancy2);
readRect(s, extraButtonHighlightDest, kGameTypeNancy1);
s.skip(0x10, kGameTypeVampire, kGameTypeVampire);
readRect(s, textboxScreenPosition);
readRect(s, inventoryBoxScreenPosition);
readRect(s, menuButtonSrc);
readRect(s, helpButtonSrc);
readRect(s, menuButtonDest);
readRect(s, helpButtonDest);
readRect(s, menuButtonHighlightSrc, kGameTypeNancy2);
readRect(s, helpButtonHighlightSrc, kGameTypeNancy2);
readRect(s, clockHighlightSrc, kGameTypeNancy2);
s.skip(0x2, kGameTypeVampire, kGameTypeVampire);
s.syncAsByte(paletteTrans, kGameTypeVampire, kGameTypeVampire);
s.skip(0x2, kGameTypeVampire, kGameTypeVampire);
s.syncAsByte(rTrans);
s.syncAsByte(gTrans);
s.syncAsByte(bTrans);
s.skip(6); // Black and white
s.syncAsUint16LE(horizontalEdgesSize);
s.syncAsUint16LE(verticalEdgesSize);
s.syncAsUint16LE(numFonts);
// Skip data for debug features (diagnostics, version...)
s.skip(0x18, kGameTypeVampire, kGameTypeVampire);
s.skip(0x1A, kGameTypeNancy1);
s.syncAsSint16LE(playerTimeMinuteLength);
s.syncAsUint16LE(buttonPressTimeDelay);
s.syncAsUint16LE(dayStartMinutes, kGameTypeNancy6);
s.syncAsUint16LE(dayEndMinutes, kGameTypeNancy6);
s.syncAsByte(overrideMovementTimeDeltas);
s.syncAsSint16LE(slowMovementTimeDelta);
s.syncAsSint16LE(fastMovementTimeDelta);
}
VIEW::VIEW(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
readRect(*chunkStream, screenPosition);
readRect(*chunkStream, bounds);
}
PCAL::PCAL(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
uint num = chunkStream->readUint16LE();
readFilenameArray(*chunkStream, calNames, num);
}
INV::INV(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
Common::Serializer s(chunkStream, nullptr);
s.setVersion(g_nancy->getGameType());
readRect(*chunkStream, scrollbarSrcBounds);
s.syncAsUint16LE(scrollbarDefaultPos.x);
s.syncAsUint16LE(scrollbarDefaultPos.y);
s.syncAsUint16LE(scrollbarMaxScroll);
readRectArray(s, ornamentSrcs, 6, 6, kGameTypeVampire, kGameTypeNancy1);
readRectArray(s, ornamentDests, 6, 6, kGameTypeVampire, kGameTypeNancy1);
uint numFrames = g_nancy->getGameType() == kGameTypeVampire ? 10 : 7;
readRectArray(s, curtainAnimationSrcs, numFrames * 2);
readRect(s, curtainsScreenPosition);
s.syncAsUint16LE(curtainsFrameTime);
s.syncAsUint16LE(captionAutoClearTime, kGameTypeNancy3);
readFilename(s, inventoryBoxIconsImageName);
readFilename(s, inventoryCursorsImageName);
s.skip(0x4, kGameTypeVampire, kGameTypeNancy1); // inventory box icons surface w/h
s.skip(0x4, kGameTypeVampire, kGameTypeNancy1); // inventory cursors surface w/h
s.skip(0x10); // unknown rect, same size as a hotspot
byte textBuf[60];
if (s.getVersion() >= kGameTypeNancy2) {
cantSound.readNormal(*chunkStream);
s.syncBytes(textBuf, 60);
textBuf[59] = '\0';
cantText = (char *)textBuf;
}
uint itemNameLength;
switch (s.getVersion()) {
case kGameTypeVampire :
itemNameLength = 15;
break;
case kGameTypeNancy1 :
itemNameLength = 20;
break;
case kGameTypeNancy2 :
// fall through
default:
itemNameLength = 48;
break;
}
uint16 numItems = g_nancy->getStaticData().numItems;
itemDescriptions.resize(numItems);
for (uint i = 0; i < numItems; ++i) {
ItemDescription &item = itemDescriptions[i];
s.syncBytes(textBuf, itemNameLength);
textBuf[itemNameLength - 1] = '\0';
item.name = (char *)textBuf;
s.syncAsUint16LE(item.keepItem);
s.syncAsUint16LE(item.sceneID, kGameTypeNancy7);
s.syncAsUint16LE(item.sceneSoundFlag, kGameTypeNancy7);
readRect(s, item.sourceRect);
readRect(s, item.highlightedSourceRect, kGameTypeNancy2);
if (s.getVersion() == kGameTypeNancy2) {
s.syncBytes(textBuf, 60);
textBuf[59] = '\0';
assembleTextLine((char *)textBuf, item.cantText, 60);
s.syncBytes(textBuf, 60);
textBuf[59] = '\0';
assembleTextLine((char *)textBuf, item.cantTextNotHolding, 60);
item.cantSound.readNormal(*chunkStream);
item.cantSoundNotHolding.readNormal(*chunkStream);
} else if (s.getVersion() >= kGameTypeNancy3) {
s.syncBytes(textBuf, 60);
textBuf[59] = '\0';
assembleTextLine((char *)textBuf, item.cantText, 60);
item.cantSound.readNormal(*chunkStream);
}
}
}
TBOX::TBOX(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
bool isVampire = g_nancy->getGameType() == Nancy::GameType::kGameTypeVampire;
readRect(*chunkStream, scrollbarSrcBounds);
chunkStream->seek(0x20);
readRect(*chunkStream, innerBoundingBox);
scrollbarDefaultPos.x = chunkStream->readUint16LE() - (isVampire ? 1 : 0);
scrollbarDefaultPos.y = chunkStream->readUint16LE();
scrollbarMaxScroll = chunkStream->readUint16LE();
upOffset = chunkStream->readUint16LE() + 1;
downOffset = chunkStream->readUint16LE();
leftOffset = chunkStream->readUint16LE() - 1;
rightOffset = chunkStream->readUint16LE();
readRectArray(*chunkStream, ornamentSrcs, 14);
readRectArray(*chunkStream, ornamentDests, 14);
defaultFontID = chunkStream->readUint16LE();
defaultTextColor = chunkStream->readUint16LE();
if (g_nancy->getGameType() >= kGameTypeNancy2) {
conversationFontID = chunkStream->readUint16LE();
highlightConversationFontID = chunkStream->readUint16LE();
} else {
conversationFontID = defaultFontID;
highlightConversationFontID = defaultFontID;
}
tabWidth = chunkStream->readUint16LE();
pageScrollPercent = chunkStream->readUint16LE(); // Not implemented yet
Graphics::PixelFormat format = g_nancy->_graphics->getInputPixelFormat();
if (g_nancy->getGameType() >= kGameTypeNancy2) {
byte r, g, b;
r = chunkStream->readByte();
g = chunkStream->readByte();
b = chunkStream->readByte();
textBackground = (r << format.rShift) |
(g << format.gShift) |
(b << format.bShift);
r = chunkStream->readByte();
g = chunkStream->readByte();
b = chunkStream->readByte();
highlightTextBackground = (r << format.rShift) |
(g << format.gShift) |
(b << format.bShift);
} else {
textBackground = highlightTextBackground = 0;
}
}
MAP::MAP(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
Common::Serializer s(chunkStream, nullptr);
s.setVersion(g_nancy->getGameType());
uint numLocations = s.getVersion() == kGameTypeVampire ? 7 : 4;
uint numMaps = s.getVersion() == kGameTypeVampire ? 4 : 2;
readFilenameArray(s, mapNames, numMaps);
readFilenameArray(s, mapPaletteNames, numMaps, kGameTypeVampire, kGameTypeVampire);
s.skip(4);
sounds.resize(numMaps);
for (uint i = 0; i < numMaps; ++i) {
sounds[i].readMenu(*chunkStream);
}
s.skip(0x20);
s.syncAsUint16LE(globeFrameTime, kGameTypeVampire, kGameTypeVampire);
readRectArray(s, globeSrcs, 8, 8, kGameTypeVampire, kGameTypeVampire);
readRect(s, globeDest, kGameTypeVampire, kGameTypeVampire);
s.skip(2, kGameTypeNancy1);
readRect(s, buttonSrc, kGameTypeNancy1);
readRect(s, buttonDest, kGameTypeNancy1);
locations.resize(numLocations);
for (uint i = 0; i < numLocations; ++i) {
readRect(*chunkStream, locations[i].labelSrc);
}
readRect(s, closedLabelSrc);
readRect(s, globeGargoyleSrc, kGameTypeVampire, kGameTypeVampire);
readRect(s, globeGargoyleDest, kGameTypeVampire, kGameTypeVampire);
char buf[30];
for (uint i = 0; i < numLocations; ++i) {
s.syncBytes((byte *)buf, 30);
buf[29] = '\0';
locations[i].description = buf;
}
for (uint i = 0; i < numLocations; ++i) {
readRect(*chunkStream, locations[i].hotspot);
}
s.skip(numLocations * 2);
s.skip(0x10);
s.syncAsUint16LE(cursorPosition.x);
s.syncAsUint16LE(cursorPosition.y);
for (uint j = 0; j < 2; ++j) {
for (uint i = 0; i < numLocations; ++i) {
SceneChangeDescription &sc = locations[i].scenes[j];
s.syncAsUint16LE(sc.sceneID);
s.syncAsUint16LE(sc.frameID);
s.syncAsUint16LE(sc.verticalOffset);
s.syncAsUint16LE(sc.paletteID, kGameTypeVampire, kGameTypeVampire);
}
}
}
HELP::HELP(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
readFilename(*chunkStream, imageName);
chunkStream->skip(20);
if (g_nancy->getGameType() <= kGameTypeNancy1) {
buttonDest.left = chunkStream->readUint16LE();
buttonDest.top = chunkStream->readUint16LE();
buttonDest.right = chunkStream->readUint16LE();
buttonDest.bottom = chunkStream->readUint16LE();
buttonSrc.left = chunkStream->readUint16LE();
buttonSrc.top = chunkStream->readUint16LE();
buttonSrc.right = chunkStream->readUint16LE();
buttonSrc.bottom = chunkStream->readUint16LE();
} else {
readRect(*chunkStream, buttonDest);
readRect(*chunkStream, buttonSrc);
readRect(*chunkStream, buttonHoverSrc);
}
}
CRED::CRED(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
bool isVampire = g_nancy->getGameType() == kGameTypeVampire;
readFilename(*chunkStream, imageName);
textNames.resize(isVampire ? 7 : 1);
for (Common::Path &str : textNames) {
readFilename(*chunkStream, str);
}
chunkStream->skip(0x20);
readRect(*chunkStream, textScreenPosition);
chunkStream->skip(0x10);
updateTime = chunkStream->readUint16LE();
pixelsToScroll = chunkStream->readUint16LE();
sound.readMenu(*chunkStream);
}
MENU::MENU(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
Common::Serializer ser(chunkStream, nullptr);
ser.setVersion(g_nancy->getGameType());
readFilename(ser, _imageName);
ser.skip(22);
uint numOptions = g_nancy->getGameType() <= kGameTypeNancy6 ? 8 : 9;
readRectArray16(ser, _buttonDests, numOptions, numOptions, kGameTypeVampire, kGameTypeNancy1);
readRectArray16(ser, _buttonDownSrcs, numOptions, numOptions, kGameTypeVampire, kGameTypeNancy1);
readRectArray(ser, _buttonDests, numOptions, numOptions, kGameTypeNancy2);
readRectArray(ser, _buttonDownSrcs, numOptions, numOptions, kGameTypeNancy2);
readRectArray(ser, _buttonDisabledSrcs, numOptions, numOptions, kGameTypeNancy2);
readRectArray(ser, _buttonHighlightSrcs, numOptions, numOptions, kGameTypeNancy2);
}
SET::SET(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
readFilename(*chunkStream, _imageName);
chunkStream->skip(20); // image info
chunkStream->skip(16); // bounds for all scrollbars
uint numButtons;
if (g_nancy->getGameType() == kGameTypeVampire) {
numButtons = 5;
} else if (g_nancy->getGameType() <= kGameTypeNancy5) {
numButtons = 4;
} else {
numButtons = 3;
}
readRectArray(*chunkStream, _scrollbarBounds, 3);
readRectArray(*chunkStream, _buttonDests, numButtons);
readRectArray(*chunkStream, _buttonDownSrcs, numButtons);
if (g_nancy->getGameType() >= kGameTypeNancy2) {
readRect(*chunkStream, _doneButtonHighlightSrc);
}
readRectArray(*chunkStream, _scrollbarSrcs, 3);
_scrollbarsCenterYPos.resize(3);
_scrollbarsCenterXPosL.resize(3);
_scrollbarsCenterXPosR.resize(3);
for (uint i = 0; i < 3; ++i) {
_scrollbarsCenterYPos[i] = chunkStream->readUint16LE();
_scrollbarsCenterXPosL[i] = chunkStream->readUint16LE();
_scrollbarsCenterXPosR[i] = chunkStream->readUint16LE();
}
_sounds.resize(3);
for (uint i = 0; i < 3; ++i) {
_sounds[i].readMenu(*chunkStream);
}
}
LOAD::LOAD(Common::SeekableReadStream *chunkStream) :
EngineData(chunkStream),
_highlightFontID(-1),
_disabledFontID(-1),
_blinkingTimeDelay(0) {
Common::Serializer s(chunkStream, nullptr);
s.setVersion(g_nancy->getGameType());
if (s.getVersion() <= kGameTypeNancy7) {
// v1
readFilename(s, _image1Name);
s.skip(0x1F, kGameTypeVampire, kGameTypeVampire);
s.skip(0x23, kGameTypeNancy1);
s.skip(4);
s.syncAsSint16LE(_mainFontID);
s.syncAsSint16LE(_highlightFontID, kGameTypeNancy2);
s.syncAsSint16LE(_disabledFontID, kGameTypeNancy2);
s.syncAsSint16LE(_fontXOffset);
s.syncAsSint16LE(_fontYOffset);
s.skip(16);
if (s.getVersion() <= kGameTypeNancy1) {
readRectArray16(s, _saveButtonDests, 7);
readRectArray16(s, _loadButtonDests, 7);
readRectArray16(s, _textboxBounds, 7);
readRect16(s, _doneButtonDest);
readRectArray16(s, _saveButtonDownSrcs, 7);
readRectArray16(s, _loadButtonDownSrcs, 7);
s.skip(8 * 7);
readRect16(s, _doneButtonDownSrc);
readRect(s, _blinkingCursorSrc);
s.syncAsUint16LE(_blinkingTimeDelay, kGameTypeNancy1);
readRectArray(s, _cancelButtonSrcs, 7);
readRectArray(s, _cancelButtonDests, 7);
readRect(s, _cancelButtonDownSrc);
} else {
readRectArray(s, _saveButtonDests, 7);
readRectArray(s, _loadButtonDests, 7);
readRectArray(s, _textboxBounds, 7);
readRect(s, _doneButtonDest);
readRectArray(s, _saveButtonDownSrcs, 7);
readRectArray(s, _loadButtonDownSrcs, 7);
s.skip(16 * 7);
readRect(s, _doneButtonDownSrc);
readRectArray(s, _saveButtonHighlightSrcs, 7);
readRectArray(s, _loadButtonHighlightSrcs, 7);
s.skip(16 * 7);
readRect(s, _doneButtonHighlightSrc);
readRectArray(s, _saveButtonDisabledSrcs, 7);
readRectArray(s, _loadButtonDisabledSrcs, 7);
s.skip(16 * 7);
readRect(s, _doneButtonDisabledSrc);
readRect(s, _blinkingCursorSrc);
s.syncAsUint16LE(_blinkingTimeDelay);
readRectArray(s, _cancelButtonSrcs, 7);
readRectArray(s, _cancelButtonDests, 7);
readRect(s, _cancelButtonDownSrc);
readRect(s, _cancelButtonHighlightSrc);
readRect(s, _cancelButtonDisabledSrc);
readFilename(s, _gameSavedPopup, kGameTypeNancy3);
readFilename(s, _emptySaveText, kGameTypeNancy7);
readFilename(s, _defaultSaveNamePrefix, kGameTypeNancy7);
s.skip(16, kGameTypeNancy3);
}
} else {
// v2
readFilename(*chunkStream, _image1Name);
readFilename(*chunkStream, _image2Name);
readFilename(*chunkStream, _imageButtonsName);
readRectArray(*chunkStream, _unpressedButtonSrcs, 5);
readRectArray(*chunkStream, _pressedButtonSrcs, 5);
readRectArray(*chunkStream, _highlightedButtonSrcs, 5);
readRectArray(*chunkStream, _disabledButtonSrcs, 5);
readRectArray(*chunkStream, _buttonDests, 5);
readRectArray(*chunkStream, _textboxBounds, 10);
chunkStream->skip(25); // prefixes and suffixes for filenames
_mainFontID = chunkStream->readSint16LE();
_highlightFontID = chunkStream->readSint16LE();
_fontXOffset = chunkStream->readSint16LE();
_fontYOffset = chunkStream->readSint16LE();
chunkStream->skip(16); // src rect for dash in font
_blinkingTimeDelay = chunkStream->readUint16LE();
readFilename(*chunkStream, _gameSavedPopup);
readFilename(*chunkStream, _emptySaveText);
}
}
SDLG::SDLG(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
while (chunkStream->pos() < chunkStream->size()) {
dialogs.push_back(Dialog(chunkStream));
}
}
SDLG::Dialog::Dialog(Common::SeekableReadStream *chunkStream) {
readFilename(*chunkStream, imageName);
chunkStream->skip(16);
readRect(*chunkStream, yesDest);
readRect(*chunkStream, noDest);
readRect(*chunkStream, cancelDest);
chunkStream->skip(16);
readRect(*chunkStream, yesHighlightSrc);
readRect(*chunkStream, noHighlightSrc);
readRect(*chunkStream, cancelHighlightSrc);
readRect(*chunkStream, yesDownSrc);
readRect(*chunkStream, noDownSrc);
readRect(*chunkStream, cancelDownSrc);
}
HINT::HINT(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
uint size = chunkStream->size();
numHints.resize(size);
for (uint i = 0; i < size; ++i) {
numHints[i] = chunkStream->readByte();
}
}
SPUZ::SPUZ(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
tileOrder.resize(3);
for (uint difficulty = 0; difficulty < 3; ++difficulty) {
tileOrder[difficulty].resize(6);
for (uint y = 0; y < 6; ++y) {
tileOrder[difficulty][y].resize(6);
for (uint x = 0; x < 6; ++x) {
tileOrder[difficulty][y][x] = chunkStream->readSint16LE();
}
}
}
}
CLOK::CLOK(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
Common::Serializer s(chunkStream, nullptr);
s.setVersion(g_nancy->getGameType());
uint numFrames = s.getVersion() == kGameTypeVampire? 8 : 7;
readRectArray(s, animSrcs, numFrames);
readRectArray(s, animDests, numFrames, numFrames, kGameTypeNancy2);
readRect(s, staticImageSrc, kGameTypeNancy2);
readRect(s, staticImageDest, kGameTypeNancy2);
readRectArray(s, hoursHandSrcs, 12);
readRectArray(s, hoursHandDests, 12, 12, kGameTypeNancy2);
readRectArray(s, minutesHandSrcs, 4);
readRectArray(s, minutesHandDests, 4, 4, kGameTypeNancy2);
readRect(s, screenPosition, kGameTypeVampire, kGameTypeVampire);
readRectArray(s, hoursHandDests, 12, 12, kGameTypeVampire, kGameTypeVampire);
readRectArray(s, minutesHandDests, 4, 4, kGameTypeVampire, kGameTypeVampire);
readRect(s, staticImageSrc, kGameTypeVampire, kGameTypeVampire);
readRect(s, staticImageDest, kGameTypeVampire, kGameTypeVampire);
s.syncAsUint32LE(timeToKeepOpen);
s.syncAsUint16LE(frameTime);
s.syncAsByte(clockIsDisabled, kGameTypeNancy5);
s.syncAsByte(clockIsDay, kGameTypeNancy5);
s.syncAsUint32LE(countdownTime, kGameTypeNancy5);
s.skip(2, kGameTypeNancy5);
readRectArray(s, daySrcs, 3, 3, kGameTypeNancy5);
readRectArray(s, countdownSrcs, 13, 13, kGameTypeNancy5);
readRect(s, disabledSrc, kGameTypeNancy5);
}
SPEC::SPEC(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
fadeToBlackNumFrames = chunkStream->readByte();
fadeToBlackFrameTime = chunkStream->readUint16LE();
crossDissolveNumFrames = chunkStream->readUint16LE();
}
RCLB::RCLB(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
lightSwitchID = chunkStream->readUint16LE();
unk2 = chunkStream->readUint16LE();
char buf[100];
while (chunkStream->pos() < chunkStream->size()) {
themes.push_back(Theme());
Theme &theme = themes.back();
chunkStream->read(buf, 100);
theme.themeName = buf;
for (uint i = 0; i < 10; ++i) {
int32 val = chunkStream->readSint32LE();
if (val != -1) {
theme.wallIDs.push_back(val);
}
}
for (uint i = 0; i < 10; ++i) {
int16 val = chunkStream->readUint16LE();
if (val != -1) {
theme.floorIDs.push_back(val);
}
}
for (uint i = 0; i < 10; ++i) {
int16 val = chunkStream->readSint16LE();
if (val != -1) {
theme.exitFloorIDs.push_back(val);
}
}
for (uint i = 0; i < 10; ++i) {
int16 val = chunkStream->readSint16LE();
if (val != -1) {
theme.ceilingIDs.push_back(val);
}
}
for (uint i = 0; i < 10; ++i) {
int32 val = chunkStream->readSint32LE();
if (val != -1) {
theme.doorIDs.push_back(val);
}
}
for (uint i = 0; i < 10; ++i) {
int32 val = chunkStream->readSint32LE();
if (val != -1) {
theme.transparentwallIDs.push_back(val);
}
}
for (uint i = 0; i < 10; ++i) {
int32 val = chunkStream->readSint32LE();
if (val != -1) {
theme.objectwallIDs.push_back(val);
}
}
for (uint i = 0; i < 10; ++i) {
int16 val = chunkStream->readSint16LE();
if (val != -1) {
theme.objectWallHeights.push_back(val);
}
}
theme.generalLighting = chunkStream->readUint16LE();
theme.hasLightSwitch = chunkStream->readUint16LE();
theme.transparentWallDensity = chunkStream->readSint16LE();
theme.objectWallDensity = chunkStream->readSint16LE();
theme.doorDensity = chunkStream->readSint16LE();
}
}
RCPR::RCPR(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
readRectArray(*chunkStream, screenViewportSizes, 6);
viewportSizeUsed = chunkStream->readUint16LE();
wallColor[0] = chunkStream->readByte();
wallColor[1] = chunkStream->readByte();
wallColor[2] = chunkStream->readByte();
playerColor[0] = chunkStream->readByte();
playerColor[1] = chunkStream->readByte();
playerColor[2] = chunkStream->readByte();
doorColor[0] = chunkStream->readByte();
doorColor[1] = chunkStream->readByte();
doorColor[2] = chunkStream->readByte();
lightSwitchColor[0] = chunkStream->readByte();
lightSwitchColor[1] = chunkStream->readByte();
lightSwitchColor[2] = chunkStream->readByte();
exitColor[0] = chunkStream->readByte();
exitColor[1] = chunkStream->readByte();
exitColor[2] = chunkStream->readByte();
uColor6[0] = chunkStream->readByte();
uColor6[1] = chunkStream->readByte();
uColor6[2] = chunkStream->readByte();
uColor7[0] = chunkStream->readByte();
uColor7[1] = chunkStream->readByte();
uColor7[2] = chunkStream->readByte();
uColor8[0] = chunkStream->readByte();
uColor8[1] = chunkStream->readByte();
uColor8[2] = chunkStream->readByte();
transparentWallColor[0] = chunkStream->readByte();
transparentWallColor[1] = chunkStream->readByte();
transparentWallColor[2] = chunkStream->readByte();
uColor10[0] = chunkStream->readByte();
uColor10[1] = chunkStream->readByte();
uColor10[2] = chunkStream->readByte();
Common::Path tmp;
while (chunkStream->pos() < chunkStream->size()) {
readFilename(*chunkStream, tmp);
Common::String baseName(tmp.baseName());
if (baseName.hasPrefixIgnoreCase("Wall")) {
wallNames.push_back(tmp);
} else if (baseName.hasPrefixIgnoreCase("SpW")) {
specialWallNames.push_back(tmp);
} else if (baseName.hasPrefixIgnoreCase("Ceil")) {
ceilingNames.push_back(tmp);
} else if (baseName.hasPrefixIgnoreCase("Floor")) {
floorNames.push_back(tmp);
}
}
}
ImageChunk::ImageChunk(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
readFilename(*chunkStream, imageName);
width = chunkStream->readUint16LE();
height = chunkStream->readUint16LE();
}
CVTX::CVTX(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
uint16 numEntries = chunkStream->readUint16LE();
char *buf = nullptr;
uint bufSize = 0;
Common::String keyName;
for (uint i = 0; i < numEntries; ++i) {
readFilename(*chunkStream, keyName);
uint16 stringSize = chunkStream->readUint16LE();
if (stringSize > bufSize) {
delete[] buf;
buf = new char[stringSize * 2];
bufSize = stringSize * 2;
}
if (buf) {
chunkStream->read(buf, stringSize);
buf[stringSize] = '\0';
texts.setVal(keyName, buf);
} else {
texts.setVal(keyName, Common::String());
}
}
delete[] buf;
}
TABL::TABL(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
uint numEntries = chunkStream->readUint16LE();
readFilename(*chunkStream, soundBaseName);
startIDs.resize(numEntries);
for (uint i = 0; i < numEntries; ++i) {
startIDs[i] = chunkStream->readUint16LE();
}
chunkStream->skip((20 - numEntries) * 2);
correctIDs.resize(numEntries);
for (uint i = 0; i < numEntries; ++i) {
correctIDs[i] = chunkStream->readUint16LE();
}
chunkStream->skip((20 - numEntries) * 2);
readRectArray(*chunkStream, srcRects, numEntries, 20);
char buf[1000];
strings.resize(numEntries);
for (uint i = 0; i < numEntries; ++i) {
chunkStream->read(buf, 1000);
assembleTextLine(buf, strings[i], 1000);
}
chunkStream->skip((20 - numEntries) * 1000);
}
MARK::MARK(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
readRectArray(*chunkStream, _markSrcs, 5);
}
} // End of namespace Nancy