Files
2026-02-02 04:50:13 +01:00

251 lines
7.1 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 "mediastation/mediastation.h"
#include "mediastation/context.h"
#include "mediastation/debugchannels.h"
#include "mediastation/bitmap.h"
#include "mediastation/mediascript/collection.h"
#include "mediastation/mediascript/function.h"
#include "mediastation/actors/camera.h"
#include "mediastation/actors/canvas.h"
#include "mediastation/actors/palette.h"
#include "mediastation/actors/image.h"
#include "mediastation/actors/path.h"
#include "mediastation/actors/sound.h"
#include "mediastation/actors/movie.h"
#include "mediastation/actors/sprite.h"
#include "mediastation/actors/stage.h"
#include "mediastation/actors/hotspot.h"
#include "mediastation/actors/timer.h"
#include "mediastation/actors/screen.h"
#include "mediastation/actors/font.h"
#include "mediastation/actors/text.h"
namespace MediaStation {
Context::~Context() {
for (auto it = _variables.begin(); it != _variables.end(); ++it) {
delete it->_value;
}
_variables.clear();
}
void MediaStationEngine::readControlCommands(Chunk &chunk) {
ContextSectionType sectionType = kContextEndOfSection;
do {
sectionType = static_cast<ContextSectionType>(chunk.readTypedUint16());
debugC(5, kDebugLoading, "%s: sectionType = 0x%x (@0x%llx)", __func__, static_cast<uint>(sectionType), static_cast<long long int>(chunk.pos()));
if (sectionType != kContextEndOfSection) {
readCommandFromStream(chunk, sectionType);
}
} while (sectionType != kContextEndOfSection);
}
void MediaStationEngine::readCreateContextData(Chunk &chunk) {
uint contextId = chunk.readTypedUint16();
debugC(5, kDebugLoading, "%s: Context %d", __func__, contextId);
Context *context = _loadedContexts.getValOrDefault(contextId);
if (context == nullptr) {
context = new Context();
context->_id = contextId;
_loadedContexts.setVal(contextId, context);
}
}
void MediaStationEngine::readDestroyContextData(Chunk &chunk) {
uint contextId = chunk.readTypedUint16();
debugC(5, kDebugLoading, "%s: Context %d", __func__, contextId);
destroyContext(contextId);
}
void MediaStationEngine::readDestroyActorData(Chunk &chunk) {
uint actorId = chunk.readTypedUint16();
debugC(5, kDebugLoading, "%s: Actor %d", __func__, actorId);
destroyActor(actorId);
}
void MediaStationEngine::readActorLoadComplete(Chunk &chunk) {
uint actorId = chunk.readTypedUint16();
debugC(5, kDebugLoading, "%s: Actor %d", __func__, actorId);
Actor *actor = g_engine->getActorById(actorId);
actor->loadIsComplete();
}
void MediaStationEngine::readCreateActorData(Chunk &chunk) {
uint contextId = chunk.readTypedUint16();
ActorType type = static_cast<ActorType>(chunk.readTypedUint16());
uint id = chunk.readTypedUint16();
debugC(5, kDebugLoading, "%s: Actor %d, type 0x%x", __func__, id, static_cast<uint>(type));
Actor *actor = nullptr;
switch (type) {
case kActorTypeImage:
actor = new ImageActor();
break;
case kActorTypeMovie:
actor = new StreamMovieActor();
break;
case kActorTypeSound:
actor = new SoundActor();
break;
case kActorTypePalette:
actor = new PaletteActor();
break;
case kActorTypePath:
actor = new PathActor();
break;
case kActorTypeTimer:
actor = new TimerActor();
break;
case kActorTypeHotspot:
actor = new HotspotActor();
break;
case kActorTypeSprite:
actor = new SpriteMovieActor();
break;
case kActorTypeCanvas:
actor = new CanvasActor();
break;
case kActorTypeCamera:
actor = new CameraActor();
break;
case kActorTypeStage:
actor = new StageActor();
break;
case kActorTypeScreen:
actor = new ScreenActor();
break;
case kActorTypeFont:
actor = new FontActor();
break;
case kActorTypeText:
actor = new TextActor();
break;
default:
error("%s: No class for actor type 0x%x (@0x%llx)", __func__, static_cast<uint>(type), static_cast<long long int>(chunk.pos()));
}
actor->setId(id);
actor->setContextId(contextId);
actor->initFromParameterStream(chunk);
g_engine->registerActor(actor);
}
void MediaStationEngine::readCreateVariableData(Chunk &chunk) {
uint contextId = chunk.readTypedUint16();
uint id = chunk.readTypedUint16();
if (g_engine->getVariable(id) != nullptr) {
error("%s: Global variable %d already exists", __func__, id);
}
ScriptValue *value = new ScriptValue(&chunk);
Context *context = _loadedContexts.getValOrDefault(contextId);
if (context == nullptr) {
error("%s: Context %d does not exist or has not been loaded yet in this title", __func__, contextId);
}
context->_variables.setVal(id, value);
debugC(5, kDebugScript, "%s: %d (type: %s)", __func__, id, scriptValueTypeToStr(value->getType()));
}
void MediaStationEngine::readHeaderSections(Subfile &subfile, Chunk &chunk) {
do {
ChannelClient *actor = g_engine->getChannelClientByChannelIdent(chunk._id);
if (actor == nullptr) {
error("%s: Client \"%s\" (0x%x) does not exist or has not been read yet in this title. (@0x%llx)", __func__, tag2str(chunk._id), chunk._id, static_cast<long long int>(chunk.pos()));
}
if (chunk.bytesRemaining() > 0) {
actor->readChunk(chunk);
}
if (chunk.bytesRemaining() != 0) {
warning("%s: %d bytes remaining at end of chunk", __func__, chunk.bytesRemaining());
}
if (!subfile.atEnd()) {
chunk = subfile.nextChunk();
}
} while (!subfile.atEnd());
}
void MediaStationEngine::readContextNameData(Chunk &chunk) {
uint contextId = chunk.readTypedUint16();
debugC(5, kDebugLoading, "%s: Context %d", __func__, contextId);
Context *context = _loadedContexts.getValOrDefault(contextId);
if (context == nullptr) {
error("%s: Context %d does not exist or has not been loaded yet in this title", __func__, contextId);
}
context->_name = chunk.readTypedString();
}
void MediaStationEngine::readCommandFromStream(Chunk &chunk, ContextSectionType sectionType) {
switch (sectionType) {
case kContextCreateData:
readCreateContextData(chunk);
break;
case kContextDestroyData:
readDestroyContextData(chunk);
break;
case kContextCreateActorData:
readCreateActorData(chunk);
break;
case kContextDestroyActorData:
readDestroyActorData(chunk);
break;
case kContextActorLoadComplete:
readActorLoadComplete(chunk);
break;
case kContextCreateVariableData:
readCreateVariableData(chunk);
break;
case kContextNameData:
readContextNameData(chunk);
break;
default:
readUnrecognizedFromStream(chunk, static_cast<uint>(sectionType));
break;
}
}
} // End of namespace MediaStation