mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 04:28:37 +00:00
2050ae13b6
These are flagged by GCC if -Wswitch-default is enabled.
515 lines
12 KiB
C++
515 lines
12 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 "neverhood/diskplayerscene.h"
|
|
#include "neverhood/mouse.h"
|
|
#include "neverhood/smackerplayer.h"
|
|
|
|
namespace Neverhood {
|
|
|
|
static const uint32 kDiskplayerPaletteFileHashes[] = {
|
|
0x03B78240,
|
|
0x34B32B08,
|
|
0x4F2569D4,
|
|
0x07620590,
|
|
0x38422401
|
|
};
|
|
|
|
static const byte kDiskplayerInitArray[] = {
|
|
2, 1, 4, 5, 3, 11, 8, 6, 7, 9, 10, 17, 16, 18, 19, 20, 15, 14, 13, 12
|
|
};
|
|
|
|
static const uint32 kDiskplayerSmackerFileHashes[] = {
|
|
0x010A2810,
|
|
0x020A2810,
|
|
0x040A2810,
|
|
0x080A2810,
|
|
0x100A2810,
|
|
0x200A2810,
|
|
0x400A2810,
|
|
0x800A2810,
|
|
0x000A2811,
|
|
0x010C2810,
|
|
0x020C2810,
|
|
0x040C2810,
|
|
0x080C2810,
|
|
0x100C2810,
|
|
0x200C2810,
|
|
0x400C2810,
|
|
0x800C2810,
|
|
0x000C2811,
|
|
0x000C2812,
|
|
0x02002810,
|
|
0x04002810
|
|
};
|
|
|
|
static const uint32 kDiskplayerSlotFileHashes1[] = {
|
|
0x81312280,
|
|
0x01312281,
|
|
0x01312282,
|
|
0x01312284,
|
|
0x01312288,
|
|
0x01312290,
|
|
0x013122A0,
|
|
0x013122C0,
|
|
0x01312200,
|
|
0x82312280,
|
|
0x02312281,
|
|
0x02312282,
|
|
0x02312284,
|
|
0x02312288,
|
|
0x02312290,
|
|
0x023122A0,
|
|
0x023122C0,
|
|
0x02312200,
|
|
0x02312380,
|
|
0x04312281
|
|
};
|
|
|
|
static const uint32 kDiskplayerSlotFileHashes2[] = {
|
|
0x90443A00,
|
|
0x90443A18,
|
|
0x90443A28,
|
|
0x90443A48,
|
|
0x90443A88,
|
|
0x90443B08,
|
|
0x90443808,
|
|
0x90443E08,
|
|
0x90443208,
|
|
0xA0443A00,
|
|
0xA0443A18,
|
|
0xA0443A28,
|
|
0xA0443A48,
|
|
0xA0443A88,
|
|
0xA0443B08,
|
|
0xA0443808,
|
|
0xA0443E08,
|
|
0xA0443208,
|
|
0xA0442A08,
|
|
0xC0443A18
|
|
};
|
|
|
|
static const uint32 kDiskplayerSlotFileHashes3[] = {
|
|
0x10357320,
|
|
0x10557320,
|
|
0x10957320,
|
|
0x11157320,
|
|
0x12157320,
|
|
0x14157320,
|
|
0x18157320,
|
|
0x00157320,
|
|
0x30157320,
|
|
0x1035B320,
|
|
0x1055B320,
|
|
0x1095B320,
|
|
0x1115B320,
|
|
0x1215B320,
|
|
0x1415B320,
|
|
0x1815B320,
|
|
0x0015B320,
|
|
0x3015B320,
|
|
0x5015B320,
|
|
0x10543320
|
|
};
|
|
|
|
static const uint32 kDiskplayerSlotFileHashes4[] = {
|
|
0xDC8020E4,
|
|
0xDC802164,
|
|
0xDC802264,
|
|
0xDC802464,
|
|
0xDC802864,
|
|
0xDC803064,
|
|
0xDC800064,
|
|
0xDC806064,
|
|
0xDC80A064,
|
|
0xDC8020E7,
|
|
0xDC802167,
|
|
0xDC802267,
|
|
0xDC802467,
|
|
0xDC802867,
|
|
0xDC803067,
|
|
0xDC800067,
|
|
0xDC806067,
|
|
0xDC80A067,
|
|
0xDC812067,
|
|
0xDC802161
|
|
};
|
|
|
|
AsDiskplayerSceneKey::AsDiskplayerSceneKey(NeverhoodEngine *vm)
|
|
: AnimatedSprite(vm, 1100) {
|
|
|
|
createSurface1(0x100B90B4, 1200);
|
|
_x = 211;
|
|
_y = 195;
|
|
startAnimation(0x100B90B4, 0, -1);
|
|
_newStickFrameIndex = 0;
|
|
_needRefresh = true;
|
|
updatePosition();
|
|
setVisible(false);
|
|
}
|
|
|
|
uint32 AsDiskplayerSceneKey::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) {
|
|
uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
|
|
switch (messageNum) {
|
|
case NM_ANIMATION_STOP:
|
|
gotoNextState();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return messageResult;
|
|
}
|
|
|
|
void AsDiskplayerSceneKey::stDropKey() {
|
|
startAnimation(0x100B90B4, 0, -1);
|
|
SetUpdateHandler(&AnimatedSprite::update);
|
|
SetMessageHandler(&AsDiskplayerSceneKey::handleMessage);
|
|
NextState(&AsDiskplayerSceneKey::stDropKeyDone);
|
|
setVisible(true);
|
|
}
|
|
|
|
void AsDiskplayerSceneKey::stDropKeyDone() {
|
|
stopAnimation();
|
|
SetUpdateHandler(&AnimatedSprite::update);
|
|
SetMessageHandler(&Sprite::handleMessage);
|
|
setVisible(false);
|
|
}
|
|
|
|
DiskplayerPlayButton::DiskplayerPlayButton(NeverhoodEngine *vm, DiskplayerScene *diskplayerScene)
|
|
: StaticSprite(vm, 1400), _diskplayerScene(diskplayerScene), _isPlaying(false) {
|
|
|
|
loadSprite(0x24A4A664, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
|
|
setVisible(false);
|
|
loadSound(0, 0x44043000);
|
|
loadSound(1, 0x44045000);
|
|
SetMessageHandler(&DiskplayerPlayButton::handleMessage);
|
|
}
|
|
|
|
uint32 DiskplayerPlayButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) {
|
|
uint32 messageResult = 0;
|
|
Sprite::handleMessage(messageNum, param, sender);
|
|
switch (messageNum) {
|
|
case 0x1011:
|
|
if (!_diskplayerScene->getDropKey()) {
|
|
if (_isPlaying) {
|
|
sendMessage(_diskplayerScene, 0x2001, 0);
|
|
release();
|
|
} else {
|
|
sendMessage(_diskplayerScene, 0x2000, 0);
|
|
press();
|
|
}
|
|
}
|
|
updatePosition();
|
|
messageResult = 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return messageResult;
|
|
}
|
|
|
|
void DiskplayerPlayButton::press() {
|
|
if (!_isPlaying) {
|
|
setVisible(true);
|
|
updatePosition();
|
|
playSound(0);
|
|
_isPlaying = true;
|
|
}
|
|
}
|
|
|
|
void DiskplayerPlayButton::release() {
|
|
if (_isPlaying) {
|
|
setVisible(false);
|
|
updatePosition();
|
|
playSound(1);
|
|
_isPlaying = false;
|
|
}
|
|
}
|
|
|
|
DiskplayerSlot::DiskplayerSlot(NeverhoodEngine *vm, DiskplayerScene *diskplayerScene, int slotIndex, bool isAvailable)
|
|
: Entity(vm, 0), _diskplayerScene(diskplayerScene), _isLocked(false), _isBlinking(false),
|
|
_blinkCountdown(0), _initialBlinkCountdown(2), _inactiveSlot(NULL), _appearSlot(NULL), _activeSlot(NULL) {
|
|
|
|
if (isAvailable && slotIndex < 20) {
|
|
_inactiveSlot = _diskplayerScene->addSprite(new StaticSprite(_vm, kDiskplayerSlotFileHashes1[slotIndex], 1100));
|
|
_appearSlot = _diskplayerScene->addSprite(new StaticSprite(_vm, kDiskplayerSlotFileHashes2[slotIndex], 1000));
|
|
_activeSlot = _diskplayerScene->addSprite(new StaticSprite(_vm, kDiskplayerSlotFileHashes3[slotIndex], 1100));
|
|
_inactiveSlot->setVisible(false);
|
|
_appearSlot->setVisible(false);
|
|
_activeSlot->setVisible(false);
|
|
loadSound(0, 0x46210074);
|
|
setSoundPan(0, slotIndex * 100 / 19);
|
|
} else if (slotIndex != 20) {
|
|
_activeSlot = _diskplayerScene->addSprite(new StaticSprite(_vm, kDiskplayerSlotFileHashes4[slotIndex], 1100));
|
|
_activeSlot->setVisible(false);
|
|
}
|
|
SetUpdateHandler(&DiskplayerSlot::update);
|
|
}
|
|
|
|
void DiskplayerSlot::update() {
|
|
if (_blinkCountdown != 0 && (--_blinkCountdown == 0)) {
|
|
if (_isBlinking) {
|
|
if (_inactiveSlot)
|
|
_inactiveSlot->setVisible(true);
|
|
if (_activeSlot)
|
|
_activeSlot->setVisible(false);
|
|
_blinkCountdown = _initialBlinkCountdown / 2;
|
|
} else {
|
|
if (_inactiveSlot)
|
|
_inactiveSlot->setVisible(false);
|
|
if (_activeSlot)
|
|
_activeSlot->setVisible(true);
|
|
_blinkCountdown = _initialBlinkCountdown;
|
|
}
|
|
_isBlinking = !_isBlinking;
|
|
}
|
|
}
|
|
|
|
void DiskplayerSlot::appear() {
|
|
if (_inactiveSlot)
|
|
_inactiveSlot->setVisible(true);
|
|
if (_appearSlot)
|
|
_appearSlot->setVisible(true);
|
|
if (_inactiveSlot)
|
|
playSound(0);
|
|
}
|
|
|
|
void DiskplayerSlot::play() {
|
|
if (!_isLocked) {
|
|
if (_inactiveSlot)
|
|
_inactiveSlot->setVisible(false);
|
|
if (_activeSlot)
|
|
_activeSlot->setVisible(true);
|
|
_isBlinking = true;
|
|
_blinkCountdown = 0;
|
|
}
|
|
}
|
|
|
|
void DiskplayerSlot::activate() {
|
|
if (!_isLocked)
|
|
_blinkCountdown = _initialBlinkCountdown;
|
|
}
|
|
|
|
void DiskplayerSlot::stop() {
|
|
if (!_isLocked) {
|
|
if (_inactiveSlot)
|
|
_inactiveSlot->setVisible(true);
|
|
if (_activeSlot)
|
|
_activeSlot->setVisible(false);
|
|
_isBlinking = false;
|
|
_blinkCountdown = 0;
|
|
}
|
|
}
|
|
|
|
DiskplayerScene::DiskplayerScene(NeverhoodEngine *vm, Module *parentModule, int paletteIndex)
|
|
: Scene(vm, parentModule), _diskIndex(0), _appearCountdown(0), _tuneInCountdown(0),
|
|
_hasAllDisks(false), _dropKey(false), _inputDisabled(true), _updateStatus(kUSStopped) {
|
|
|
|
int availableDisksCount = 0;
|
|
|
|
setBackground(0x8A000044);
|
|
setPalette(kDiskplayerPaletteFileHashes[paletteIndex]);
|
|
|
|
_ssPlayButton = insertSprite<DiskplayerPlayButton>(this);
|
|
addCollisionSprite(_ssPlayButton);
|
|
|
|
_asKey = insertSprite<AsDiskplayerSceneKey>();
|
|
|
|
for (int i = 0; i < 20; i++) {
|
|
_diskAvailable[i] = false;
|
|
if (getSubVar(VA_IS_TAPE_INSERTED, i))
|
|
availableDisksCount++;
|
|
}
|
|
|
|
for (int i = 0; i < availableDisksCount; i++)
|
|
_diskAvailable[kDiskplayerInitArray[i] - 1] = true;
|
|
|
|
for (int slotIndex = 0; slotIndex < 20; slotIndex++) {
|
|
_diskSlots[slotIndex] = new DiskplayerSlot(_vm, this, slotIndex, _diskAvailable[slotIndex]);
|
|
addEntity(_diskSlots[slotIndex]);
|
|
}
|
|
|
|
_hasAllDisks = availableDisksCount == 20;
|
|
|
|
if (_hasAllDisks && !getGlobalVar(V_HAS_FINAL_KEY))
|
|
_dropKey = true;
|
|
|
|
_finalDiskSlot = new DiskplayerSlot(_vm, this, 20, false);
|
|
addEntity(_finalDiskSlot);
|
|
|
|
insertPuzzleMouse(0x000408A8, 20, 620);
|
|
showMouse(false);
|
|
|
|
_diskSmackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x08288103, false, true));
|
|
_diskSmackerPlayer->setDrawPos(154, 86);
|
|
_vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder());
|
|
|
|
_palette->usePalette();
|
|
|
|
SetMessageHandler(&DiskplayerScene::handleMessage);
|
|
SetUpdateHandler(&DiskplayerScene::update);
|
|
_appearCountdown = 6;
|
|
|
|
}
|
|
|
|
void DiskplayerScene::update() {
|
|
Scene::update();
|
|
|
|
if (_updateStatus == kUSTuningIn && _diskSmackerPlayer->isDone()) {
|
|
if (_diskAvailable[_diskIndex])
|
|
playDisk();
|
|
else
|
|
playStatic();
|
|
} else if (_updateStatus == kUSPlaying && _diskSmackerPlayer->isDone()) {
|
|
_diskSlots[_diskIndex]->stop();
|
|
_diskIndex++;
|
|
if (_hasAllDisks) {
|
|
if (_diskIndex != 20) {
|
|
playDisk();
|
|
} else if (_dropKey) {
|
|
playDisk();
|
|
_updateStatus = kUSPlayingFinal;
|
|
} else {
|
|
_diskIndex = 0;
|
|
stop();
|
|
}
|
|
} else if (_diskIndex != 20) {
|
|
tuneIn();
|
|
} else {
|
|
_diskIndex = 0;
|
|
stop();
|
|
}
|
|
} else if (_updateStatus == kUSPlayingFinal) {
|
|
if (_diskSmackerPlayer->getFrameNumber() == 133) {
|
|
_asKey->stDropKey();
|
|
setGlobalVar(V_HAS_FINAL_KEY, 1);
|
|
} else if (_diskSmackerPlayer->isDone()) {
|
|
for (int i = 0; i < 20; i++) {
|
|
_diskSlots[i]->setLocked(false);
|
|
_diskSlots[i]->stop();
|
|
}
|
|
_diskIndex = 0;
|
|
stop();
|
|
showMouse(true);
|
|
_dropKey = false;
|
|
}
|
|
}
|
|
|
|
if (_appearCountdown != 0 && (--_appearCountdown == 0)) {
|
|
_diskSlots[_diskIndex]->appear();
|
|
if (_dropKey) {
|
|
_diskSlots[_diskIndex]->activate();
|
|
_diskSlots[_diskIndex]->setLocked(true);
|
|
}
|
|
_diskIndex++;
|
|
while (!_diskAvailable[_diskIndex] && _diskIndex < 19)
|
|
_diskIndex++;
|
|
if (_diskIndex < 20) {
|
|
_appearCountdown = 1;
|
|
} else {
|
|
_diskIndex = 0;
|
|
_inputDisabled = false;
|
|
if (_dropKey) {
|
|
_ssPlayButton->press();
|
|
_tuneInCountdown = 2;
|
|
} else {
|
|
showMouse(true);
|
|
_diskSlots[_diskIndex]->activate();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_tuneInCountdown != 0 && (--_tuneInCountdown == 0))
|
|
playDisk();
|
|
|
|
}
|
|
|
|
uint32 DiskplayerScene::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) {
|
|
Scene::handleMessage(messageNum, param, sender);
|
|
if (!_inputDisabled) {
|
|
switch (messageNum) {
|
|
case NM_MOUSE_CLICK:
|
|
if (param.asPoint().x <= 20 || param.asPoint().x >= 620) {
|
|
sendMessage(_parentModule, 0x1009, 0);
|
|
} else if (!_dropKey &&
|
|
param.asPoint().x > 38 && param.asPoint().x < 598 &&
|
|
param.asPoint().y > 400 && param.asPoint().y < 460) {
|
|
|
|
_diskSlots[_diskIndex]->stop();
|
|
_diskIndex = (param.asPoint().x - 38) / 28;
|
|
_diskSlots[_diskIndex]->activate();
|
|
if (_updateStatus == kUSPlaying) {
|
|
if (_diskAvailable[_diskIndex])
|
|
playDisk();
|
|
else
|
|
playStatic();
|
|
}
|
|
}
|
|
break;
|
|
case NM_ANIMATION_UPDATE:
|
|
tuneIn();
|
|
break;
|
|
case 0x2001:
|
|
stop();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void DiskplayerScene::openSmacker(uint32 fileHash, bool keepLastFrame) {
|
|
_diskSmackerPlayer->open(fileHash, keepLastFrame);
|
|
_vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder());
|
|
_palette->usePalette();
|
|
}
|
|
|
|
void DiskplayerScene::stop() {
|
|
openSmacker(0x08288103, true);
|
|
_ssPlayButton->release();
|
|
_updateStatus = kUSStopped;
|
|
_diskSlots[_diskIndex]->activate();
|
|
}
|
|
|
|
void DiskplayerScene::tuneIn() {
|
|
openSmacker(0x900001C1, false);
|
|
_ssPlayButton->release();
|
|
_updateStatus = kUSTuningIn;
|
|
_diskSlots[_diskIndex]->activate();
|
|
}
|
|
|
|
void DiskplayerScene::playDisk() {
|
|
openSmacker(kDiskplayerSmackerFileHashes[_diskIndex], false);
|
|
_updateStatus = kUSPlaying;
|
|
_diskSlots[_diskIndex]->play();
|
|
}
|
|
|
|
void DiskplayerScene::playStatic() {
|
|
openSmacker(0x90000101, false);
|
|
_ssPlayButton->release();
|
|
_updateStatus = kUSPlaying;
|
|
_diskSlots[_diskIndex]->activate();
|
|
}
|
|
|
|
} // End of namespace Neverhood
|