25 #include "advancedDetector.h" 26 #include "audio/audiostream.h" 27 #include "audio/mixer.h" 28 #include "common/array.h" 29 #include "common/error.h" 30 #include "common/file.h" 31 #include "common/fs.h" 32 #include "common/hashmap.h" 33 #include "common/memstream.h" 34 #include "common/random.h" 35 #include "common/scummsys.h" 36 #include "common/serializer.h" 37 #include "common/system.h" 38 #include "common/text-to-speech.h" 39 #include "common/util.h" 40 #include "engines/engine.h" 41 #include "graphics/palette.h" 42 #include "macs2/amiga_archive.h" 43 #include "macs2/events.h" 44 #include "macs2/macs2_constants.h" 45 #include "macs2/pathfinding.h" 46 #include "macs2/scriptexecutor.h" 47 #include "macs2/sprite.h" 48 #include "macs2/text.h" 77 virtual int readBuffer(int16 *buffer,
const int numSamples);
101 struct Macs2GameDescription;
111 Common::Point getBottomMiddleOffset(uint16 scale = 100)
const;
114 enum class MenuMode : uint16 {
121 enum class OptionsSubMode : uint16 {
131 uint16 inactiveStep = 0;
132 uint16 activeStep = 0;
133 uint16 hoverStep = 0;
146 uint32 _frameIndex = 0;
155 uint16 _activeExtraSlot = 0;
156 uint16 _unknown0C = 0;
157 uint8 _unknown0E = 0;
158 uint8 _unknown0F = 0;
160 if (_activeExtraSlot >= 1 && _activeExtraSlot <= 8)
161 return _extraBlobs[_activeExtraSlot - 1];
165 if (_activeExtraSlot >= 1 && _activeExtraSlot <= 8)
166 return _extraBlobs[_activeExtraSlot - 1];
201 bool isValid()
const {
202 return _blob.
size() >= 14;
205 uint16 sequencePosition()
const {
206 return READ_LE_UINT16(&_blob[0x02]);
209 uint16 repeatCounter()
const {
210 return READ_LE_UINT16(&_blob[0x04]);
213 uint16 loopStartPosition()
const {
214 return READ_LE_UINT16(&_blob[0x06]);
217 uint16 delayCounter()
const {
218 return READ_LE_UINT16(&_blob[0x08]);
221 uint16 sequenceLength()
const {
222 return READ_LE_UINT16(&_blob[0x0A]) + 1;
225 uint32 frameDataOffset()
const {
226 return 0x0B + sequenceLength();
229 uint16 frameCount()
const {
230 const uint32 off = frameDataOffset();
231 if (off + 2 > _blob.
size()) {
234 return READ_LE_UINT16(&_blob[off]);
247 bool getFrameInfo(uint16 index,
FrameInfo &out)
const {
248 uint32 pos = frameDataOffset() + 2;
249 for (uint16 i = 0; i <= index; i++) {
250 if (pos + 10 > _blob.
size()) {
253 const int16 ox = (int16)READ_LE_UINT16(&_blob[pos]);
254 const int16 oy = (int16)READ_LE_UINT16(&_blob[pos + 2]);
255 const uint16 unk = READ_LE_UINT16(&_blob[pos + 4]);
256 const uint16 w = READ_LE_UINT16(&_blob[pos + 6]);
257 const uint16 h = READ_LE_UINT16(&_blob[pos + 8]);
259 if (w == 0 || h == 0 || pos + (uint32)w * h > _blob.
size()) {
263 out = {ox, oy, unk, w, h, &_blob[pos]};
266 pos += (uint32)w * h;
276 Music *_music =
nullptr;
293 void readResourceFile();
302 void loadResourceFileV1();
304 void loadResourceFileV2();
306 void bootstrapMcsActorsObjectsAndScene();
309 const char *getResourceMcsFilename()
const;
311 void readAmigaResources();
312 void applyAmigaUiPalette();
318 void installAmigaPortraitPalette(
bool copyFromPlayfield);
319 void buildAmigaPanelRemapTable();
320 bool loadAmigaCursorResource(uint16 resourceId,
AnimFrame &out);
321 bool loadAmigaMxffFont();
322 bool loadAmigaOverlayFont(uint8 resourceIndex);
323 bool loadAmigaOverlayFontResource(uint16 ffId);
330 bool loadAmigaSceneBackground(uint32 sceneResourceId);
332 void initInventoryIconIndices();
344 void changeScene(uint32 newSceneIndex,
bool executeScript =
true);
370 void updateBackgroundAnimationDepthMap(
size_t animIndex);
371 void updateAllBackgroundAnimationDepthMaps();
383 bool loadOverlayFont(uint8 resourceIndex, uint16 executingObjectID);
388 bool resolveResourceFileOffset(uint8 resourceIndex, uint16 executingObjectId, uint32 &outOffset)
const;
390 bool loadSizedResourcePayload(uint8 resourceIndex, uint16 executingObjectId,
Common::Array<uint8> &outPayload);
392 bool loadAhffAnimResource(uint8 resourceIndex, uint16 executingObjectId,
Common::Array<uint8> &outBlob);
401 int megapicW,
int megapicH,
bool upscaleHalfRes =
false);
412 uint16 frameIndex = 0;
413 bool duckMusic =
false;
418 bool playing =
false;
419 bool applyPaletteOnStart =
false;
420 uint16 frameCount = 0;
421 uint16 startFrame = 0;
423 uint16 speedTicks = 1;
424 uint16 tickCounter = 0;
425 uint16 currentFrame = 0;
433 void clear(
int screenW,
int screenH) {
437 startFrame = endFrame = currentFrame = 0;
440 applyPaletteOnStart =
false;
443 clipMiX = clipMiY = 0;
444 clipMaX = (uint16)
MAX(0, screenW - 1);
445 clipMaY = (uint16)
MAX(0, screenH - 1);
450 bool loadDeltaAnimResource(uint8 resourceIndex, uint16 executingObjectId,
bool forceSkipSpeed1 =
false);
451 void clearDeltaAnim();
452 bool startDeltaPlayback(uint16 startFrame, uint16 endFrame, uint16 speedTicks,
bool applyPalette);
453 bool tickDeltaPlayback();
454 void applyDeltaFrameToBackground(
const DeltaFrame &frame);
455 void playDeltaFrameSfx(uint16 displayFrame);
467 uint32 _helpOffsets[256] = {0};
475 uint32 _mcsDirectoryOffset = kMcsV1DirectoryOffset;
478 bool _amigaNativePlayfieldPalette =
false;
490 bool _bottomHudVisible =
true;
497 bool _hudMegapicLoaded[6] = {};
500 uint16 _panelTopY = 0;
501 uint16 _panelHeight = 0;
502 MenuMode _menuMode = MenuMode::Main;
503 OptionsSubMode _optionsSubMode = OptionsSubMode::None;
504 Script::MouseMode _savedMenuCursorMode = Script::MouseMode::Walk;
505 uint16 _inventScroll = 1;
506 uint16 _inventOriginX = 0;
507 uint16 _inventOriginY = 0;
508 uint16 _inventCols = 4;
509 uint16 _inventRows = 2;
510 uint16 _inventSlotW = 64;
511 uint16 _inventSlotH = 52;
512 uint16 _inventLayoutMode = 0;
518 uint16 _hudTextLayout[7] = {};
519 uint16 _hudTextRecolor[4] = {};
520 uint16 _saveListScroll = 1;
523 uint16 _skipSpeed = 1;
525 void setCursorMode(Script::MouseMode newMode);
526 void nextCursorMode();
530 uint16 _walkDepthThresholdY;
531 uint16 _walkDepthScaleFactor;
532 uint16 _walkBaseSpeedPct;
538 uint16 _scenePaletteMode;
541 uint16 _paletteDarkenPercent;
543 void applyPaletteDarkening();
549 void applyScenePaletteEffect();
556 void updateBackgroundAnimationPalette();
560 bool _movementFinishedFlag =
false;
564 bool loadAnimationFromSceneData(uint16 objectIndex, uint16 slotIndex, uint8 arrayIndex,
bool shouldMirror =
false, uint16 executingScriptObjectId = 0);
568 void sortObjectsByDepth(uint16 objectIndex);
570 Music *getMusic()
const {
return _music; }
572 uint16 scaledMusicVolume(uint16 gameAttenuation)
const;
584 void setCurrentSoundData(
const Common::Array<uint8> &data,
int rateHz = 0x1F40,
int headerSkip = 2);
585 void clearCurrentSoundData();
586 bool hasCurrentSoundData()
const {
return !_currentSoundData.empty(); }
589 bool isSamplePlaying()
const;
595 void playAudioFile(
const Common::Path &basename,
bool speechBus);
597 bool isSpeechPlaying()
const;
605 uint32 _sceneTimerParams[4] = {0};
611 bool _clipRectDirty =
false;
618 void runScriptExecutor(
bool firstRun =
false) {
619 _scriptExecutor->run(firstRun);
622 bool _runScheduled =
false;
625 bool _scheduledRunIsInitScene =
false;
629 uint16 _gameSpeedMode = 0;
630 void setGameSpeedMode(uint16 mode);
636 enum class InputMode { None,
639 InputMode _inputMode = InputMode::None;
642 uint32 _inputFrameCounter = 0;
643 uint32 _inputPlaybackEndFrame = 0;
647 void stopInputRecording();
648 void recordInputFrame(uint16 mouseX, uint16 mouseY, uint16 buttons);
649 bool readInputFrame(uint16 &mouseX, uint16 &mouseY, uint16 &buttons);
652 int _currentSoundRate = 0x1F40;
653 int _currentSoundHeaderSkip = 2;
660 void scheduleRun(
bool initScene =
false);
672 void loadTranslation();
679 uint32 getFeatures()
const;
681 bool isAmiga()
const {
return getPlatform() == Common::kPlatformAmiga; }
684 bool isDemo()
const {
return getFeatures() &
ADGF_DEMO; }
686 bool isV1()
const {
return _mcsFileVersion == McsFileVersion::V1; }
687 bool isV2()
const {
return _mcsFileVersion == McsFileVersion::V2; }
691 McsFileVersion getMcsFileVersion()
const {
return _mcsFileVersion; }
692 int screenWidth()
const {
return isV2() ? kWinScreenWidth : kScreenWidth; }
693 int screenWidthLast()
const {
return screenWidth() - 1; }
694 int gameHeight()
const {
return isV2() ? kWinGameHeight : kGameHeight; }
695 int gameHeightLast()
const {
return gameHeight() - 1; }
702 if (_panelTopY == 0 || _panelHeight == 0)
703 return kWinGameHeight;
704 return (
int)_panelTopY + (int)_panelHeight;
706 if (enhancementEnabled(kEnhUIUX))
707 return gameHeight() + kUIHeight;
710 int screenHeightLast() {
return screenHeight() - 1; }
719 void setBottomHudVisible(
bool visible);
723 return _panelTopY != 0 && _panelHeight != 0;
739 static uint16 specialAnimSlotToAnimSlot(uint16 specialSlot);
746 uint16 resolveAnimSlotIndex(
const GameObject *obj)
const;
757 int dialogPadH()
const {
return isAmiga() ? 8 : 16; }
758 int dialogTextInset()
const {
return isAmiga() ? 4 : 9; }
759 int dialogLineGap()
const {
return 2; }
760 int portraitBorderPad()
const {
return isAmiga() ? 2 : 13; }
761 int portraitContentInset()
const {
return isAmiga() ? 1 : 7; }
762 int portraitTextGap()
const {
return isAmiga() ? 10 : 18; }
770 return _text.amigaTextLinePitch ? (int)_text.amigaTextLinePitch : (
int)_text._maxGlyphHeight;
771 return (
int)_text._maxGlyphHeight + dialogLineGap();
776 return isV2() ? (uint8)((uint16)charY >> 1) : (uint8)charY;
780 void loadBootstrapResources();
785 bool loadSceneGraphics(uint32 sceneIndex);
787 bool loadSceneGraphicsV1(uint32 sceneIndex);
789 bool loadSceneGraphicsV2(uint32 sceneIndex);
797 return (f == kSupportsLoadingDuringRuntime) ||
798 (f == kSupportsSavingDuringRuntime) ||
799 (f == kSupportsReturnToLauncher) ||
800 (f == kSupportsChangingOptionsDuringRuntime);
803 void syncSoundSettings()
override;
838 bool tick()
override;
841 Common::TextToSpeechManager::Action action = Common::TextToSpeechManager::INTERRUPT_NO_REPEAT,
842 uint16 speakerObjectId = 0)
const;
843 void setTTSVoice(uint16 speakerObjectId)
const;
844 void stopTextToSpeech()
const;
847 bool hotspotDirty()
const override;
848 void rebuildHotspotSnapshot()
const;
858 uint16 orientation = 0;
861 int currentSceneIndex = -1;
862 uint16 numHotspots = 0;
867 bool mapModeActive =
false;
874 Common::String lookupInteractionDisplayName(uint16 interactionId);
878 #endif // MACS2_MACS2H Definition: managed_surface.h:51
virtual int readBuffer(int16 *buffer, const int numSamples)
bool canSaveGameStateCurrently(Common::U32String *msg=nullptr) override
Definition: macs2.h:808
Common::Array< byte > _amigaPendingSceneScript
Definition: macs2.h:483
uint8 depthThresholdForY(int16 charY) const
Definition: macs2.h:775
EngineFeature
Definition: engine.h:282
bool scriptValuesHaveHighWord() const
Definition: macs2.h:749
bool hasFeature(EngineFeature f) const override
Definition: macs2.h:796
Audio::SoundHandle _currentSoundHandle
Definition: macs2.h:655
virtual Audio::Timestamp getLength() const
Definition: gameobjects.h:107
virtual bool isStereo() const
Definition: advancedDetector.h:164
void clear()
Definition: array.h:321
int dialogLineHeight() const
Definition: macs2.h:768
uint16 overloadAnimSlot() const
Definition: macs2.h:738
bool isBottomHudVisible() const
Definition: macs2.h:718
Definition: amiga_archive.h:100
uint16 maxAnimSlots() const
Definition: macs2.h:734
virtual int getRate() const
bool hasNativeHudAssets() const
Definition: macs2.h:722
uint16 maxHotspots() const
Definition: macs2.h:742
Definition: timestamp.h:83
int _rate
Definition: macs2.h:57
Definition: scriptexecutor.h:107
Definition: serializer.h:80
Definition: audiostream.h:212
bool shouldQuit() const override
Definition: macs2.h:285
Common::Error loadGameStream(Common::SeekableReadStream *stream) override
Definition: macs2.h:827
constexpr int PALETTE_COUNT
Definition: palette.h:42
uint32 getMcsDirectoryOffset() const
Definition: macs2.h:690
Audio::SoundHandle _speechSoundHandle
Definition: macs2.h:657
uint16 ticksPerGameFrame() const
Definition: macs2.h:731
int16 scaleScriptCoord(int16 coord) const
Definition: macs2.h:753
bool scriptVarIndexHasPaddingWord() const
Definition: macs2.h:751
McsFileVersion
Definition: macs2.h:295
int screenHeight()
Definition: macs2.h:700
virtual bool endOfData() const
size_type size() const
Definition: array.h:316
bool canLoadGameStateCurrently(Common::U32String *msg=nullptr) override
Definition: macs2.h:805
Definition: memstream.h:43
Definition: pathfinding.h:57
int dialogPadW() const
Definition: macs2.h:756
uint16 maxOrientations() const
Definition: macs2.h:736
uint32 timerTickMs() const
Definition: macs2.h:729
uint maxObjectResources() const
Definition: macs2.h:744
T MAX(T a, T b)
Definition: util.h:66
Simple class for handling a palette data.
Definition: palette.h:61
Definition: actionbar.h:31
virtual bool seek(const Audio::Timestamp &where)
Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave=false) override
Definition: macs2.h:823
Add "-demo" to gameid.
Definition: advancedDetector.h:157
Common::Platform platform
Definition: advancedDetector.h:199
Common::String _ttsPreviousSaid
Definition: macs2.h:487