/* 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 .
*
*/
#include "mediastation/boot.h"
#include "mediastation/debugchannels.h"
#include "mediastation/mediastation.h"
namespace MediaStation {
#pragma region ContextReference
ContextReference::ContextReference(Chunk &chunk) {
// Read the file number.
ContextReferenceSectionType sectionType = getSectionType(chunk);
if (kContextReferenceContextId != sectionType) {
error("%s: Got unexpected section type %d", __func__, static_cast(sectionType));
}
_contextId = chunk.readTypedUint16();
sectionType = getSectionType(chunk);
if (kContextReferenceStreamId != sectionType) {
error("%s: Got unexpected section type %d", __func__, static_cast(sectionType));
}
_streamId = chunk.readTypedUint16();
// Read the context name. Only some titles have context names,
// and unfortunately we can't determine which just by relying
// on the title compiler version number.
sectionType = getSectionType(chunk);
if (kContextReferenceName == sectionType) {
_name = chunk.readTypedString();
sectionType = getSectionType(chunk);
}
// Read the parent context IDs. We don't know how many file
// references there are beforehand, so we'll just read until
// we get something else.
uint rewindOffset = chunk.pos();
while (kContextReferenceParentContextId == sectionType) {
int fileReference = chunk.readTypedUint16();
_parentContextIds.push_back(fileReference);
rewindOffset = chunk.pos();
sectionType = getSectionType(chunk);
}
chunk.seek(rewindOffset);
}
ContextReferenceSectionType ContextReference::getSectionType(Chunk &chunk) {
return static_cast(chunk.readTypedUint16());
}
#pragma endregion
#pragma region ScreenReference
ScreenReference::ScreenReference(Chunk &chunk) {
// Make sure this declaration isn't empty.
ScreenReferenceSectionType sectionType = getSectionType(chunk);
if (kScreenReferenceScreenId != sectionType) {
error("%s: Got unexpected section type %d", __func__, static_cast(sectionType));
}
_screenActorId = chunk.readTypedUint16();
sectionType = getSectionType(chunk);
if (kScreenReferenceContextId != sectionType) {
error("%s: Got unexpected section type %d", __func__, static_cast(sectionType));
}
_contextId = chunk.readTypedUint16();
}
ScreenReferenceSectionType ScreenReference::getSectionType(Chunk &chunk) {
return static_cast(chunk.readTypedUint16());
}
#pragma endregion
#pragma region FileInfo
FileInfo::FileInfo(Chunk &chunk) {
// Read the file ID.
FileInfoSectionType sectionType = getSectionType(chunk);
if (kFileInfoFileId != sectionType) {
error("%s: Got unexpected section type %d", __func__, static_cast(sectionType));
}
_id = chunk.readTypedUint16();
// Read the intended file location.
sectionType = getSectionType(chunk);
if (kFileInfoFileNameAndType != sectionType) {
error("%s: Got unexpected section type %d", __func__, static_cast(sectionType));
}
_intendedLocation = static_cast(chunk.readTypedUint16());
// Since the platforms that Media Station originally targeted were case-insensitive,
// the case of these filenames might not match the case of the files actually in
// the directory. All files should be matched case-insensitively.
_name = chunk.readTypedFilename();
}
FileInfoSectionType FileInfo::getSectionType(Chunk &chunk) {
return static_cast(chunk.readTypedUint16());
}
#pragma endregion
#pragma region StreamInfo
StreamInfo::StreamInfo(Chunk &chunk) {
// Read the actor ID.
StreamInfoSectionType sectionType = getSectionType(chunk);
if (kStreamInfoActorId != sectionType) {
error("%s: Got unexpected section type %d", __func__, static_cast(sectionType));
}
_actorId = chunk.readTypedUint16();
// Read the file ID.
sectionType = getSectionType(chunk);
if (kStreamInfoFileId != sectionType) {
error("%s: Expected section type FILE_ID, got 0x%x", __func__, static_cast(sectionType));
}
_fileId = chunk.readTypedUint16();
// Read the start offset from the absolute start of the file.
sectionType = getSectionType(chunk);
if (kStreamInfoStartOffset != sectionType) {
error("%s: Expected section type START_OFFSET, got 0x%x", __func__, static_cast(sectionType));
}
_startOffsetInFile = chunk.readTypedUint32();
}
StreamInfoSectionType StreamInfo::getSectionType(Chunk &chunk) {
return static_cast(chunk.readTypedUint16());
}
#pragma endregion
#pragma region CursorDeclaration
CursorDeclaration::CursorDeclaration(Chunk &chunk) {
uint16 unk1 = chunk.readTypedUint16(); // Always 0x0001
_id = chunk.readTypedUint16();
_unk = chunk.readTypedUint16();
_name = chunk.readTypedFilename();
debugC(5, kDebugLoading, " - CursorDeclaration(): unk1 = 0x%x, id = 0x%x, unk = 0x%x, name = %s", unk1, _id, _unk, _name.c_str());
}
#pragma endregion
#pragma region Boot
void MediaStationEngine::readDocumentDef(Chunk &chunk) {
BootSectionType sectionType = kBootLastSection;
while (true) {
sectionType = static_cast(chunk.readTypedUint16());
if (sectionType == kBootLastSection) {
break;
}
readDocumentInfoFromStream(chunk, sectionType);
}
}
void MediaStationEngine::readDocumentInfoFromStream(Chunk &chunk, BootSectionType sectionType) {
switch (sectionType) {
case kBootVersionInformation:
readVersionInfoFromStream(chunk);
break;
case kBootContextReference:
readContextReferencesFromStream(chunk);
break;
case kBootScreenReference:
readScreenReferencesFromStream(chunk);
break;
case kBootFileInfo:
readAndAddFileMaps(chunk);
break;
case kBootStreamInfo:
readAndAddStreamMaps(chunk);
break;
case kBootUnk1:
_unk1 = chunk.readTypedUint16();
break;
case kBootFunctionTableSize:
_functionTableSize = chunk.readTypedUint16();
break;
case kBootUnk3:
_unk3 = chunk.readTypedUint16();
break;
default:
// See if any registered parameter clients know how to
// handle this parameter.
readUnrecognizedFromStream(chunk, static_cast(sectionType));
}
}
void MediaStationEngine::readVersionInfoFromStream(Chunk &chunk) {
_gameTitle = chunk.readTypedString();
_versionInfo = chunk.readTypedVersion();
_engineInfo = chunk.readTypedString();
_sourceString = chunk.readTypedString();
}
void MediaStationEngine::readContextReferencesFromStream(Chunk &chunk) {
uint flag = chunk.readTypedUint16();
while (flag != 0) {
ContextReference contextReference(chunk);
_contextReferences.setVal(contextReference._contextId, contextReference);
flag = chunk.readTypedUint16();
}
}
void MediaStationEngine::readScreenReferencesFromStream(Chunk &chunk) {
uint flag = chunk.readTypedUint16();
while (flag != 0) {
ScreenReference screenDeclaration(chunk);
_screenReferences.setVal(screenDeclaration._screenActorId, screenDeclaration);
flag = chunk.readTypedUint16();
}
}
void MediaStationEngine::readAndAddFileMaps(Chunk &chunk) {
uint flag = chunk.readTypedUint16();
while (flag != 0) {
FileInfo fileDeclaration(chunk);
_fileMap.setVal(fileDeclaration._id, fileDeclaration);
flag = chunk.readTypedUint16();
}
}
void MediaStationEngine::readAndAddStreamMaps(Chunk &chunk) {
uint flag = chunk.readTypedUint16();
while (flag != 0) {
StreamInfo subfileDeclaration(chunk);
_streamMap.setVal(subfileDeclaration._actorId, subfileDeclaration);
flag = chunk.readTypedUint16();
}
}
#pragma endregion
} // End of namespace MediaStation