mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-02 23:26:44 +00:00
c5422d4aab
AGOS: Add keymapper support commit 40359d7e9b575dbcc6233f9ba7f7454cf760c498 Author: NabeelShabbir <i210443@nu.edu.pk> Date: Thu May 30 02:51:09 2024 +0500
1163 lines
28 KiB
C++
1163 lines
28 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 "common/config-manager.h"
|
|
#include "common/debug-channels.h"
|
|
#include "common/file.h"
|
|
#include "common/fs.h"
|
|
#include "common/textconsole.h"
|
|
|
|
#include "engines/util.h"
|
|
|
|
#include "agos/debugger.h"
|
|
#include "agos/intern.h"
|
|
#include "agos/agos.h"
|
|
#include "agos/midi.h"
|
|
#include "agos/sound.h"
|
|
|
|
#include "backends/audiocd/audiocd.h"
|
|
|
|
#include "graphics/surface.h"
|
|
#include "graphics/sjis.h"
|
|
|
|
#include "audio/mididrv.h"
|
|
|
|
namespace AGOS {
|
|
|
|
static const GameSpecificSettings simon1_settings = {
|
|
"", // base_filename
|
|
"", // restore_filename
|
|
"", // tbl_filename
|
|
"EFFECTS", // effects_filename
|
|
"SIMON", // speech_filename
|
|
};
|
|
|
|
static const GameSpecificSettings simon2_settings = {
|
|
"", // base_filename
|
|
"", // restore_filename
|
|
"", // tbl_filename
|
|
"", // effects_filename
|
|
"SIMON2", // speech_filename
|
|
};
|
|
|
|
#ifdef ENABLE_AGOS2
|
|
static const GameSpecificSettings dimp_settings = {
|
|
"Gdimp", // base_filename
|
|
"", // restore_filename
|
|
"", // tbl_filename
|
|
"", // effects_filename
|
|
"MUSIC", // speech_filename
|
|
};
|
|
|
|
static const GameSpecificSettings jumble_settings = {
|
|
"Gjumble", // base_filename
|
|
"", // restore_filename
|
|
"", // tbl_filename
|
|
"", // effects_filename
|
|
"MUSIC", // speech_filename
|
|
};
|
|
|
|
static const GameSpecificSettings puzzle_settings = {
|
|
"Gpuzzle", // base_filename
|
|
"", // restore_filename
|
|
"", // tbl_filename
|
|
"", // effects_filename
|
|
"MUSIC", // speech_filename
|
|
};
|
|
|
|
static const GameSpecificSettings swampy_settings = {
|
|
"Gswampy", // base_filename
|
|
"", // restore_filename
|
|
"", // tbl_filename
|
|
"", // effects_filename
|
|
"MUSIC", // speech_filename
|
|
};
|
|
|
|
AGOSEngine_DIMP::AGOSEngine_DIMP(OSystem *system, const AGOSGameDescription *gd)
|
|
: AGOSEngine_PuzzlePack(system, gd) {
|
|
|
|
_iconToggleCount = 0;
|
|
_voiceCount = 0;
|
|
|
|
_lastTickCount = 0;
|
|
_startSecondCount = 0;
|
|
_tSecondCount = 0;
|
|
}
|
|
|
|
AGOSEngine_PuzzlePack::AGOSEngine_PuzzlePack(OSystem *system, const AGOSGameDescription *gd)
|
|
: AGOSEngine_Feeble(system, gd) {
|
|
|
|
_oopsValid = false;
|
|
_gameTime = 0;
|
|
}
|
|
#endif
|
|
|
|
AGOSEngine_Simon2::AGOSEngine_Simon2(OSystem *system, const AGOSGameDescription *gd)
|
|
: AGOSEngine_Simon1(system, gd) {
|
|
}
|
|
|
|
AGOSEngine_Simon1::AGOSEngine_Simon1(OSystem *system, const AGOSGameDescription *gd)
|
|
: AGOSEngine_Waxworks(system, gd) {
|
|
}
|
|
|
|
AGOSEngine_Waxworks::AGOSEngine_Waxworks(OSystem *system, const AGOSGameDescription *gd)
|
|
: AGOSEngine_Elvira2(system, gd) {
|
|
|
|
_boxCR = false;
|
|
_boxLineCount = 0;
|
|
memset(_boxBuffer, 0, sizeof(_boxBuffer));
|
|
_boxBufferPtr = _boxBuffer;
|
|
|
|
_linePtrs[0] = nullptr;
|
|
_linePtrs[1] = nullptr;
|
|
_linePtrs[2] = nullptr;
|
|
_linePtrs[3] = nullptr;
|
|
_linePtrs[4] = nullptr;
|
|
_linePtrs[5] = nullptr;
|
|
memset(_lineCounts, 0, sizeof(_lineCounts));
|
|
}
|
|
|
|
AGOSEngine_Elvira2::AGOSEngine_Elvira2(OSystem *system, const AGOSGameDescription *gd)
|
|
: AGOSEngine_Elvira1(system, gd) {
|
|
}
|
|
|
|
AGOSEngine_Elvira1::AGOSEngine_Elvira1(OSystem *system, const AGOSGameDescription *gd)
|
|
: AGOSEngine(system, gd), _sjisCurChar(0), _sjisFont(nullptr) {
|
|
}
|
|
|
|
AGOSEngine_Elvira1::~AGOSEngine_Elvira1() {
|
|
delete _sjisFont;
|
|
}
|
|
|
|
Common::Error AGOSEngine_Elvira1::init() {
|
|
Common::Error ret = AGOSEngine::init();
|
|
if (ret.getCode() == Common::kNoError && getPlatform() == Common::kPlatformPC98) {
|
|
_sjisFont = Graphics::FontSJIS::createFont(Common::kPlatformPC98);
|
|
if (_sjisFont)
|
|
_sjisFont->toggleFatPrint(true);
|
|
else
|
|
error("AGOSEngine_Elvira1::init(): Failed to load SJIS font.");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd)
|
|
: Engine(system), _rnd("agos"), _gameDescription(gd) {
|
|
|
|
//Image dumping command disabled as it doesn't work well
|
|
#if 0
|
|
DebugMan.addDebugChannel(kDebugImageDump, "image_dump", "Enable dumping of images to files");
|
|
#endif
|
|
_vcPtr = nullptr;
|
|
_vcGetOutOfCode = 0;
|
|
_gameOffsetsPtr = nullptr;
|
|
|
|
_gameFile = nullptr;
|
|
_opcode = 0;
|
|
|
|
_itemMemSize = 0;
|
|
_tableMemSize = 0;
|
|
_vgaMemSize = 0;
|
|
|
|
_musicIndexBase = 0;
|
|
_soundIndexBase = 0;
|
|
_tableIndexBase = 0;
|
|
_textIndexBase = 0;
|
|
|
|
_numMusic = 0;
|
|
_numSFX = 0;
|
|
_numSpeech = 0;
|
|
_numZone = 0;
|
|
|
|
_numBitArray1 = 0;
|
|
_numBitArray2 = 0;
|
|
_numBitArray3 = 0;
|
|
_numItemStore = 0;
|
|
_numTextBoxes = 0;
|
|
_numVars = 0;
|
|
_numVideoOpcodes = 0;
|
|
_vgaBaseDelay = 0;
|
|
_vgaPeriod = 0;
|
|
|
|
_strippedTxtMem = nullptr;
|
|
_textMem = nullptr;
|
|
_textSize = 0;
|
|
_stringTabNum = 0;
|
|
_stringTabPos = 0;
|
|
_stringTabSize = 0;
|
|
_stringTabPtr = nullptr;
|
|
|
|
_itemArrayPtr = nullptr;
|
|
_itemArraySize = 0;
|
|
_itemArrayInited = 0;
|
|
|
|
_iconFilePtr = nullptr;
|
|
|
|
_codePtr = nullptr;
|
|
|
|
_localStringtable = nullptr;
|
|
_stringIdLocalMin = 0;
|
|
_stringIdLocalMax = 0;
|
|
|
|
_roomStates = nullptr;
|
|
_numRoomStates = 0;
|
|
|
|
_menuBase = nullptr;
|
|
_roomsList = nullptr;
|
|
_roomsListPtr = nullptr;
|
|
|
|
_xtblList = nullptr;
|
|
_xtablesHeapPtrOrg = nullptr;
|
|
_xtablesHeapCurPosOrg = 0;
|
|
_xsubroutineListOrg = nullptr;
|
|
|
|
_tblList = nullptr;
|
|
_tablesHeapPtr = nullptr;
|
|
_tablesHeapPtrOrg = nullptr;
|
|
_tablesheapPtrNew = nullptr;
|
|
_tablesHeapSize = 0;
|
|
_tablesHeapCurPos = 0;
|
|
_tablesHeapCurPosOrg = 0;
|
|
_tablesHeapCurPosNew = 0;
|
|
_subroutineListOrg = nullptr;
|
|
|
|
_subroutineList = nullptr;
|
|
|
|
_recursionDepth = 0;
|
|
|
|
_lastVgaTick = 0;
|
|
|
|
_marks = 0;
|
|
_scanFlag = false;
|
|
|
|
_scriptVar2 = 0;
|
|
_runScriptReturn1 = false;
|
|
_skipVgaWait = false;
|
|
_noParentNotify = false;
|
|
_beardLoaded = false;
|
|
_litBoxFlag = false;
|
|
_mortalFlag = false;
|
|
_displayFlag = 0;
|
|
_syncFlag2 = false;
|
|
_inCallBack = false;
|
|
_cepeFlag = false;
|
|
_fastMode = false;
|
|
|
|
_backFlag = false;
|
|
|
|
_copyProtection = false;
|
|
_pause = false;
|
|
_speech = false;
|
|
_subtitles = false;
|
|
|
|
_animatePointer = 0;
|
|
_maxCursorWidth = 0;
|
|
_maxCursorHeight = 0;
|
|
_mouseAnim = 0;
|
|
_mouseAnimMax = 0;
|
|
_mouseCursor = 0;
|
|
_mouseData = nullptr;
|
|
_oldMouseCursor = 0;
|
|
_currentMouseCursor = 0;
|
|
_currentMouseAnim = 0;
|
|
_oldMouseAnimMax = 0;
|
|
|
|
_vgaVar9 = 0;
|
|
_chanceModifier = 0;
|
|
_restoreWindow6 = 0;
|
|
_scrollX = 0;
|
|
_scrollY = 0;
|
|
_scrollXMax = 0;
|
|
_scrollYMax = 0;
|
|
_scrollCount = 0;
|
|
_scrollFlag = 0;
|
|
_scrollHeight = 0;
|
|
_scrollWidth = 0;
|
|
_scrollImage = nullptr;
|
|
_boxStarHeight = 0;
|
|
|
|
_scriptVerb = 0;
|
|
_scriptNoun1 = 0;
|
|
_scriptNoun2 = 0;
|
|
_scriptAdj1 = 0;
|
|
_scriptAdj2 = 0;
|
|
|
|
_curWindow = 0;
|
|
_textWindow = nullptr;
|
|
|
|
_subjectItem = nullptr;
|
|
_objectItem = nullptr;
|
|
_currentPlayer = nullptr;
|
|
|
|
_iOverflow = false;
|
|
_nameLocked = false;
|
|
_hitAreaObjectItem = nullptr;
|
|
_lastHitArea = nullptr;
|
|
_lastNameOn = nullptr;
|
|
_lastHitArea3 = nullptr;
|
|
_hitAreaSubjectItem = nullptr;
|
|
_currentBox = nullptr;
|
|
_currentBoxNum = 0;
|
|
_currentVerbBox = nullptr;
|
|
_lastVerbOn = nullptr;
|
|
_needHitAreaRecalc = 0;
|
|
_verbHitArea = 0;
|
|
_defaultVerb = 0;
|
|
_mouseHideCount = 0;
|
|
|
|
_dragAccept = false;
|
|
_dragEnd = false;
|
|
_dragFlag = false;
|
|
_dragMode = false;
|
|
_dragCount = 0;
|
|
_lastClickRem = nullptr;
|
|
|
|
_windowNum = 0;
|
|
|
|
_printCharCurPos = 0;
|
|
_printCharMaxPos = 0;
|
|
_printCharPixelCount = 0;
|
|
_numLettersToPrint = 0;
|
|
|
|
_clockStopped = 0;
|
|
_gameStoppedClock = 0;
|
|
_lastTime = 0;
|
|
_lastMinute = 0;
|
|
|
|
_firstTimeStruct = nullptr;
|
|
_pendingDeleteTimeEvent = nullptr;
|
|
|
|
_initMouse = 0;
|
|
_leftButtonDown = false;
|
|
_rightButtonDown = false;
|
|
_clickOnly = false;
|
|
_oneClick = 0;
|
|
_leftClick = 0;
|
|
_rightClick = 0;
|
|
_noRightClick = false;
|
|
|
|
_leftButton = 0;
|
|
_leftButtonCount = 0;
|
|
_leftButtonOld = 0;
|
|
|
|
_dummyItem1 = new Item();
|
|
_dummyItem2 = new Item();
|
|
_dummyItem3 = new Item();
|
|
|
|
_videoLockOut = 0;
|
|
_scrollUpHitArea = 0;
|
|
_scrollDownHitArea = 0;
|
|
|
|
_noOverWrite = 0;
|
|
_rejectBlock = false;
|
|
|
|
_fastFadeCount = 0;
|
|
_fastFadeInFlag = 0;
|
|
_fastFadeOutFlag = false;
|
|
_neverFade = false;
|
|
_exitCutscene = 0;
|
|
_paletteFlag = 0;
|
|
_bottomPalette = false;
|
|
_picture8600 = 0;
|
|
|
|
_soundFileId = 0;
|
|
_lastMusicPlayed = 0;
|
|
_nextMusicToPlay = 0;
|
|
_sampleEnd = 0;
|
|
_sampleWait = 0;
|
|
|
|
_showPreposition = 0;
|
|
_showMessageFlag = 0;
|
|
|
|
_newDirtyClip = false;
|
|
_wiped = false;
|
|
_copyScnFlag = 0;
|
|
_vgaSpriteChanged = 0;
|
|
|
|
_block = nullptr;
|
|
_blockEnd = nullptr;
|
|
_vgaMemPtr = nullptr;
|
|
_vgaMemEnd = nullptr;
|
|
_vgaMemBase = nullptr;
|
|
_vgaFrozenBase = nullptr;
|
|
_vgaRealBase = nullptr;
|
|
_zoneBuffers = nullptr;
|
|
|
|
_curVgaFile1 = nullptr;
|
|
_curVgaFile2 = nullptr;
|
|
_curSfxFile = nullptr;
|
|
_curSfxFileSize = 0;
|
|
|
|
_syncCount = 0;
|
|
|
|
_frameCount = 0;
|
|
|
|
_zoneNumber = 0;
|
|
|
|
_vgaWaitFor = 0;
|
|
_lastVgaWaitFor = 0;
|
|
|
|
_vgaCurZoneNum = 0;
|
|
_vgaCurSpriteId = 0;
|
|
|
|
_baseY = 0;
|
|
_scale = 0;
|
|
|
|
_feebleRect.left = 0;
|
|
_feebleRect.right = 0;
|
|
_feebleRect.top = 0;
|
|
_feebleRect.bottom = 0;
|
|
|
|
_scaleX = 0;
|
|
_scaleY = 0;
|
|
_scaleWidth = 0;
|
|
_scaleHeight = 0;
|
|
|
|
_nextVgaTimerToProcess = nullptr;
|
|
|
|
_opcode177Var1 = 1;
|
|
_opcode177Var2 = 0;
|
|
_opcode178Var1 = 1;
|
|
_opcode178Var2 = 0;
|
|
|
|
_classLine = nullptr;
|
|
_classMask = 0;
|
|
_classMode1 = 0;
|
|
_classMode2 = 0;
|
|
_currentLine = nullptr;
|
|
_currentTable = nullptr;
|
|
_findNextPtr = nullptr;
|
|
|
|
_agosMenu = 0;
|
|
_currentRoom = 0;
|
|
_superRoomNumber = 0;
|
|
_wallOn = 0;
|
|
|
|
memset(_objectArray, 0, sizeof(_objectArray));
|
|
memset(_itemStore, 0, sizeof(_itemStore));
|
|
memset(_textMenu, 0, sizeof(_textMenu));
|
|
|
|
memset(_shortText, 0, sizeof(_shortText));
|
|
memset(_shortTextX, 0, sizeof(_shortText));
|
|
memset(_shortTextY, 0, sizeof(_shortText));
|
|
memset(_longText, 0, sizeof(_longText));
|
|
memset(_longSound, 0, sizeof(_longSound));
|
|
|
|
memset(_bitArray, 0, sizeof(_bitArray));
|
|
memset(_bitArrayTwo, 0, sizeof(_bitArrayTwo));
|
|
memset(_bitArrayThree, 0, sizeof(_bitArrayThree));
|
|
|
|
_variableArray = nullptr;
|
|
_variableArray2 = nullptr;
|
|
_variableArrayPtr = nullptr;
|
|
|
|
memset(_windowArray, 0, sizeof(_windowArray));
|
|
|
|
memset(_fcsData1, 0, sizeof(_fcsData1));
|
|
memset(_fcsData2, 0, sizeof(_fcsData2));
|
|
|
|
_awaitTwoByteToken = 0;
|
|
_byteTokens = nullptr;
|
|
_byteTokenStrings = nullptr;
|
|
_twoByteTokens = nullptr;
|
|
_twoByteTokenStrings = nullptr;
|
|
_secondTwoByteTokenStrings = nullptr;
|
|
_thirdTwoByteTokenStrings = nullptr;
|
|
memset(_textBuffer, 0, sizeof(_textBuffer));
|
|
_textCount = 0;
|
|
|
|
_freeStringSlot = 0;
|
|
|
|
memset(_stringReturnBuffer, 0, sizeof(_stringReturnBuffer));
|
|
|
|
memset(_pathFindArray, 0, sizeof(_pathFindArray));
|
|
|
|
memset(_pathValues, 0, sizeof(_pathValues));
|
|
_PVCount = 0;
|
|
_GPVCount = 0;
|
|
|
|
memset(_pathValues1, 0, sizeof(_pathValues1));
|
|
_PVCount1 = 0;
|
|
_GPVCount1 = 0;
|
|
|
|
memset(_currentPalette, 0, sizeof(_currentPalette));
|
|
memset(_displayPalette, 0, sizeof(_displayPalette));
|
|
|
|
memset(_videoBuf1, 0, sizeof(_videoBuf1));
|
|
memset(_videoWindows, 0, sizeof(_videoWindows));
|
|
|
|
_dummyWindow = new WindowBlock;
|
|
_windowList = new WindowBlock[16];
|
|
|
|
memset(_lettersToPrintBuf, 0, sizeof(_lettersToPrintBuf));
|
|
|
|
_planarBuf = nullptr;
|
|
_pak98Buf = nullptr;
|
|
_paletteModNext = 16;
|
|
|
|
_midiEnabled = false;
|
|
|
|
_vgaTickCounter = 0;
|
|
|
|
_sound = nullptr;
|
|
|
|
_effectsMuted = false;
|
|
_ambientMuted = false;
|
|
_musicMuted = false;
|
|
// Initialize at default ScummVM volumes; these will be overwritten by
|
|
// syncSoundSettings.
|
|
_musicVolume = 192;
|
|
_effectsVolume = 192;
|
|
_useDigitalSfx = true;
|
|
|
|
_saveLoadType = 0;
|
|
_saveLoadSlot = 0;
|
|
memset(_saveLoadName, 0, sizeof(_saveLoadName));
|
|
memset(_saveBuf, 0, sizeof(_saveBuf));
|
|
|
|
_saveGameNameLen = 0;
|
|
_saveLoadRowCurPos = 0;
|
|
_numSaveGameRows = 0;
|
|
_saveDialogFlag = false;
|
|
_saveOrLoad = false;
|
|
_saveLoadEdit = false;
|
|
|
|
_hyperLink = 0;
|
|
_interactY = 0;
|
|
_oracleMaxScrollY = 0;
|
|
_noOracleScroll = 0;
|
|
|
|
_backGroundBuf = nullptr;
|
|
_backBuf = nullptr;
|
|
_scaleBuf = nullptr;
|
|
_window4BackScn = nullptr;
|
|
_window6BackScn = nullptr;
|
|
|
|
_window3Flag = 0;
|
|
_window4Flag = 0;
|
|
_window6Flag = 0;
|
|
|
|
_moveXMin = 0;
|
|
_moveYMin = 0;
|
|
_moveXMax = 0;
|
|
_moveYMax = 0;
|
|
|
|
_forceAscii = false;
|
|
|
|
_vc10BasePtrOld = nullptr;
|
|
memcpy (_hebrewCharWidths,
|
|
"\x5\x5\x4\x6\x5\x3\x4\x5\x6\x3\x5\x5\x4\x6\x5\x3\x4\x6\x5\x6\x6\x6\x5\x5\x5\x6\x5\x6\x6\x6\x6\x6", 32);
|
|
|
|
const Common::FSNode gameDataDir(ConfMan.getPath("path"));
|
|
|
|
// Add default file directories for Acorn version of
|
|
// Simon the Sorcerer 1
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "execute");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "tables");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "text");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "tunes");
|
|
|
|
// Add default file directories for Amiga/Macintosh
|
|
// versions of Simon the Sorcerer 2
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "voices");
|
|
|
|
// Add default file directories for Amiga & Macintosh
|
|
// versions of The Feeble Files
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "gfx");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "movies");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "sfx");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "speech");
|
|
}
|
|
|
|
Common::Error AGOSEngine::init() {
|
|
if (getGameId() == GID_DIMP) {
|
|
_screenWidth = 496;
|
|
_screenHeight = 400;
|
|
} else if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
|
_screenWidth = 640;
|
|
_screenHeight = 480;
|
|
} else {
|
|
_screenWidth = 320;
|
|
_screenHeight = 200;
|
|
}
|
|
|
|
_internalWidth = _screenWidth;
|
|
_internalHeight = _screenHeight;
|
|
|
|
if (getPlatform() == Common::kPlatformPC98) {
|
|
_internalWidth <<= 1;
|
|
_internalHeight <<= 1;
|
|
}
|
|
|
|
if (ConfMan.hasKey("disable_fade_effects"))
|
|
_neverFade = ConfMan.getBool("disable_fade_effects");
|
|
|
|
initGraphics(_internalWidth, _internalHeight);
|
|
|
|
_midi = new MidiPlayer(this);
|
|
|
|
if ((getGameType() == GType_SIMON2 && getPlatform() == Common::kPlatformWindows) ||
|
|
(getGameType() == GType_SIMON1 && getPlatform() == Common::kPlatformWindows) ||
|
|
((getFeatures() & GF_TALKIE) && getPlatform() == Common::kPlatformAcorn) ||
|
|
(getPlatform() == Common::kPlatformDOS && getGameType() != GType_PN && getGameType() != GType_FF) ||
|
|
getPlatform() == Common::kPlatformPC98) {
|
|
|
|
int ret = _midi->open();
|
|
if (ret)
|
|
warning("MIDI Player init failed: \"%s\"", MidiDriver::getErrorName(ret));
|
|
|
|
_midiEnabled = true;
|
|
}
|
|
// Digital SFX are used if MIDI SFX are not available or if the "prefer
|
|
// digital SFX" setting is set to true or is not present at all.
|
|
// Two exceptions to this are:
|
|
// - Elvira 2 DOS needs an optional file to enable digital SFX. If it is
|
|
// not present, MIDI SFX are used.
|
|
// - Simon 1 DOS floppy has only MIDI SFX.
|
|
// Note that MIDI SFX can be safely used if the MidiPlayer failed to
|
|
// initialize; they just will not play.
|
|
_useDigitalSfx = !_midiEnabled || !_midi->hasMidiSfx() || !ConfMan.hasKey("prefer_digitalsfx") || ConfMan.getBool("prefer_digitalsfx");
|
|
if ((getGameType() == GType_ELVIRA2 && getPlatform() == Common::kPlatformDOS && !SearchMan.hasFile("013.VGA")) ||
|
|
(getGameType() == GType_SIMON1 && getPlatform() == Common::kPlatformDOS && !(getFeatures() & GF_TALKIE))) {
|
|
_useDigitalSfx = false;
|
|
}
|
|
if (!_useDigitalSfx && (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) && getPlatform() == Common::kPlatformDOS) {
|
|
// Load the MIDI SFX data file for Elvira 2 and Waxworks DOS.
|
|
loadMidiSfx();
|
|
}
|
|
|
|
// allocate buffers
|
|
_backGroundBuf = new Graphics::Surface();
|
|
_backGroundBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
|
|
|
|
if (getGameType() == GType_FF || getGameType() == GType_PP || (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformPC98)) {
|
|
_backBuf = new Graphics::Surface();
|
|
_backBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
|
|
_scaleBuf = new Graphics::Surface();
|
|
_scaleBuf->create(_internalWidth, _internalHeight, Graphics::PixelFormat::createFormatCLUT8());
|
|
}
|
|
|
|
if (getGameType() == GType_SIMON2) {
|
|
_window4BackScn = new Graphics::Surface();
|
|
_window4BackScn->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
|
|
} else if (getGameType() == GType_SIMON1) {
|
|
_window4BackScn = new Graphics::Surface();
|
|
_window4BackScn->create(_screenWidth, 134, Graphics::PixelFormat::createFormatCLUT8());
|
|
} else if (getGameType() == GType_WW || getGameType() == GType_ELVIRA2) {
|
|
_window4BackScn = new Graphics::Surface();
|
|
_window4BackScn->create(224, 127, Graphics::PixelFormat::createFormatCLUT8());
|
|
} else if (getGameType() == GType_ELVIRA1) {
|
|
_window4BackScn = new Graphics::Surface();
|
|
if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_DEMO)) {
|
|
_window4BackScn->create(224, 196, Graphics::PixelFormat::createFormatCLUT8());
|
|
} else {
|
|
_window4BackScn->create(224, 144, Graphics::PixelFormat::createFormatCLUT8());
|
|
}
|
|
_window6BackScn = new Graphics::Surface();
|
|
_window6BackScn->create(48, 80, Graphics::PixelFormat::createFormatCLUT8());
|
|
}
|
|
|
|
setupGame();
|
|
|
|
setDebugger(new Debugger(this));
|
|
_sound = new Sound(this, gss, _mixer);
|
|
|
|
_copyProtection = ConfMan.getBool("copy_protection");
|
|
_language = Common::parseLanguage(ConfMan.get("language"));
|
|
|
|
if (getGameType() == GType_PP) {
|
|
_speech = true;
|
|
_subtitles = false;
|
|
} else if (getFeatures() & GF_TALKIE) {
|
|
_speech = !ConfMan.getBool("speech_mute");
|
|
_subtitles = ConfMan.getBool("subtitles");
|
|
|
|
if (getGameType() == GType_SIMON1) {
|
|
// English and German versions don't have full subtitles
|
|
if (_language == Common::EN_ANY || _language == Common::DE_DEU)
|
|
_subtitles = false;
|
|
// Other versions require speech to be enabled
|
|
else
|
|
_speech = true;
|
|
}
|
|
|
|
// Default to speech only, if both speech and subtitles disabled
|
|
if (!_speech && !_subtitles)
|
|
_speech = true;
|
|
} else {
|
|
_speech = false;
|
|
_subtitles = true;
|
|
}
|
|
|
|
// Setup mixer
|
|
syncSoundSettings();
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
static const uint16 initialVideoWindows_Simon[20] = {
|
|
0, 0, 20, 200,
|
|
0, 0, 3, 136,
|
|
17, 0, 3, 136,
|
|
0, 0, 20, 200,
|
|
0, 0, 20, 134
|
|
};
|
|
|
|
static const uint16 initialVideoWindows_Common[20] = {
|
|
3, 0, 14, 136,
|
|
0, 0, 3, 136,
|
|
17, 0, 3, 136,
|
|
0, 0, 20, 200,
|
|
3, 3, 14, 127,
|
|
};
|
|
|
|
static const uint16 initialVideoWindows_PN[20] = {
|
|
3, 0, 14, 136,
|
|
0, 0, 3, 136,
|
|
17, 0, 3, 136,
|
|
0, 0, 20, 200,
|
|
3, 2, 14, 129,
|
|
};
|
|
|
|
#ifdef ENABLE_AGOS2
|
|
void AGOSEngine_PuzzlePack::setupGame() {
|
|
if (getGameId() == GID_DIMP) {
|
|
gss = &dimp_settings;
|
|
} else if (getGameId() == GID_JUMBLE) {
|
|
gss = &jumble_settings;
|
|
} else if (getGameId() == GID_PUZZLE) {
|
|
gss = &puzzle_settings;
|
|
} else if (getGameId() == GID_SWAMPY) {
|
|
gss = &swampy_settings;
|
|
}
|
|
_numVideoOpcodes = 85;
|
|
_vgaMemSize = 7500000;
|
|
_itemMemSize = 20000;
|
|
_tableMemSize = 200000;
|
|
_frameCount = 1;
|
|
_vgaBaseDelay = 5;
|
|
_vgaPeriod = (getGameId() == GID_DIMP) ? 35 : 30;
|
|
_numBitArray1 = 128;
|
|
_numItemStore = 10;
|
|
_numTextBoxes = 40;
|
|
_numVars = 2048;
|
|
|
|
_numZone = 450;
|
|
|
|
AGOSEngine::setupGame();
|
|
}
|
|
#endif
|
|
|
|
void AGOSEngine_Simon2::setupGame() {
|
|
gss = &simon2_settings;
|
|
_tableIndexBase = 1580 / 4;
|
|
_textIndexBase = 1500 / 4;
|
|
_numVideoOpcodes = 75;
|
|
#if defined(__DS__)
|
|
_vgaMemSize = 1300000;
|
|
#else
|
|
_vgaMemSize = 2000000;
|
|
#endif
|
|
_itemMemSize = 20000;
|
|
_tableMemSize = 100000;
|
|
// Check whether to use MT-32 MIDI tracks in Simon the Sorcerer 2
|
|
if (getGameType() == GType_SIMON2 && getPlatform() == Common::kPlatformDOS && _midi->usesMT32Data())
|
|
_musicIndexBase = MUSIC_INDEX_BASE_SIMON2_MT32;
|
|
else
|
|
_musicIndexBase = MUSIC_INDEX_BASE_SIMON2_GM;
|
|
_soundIndexBase = 1660 / 4;
|
|
_frameCount = 1;
|
|
_vgaBaseDelay = 1;
|
|
_vgaPeriod = 45;
|
|
_numBitArray1 = 16;
|
|
_numBitArray2 = 16;
|
|
_numItemStore = 10;
|
|
_numTextBoxes = 20;
|
|
_numVars = 255;
|
|
|
|
_numMusic = 93;
|
|
_numSFX = 222;
|
|
_numSpeech = 11997;
|
|
_numZone = 140;
|
|
|
|
AGOSEngine::setupGame();
|
|
}
|
|
|
|
void AGOSEngine_Simon1::setupGame() {
|
|
gss = &simon1_settings;
|
|
_tableIndexBase = 1576 / 4;
|
|
_textIndexBase = 1460 / 4;
|
|
_numVideoOpcodes = 64;
|
|
_vgaMemSize = 1000000;
|
|
_itemMemSize = 20000;
|
|
_tableMemSize = 50000;
|
|
_musicIndexBase = 1316 / 4;
|
|
_soundIndexBase = 0;
|
|
_frameCount = 1;
|
|
_vgaBaseDelay = 1;
|
|
_vgaPeriod = 50;
|
|
_numBitArray1 = 16;
|
|
_numBitArray2 = 16;
|
|
_numItemStore = 10;
|
|
_numTextBoxes = 20;
|
|
_numVars = 255;
|
|
|
|
_numMusic = 34;
|
|
_numSFX = 127;
|
|
_numSpeech = 3623;
|
|
_numZone = 164;
|
|
|
|
AGOSEngine::setupGame();
|
|
}
|
|
|
|
void AGOSEngine_Waxworks::setupGame() {
|
|
gss = &simon1_settings;
|
|
_numVideoOpcodes = 64;
|
|
_vgaMemSize = 1000000;
|
|
_itemMemSize = 80000;
|
|
_tableMemSize = 50000;
|
|
_frameCount = 4;
|
|
_vgaBaseDelay = 1;
|
|
_vgaPeriod = 50;
|
|
_numBitArray1 = 16;
|
|
_numBitArray2 = 15;
|
|
_numItemStore = 50;
|
|
_numTextBoxes = 10;
|
|
_numVars = 255;
|
|
|
|
_numMusic = 26;
|
|
_numZone = 155;
|
|
|
|
AGOSEngine::setupGame();
|
|
}
|
|
|
|
void AGOSEngine_Elvira2::setupGame() {
|
|
gss = &simon1_settings;
|
|
_numVideoOpcodes = 60;
|
|
_vgaMemSize = 1000000;
|
|
_itemMemSize = 64000;
|
|
_tableMemSize = 100000;
|
|
_frameCount = 4;
|
|
_vgaBaseDelay = 1;
|
|
_vgaPeriod = 50;
|
|
_numBitArray1 = 16;
|
|
_numBitArray2 = 15;
|
|
_numItemStore = 50;
|
|
_numVars = 255;
|
|
|
|
_numMusic = 9;
|
|
_numZone = 99;
|
|
|
|
AGOSEngine::setupGame();
|
|
}
|
|
|
|
void AGOSEngine_Elvira1::setupGame() {
|
|
gss = &simon1_settings;
|
|
_numVideoOpcodes = 57;
|
|
_vgaMemSize = 1000000;
|
|
_itemMemSize = 64000;
|
|
_tableMemSize = 256000;
|
|
_frameCount = 4;
|
|
_vgaBaseDelay = 1;
|
|
_vgaPeriod = 50;
|
|
_numVars = 512;
|
|
|
|
_numMusic = 14;
|
|
_numZone = 74;
|
|
|
|
AGOSEngine::setupGame();
|
|
}
|
|
|
|
void AGOSEngine_PN::setupGame() {
|
|
gss = &simon1_settings;
|
|
_numVideoOpcodes = 57;
|
|
_vgaMemSize = 1000000;
|
|
_frameCount = 4;
|
|
_vgaBaseDelay = 1;
|
|
_vgaPeriod = 50;
|
|
_numVars = 256;
|
|
|
|
_numZone = 26;
|
|
|
|
AGOSEngine::setupGame();
|
|
}
|
|
|
|
void AGOSEngine::setupGame() {
|
|
allocItemHeap();
|
|
allocTablesHeap();
|
|
|
|
if (getGameType() != GType_SIMON2)
|
|
initMouse();
|
|
|
|
_variableArray = (int16 *)calloc(_numVars, sizeof(int16));
|
|
_variableArrayPtr = _variableArray;
|
|
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
|
_variableArray2 = (int16 *)calloc(_numVars, sizeof(int16));
|
|
}
|
|
|
|
setupOpcodes();
|
|
setupVgaOpcodes();
|
|
|
|
setZoneBuffers();
|
|
|
|
_currentMouseCursor = 255;
|
|
_currentMouseAnim = 255;
|
|
|
|
_lastMusicPlayed = -1;
|
|
_nextMusicToPlay = -1;
|
|
|
|
_noOverWrite = 0xFFFF;
|
|
|
|
_stringIdLocalMin = 1;
|
|
|
|
_agosMenu = 1;
|
|
_superRoomNumber = 1;
|
|
|
|
for (int i = 0; i < 20; i++) {
|
|
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
|
|
_videoWindows[i] = initialVideoWindows_Simon[i];
|
|
} else if (getGameType() == GType_PN) {
|
|
_videoWindows[i] = initialVideoWindows_PN[i];
|
|
} else {
|
|
_videoWindows[i] = initialVideoWindows_Common[i];
|
|
}
|
|
}
|
|
|
|
if (getGameType() == GType_ELVIRA2 && getPlatform() == Common::kPlatformAtariST) {
|
|
_videoWindows[9] = 75;
|
|
}
|
|
}
|
|
|
|
AGOSEngine::~AGOSEngine() {
|
|
_system->getAudioCDManager()->stop();
|
|
|
|
for (uint i = 0; i < _itemHeap.size(); i++) {
|
|
delete[] _itemHeap[i];
|
|
}
|
|
_itemHeap.clear();
|
|
|
|
free(_tablesHeapPtr - _tablesHeapCurPos);
|
|
|
|
free(_mouseData);
|
|
|
|
free(_gameOffsetsPtr);
|
|
free(_iconFilePtr);
|
|
free(_itemArrayPtr);
|
|
free(_menuBase);
|
|
free(_roomsList);
|
|
free(_roomStates);
|
|
free(_stringTabPtr);
|
|
free(_strippedTxtMem);
|
|
free(_tblList);
|
|
free(_textMem);
|
|
free(_xtblList);
|
|
|
|
if (_backGroundBuf)
|
|
_backGroundBuf->free();
|
|
delete _backGroundBuf;
|
|
if (_backBuf)
|
|
_backBuf->free();
|
|
delete _backBuf;
|
|
free(_planarBuf);
|
|
delete[] _pak98Buf;
|
|
if (_scaleBuf)
|
|
_scaleBuf->free();
|
|
delete _scaleBuf;
|
|
free(_zoneBuffers);
|
|
|
|
if (_window4BackScn)
|
|
_window4BackScn->free();
|
|
delete _window4BackScn;
|
|
if (_window6BackScn)
|
|
_window6BackScn->free();
|
|
delete _window6BackScn;
|
|
|
|
delete _midi;
|
|
|
|
free(_firstTimeStruct);
|
|
free(_pendingDeleteTimeEvent);
|
|
|
|
free(_variableArray);
|
|
free(_variableArray2);
|
|
|
|
delete _dummyItem1;
|
|
delete _dummyItem2;
|
|
delete _dummyItem3;
|
|
|
|
delete _dummyWindow;
|
|
delete[] _windowList;
|
|
|
|
delete _sound;
|
|
delete _gameFile;
|
|
}
|
|
|
|
void AGOSEngine::pauseEngineIntern(bool pauseIt) {
|
|
if (pauseIt) {
|
|
_keyPressed.reset();
|
|
_action = kActionNone;
|
|
_pause = true;
|
|
|
|
_midi->pause(true);
|
|
_mixer->pauseAll(true);
|
|
} else {
|
|
_pause = false;
|
|
|
|
_midi->pause(false);
|
|
_mixer->pauseAll(false);
|
|
}
|
|
}
|
|
|
|
void AGOSEngine::pause() {
|
|
PauseToken pt = pauseEngine();
|
|
|
|
while (_pause && !shouldQuit()) {
|
|
delay(1);
|
|
if (_action == kActionPause) {
|
|
pt.clear();
|
|
_keyPressed.reset();
|
|
_action = kActionNone;
|
|
}
|
|
}
|
|
}
|
|
|
|
Common::Error AGOSEngine::go() {
|
|
#ifdef ENABLE_AGOS2
|
|
loadArchives();
|
|
#endif
|
|
|
|
loadGamePcFile();
|
|
|
|
addTimeEvent(0, 1);
|
|
|
|
if (getFileName(GAME_GMEFILE) != nullptr) {
|
|
openGameFile();
|
|
}
|
|
|
|
if (getGameType() == GType_FF) {
|
|
loadIconData();
|
|
} else if (getFileName(GAME_ICONFILE) != nullptr) {
|
|
loadIconFile();
|
|
}
|
|
|
|
if (getFileName(GAME_MENUFILE) != nullptr) {
|
|
loadMenuFile();
|
|
}
|
|
|
|
vc34_setMouseOff();
|
|
|
|
if (getGameType() != GType_PP && getGameType() != GType_FF) {
|
|
uint16 count = (getGameType() == GType_SIMON2) ? 5 : _frameCount;
|
|
addVgaEvent(count, ANIMATE_INT, nullptr, 0, 0);
|
|
}
|
|
|
|
if (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformAtariST &&
|
|
(getFeatures() & GF_DEMO)) {
|
|
setWindowImage(3, 9900);
|
|
while (!shouldQuit())
|
|
delay(0);
|
|
}
|
|
|
|
if (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformAmiga &&
|
|
(getFeatures() & GF_DEMO)) {
|
|
playMusic(0, 0);
|
|
}
|
|
|
|
runSubroutine101();
|
|
permitInput();
|
|
|
|
while (!shouldQuit()) {
|
|
waitForInput();
|
|
handleVerbClicked(_verbHitArea);
|
|
delay(100);
|
|
}
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
|
|
uint32 AGOSEngine::getTime() const {
|
|
return _system->getMillis() / 1000;
|
|
}
|
|
|
|
void AGOSEngine::syncSoundSettings() {
|
|
Engine::syncSoundSettings();
|
|
|
|
int newMusicVolume = ConfMan.getInt("music_volume");
|
|
int newEffectsVolume = ConfMan.getInt("sfx_volume");
|
|
|
|
_musicMuted = newMusicVolume == 0;
|
|
if (newMusicVolume != 0)
|
|
_musicVolume = newMusicVolume;
|
|
if (getGameType() == GType_SIMON2) {
|
|
// Simon 2 has regular and ambient SFX, which can be toggled on and off
|
|
// separately.
|
|
if (newEffectsVolume == 0) {
|
|
// Global SFX volume 0 mutes both regular and ambient SFX.
|
|
_effectsMuted = _ambientMuted = true;
|
|
} else {
|
|
// If global SFX volume is > 0 and both regular and ambient SFX are
|
|
// muted, unmute them. If only one of them is muted, the volume
|
|
// change will only affect that type of SFX. If both are not muted,
|
|
// it will affect both types.
|
|
if (_effectsMuted && _ambientMuted)
|
|
_effectsMuted = _ambientMuted = false;
|
|
_effectsVolume = newEffectsVolume;
|
|
}
|
|
// Engine::syncSoundSettings applies SFX volume to all SFX handles,
|
|
// so manage the regular and ambient handles separately here.
|
|
_sound->effectsMute(_effectsMuted, _effectsVolume);
|
|
_sound->ambientMute(_ambientMuted, _effectsVolume);
|
|
} else {
|
|
// Other games only have one SFX setting.
|
|
_effectsMuted = newEffectsVolume == 0;
|
|
if (newEffectsVolume != 0)
|
|
_effectsVolume = newEffectsVolume;
|
|
}
|
|
_speech = !ConfMan.getBool("speech_mute");
|
|
|
|
if (_midiEnabled)
|
|
_midi->syncSoundSettings();
|
|
}
|
|
|
|
void AGOSEngine::syncSoundSettingsIntern() {
|
|
ConfMan.setBool("speech_mute", !_speech);
|
|
ConfMan.setInt("music_volume", _musicMuted ? 0 : _musicVolume);
|
|
bool sfxMute = getGameType() == GType_SIMON2 ?
|
|
_effectsMuted && _ambientMuted : _effectsMuted;
|
|
ConfMan.setInt("sfx_volume", sfxMute ? 0 : _effectsVolume);
|
|
|
|
Engine::syncSoundSettings();
|
|
|
|
if (getGameType() == GType_SIMON2) {
|
|
// Simon 2 has ambient sound effects, which can be toggled on and off
|
|
// separately from the other SFX.
|
|
// Engine::syncSoundSettings applies SFX volume to all SFX handles,
|
|
// so manage the regular and ambient handles separately here.
|
|
_sound->effectsMute(_effectsMuted, _effectsVolume);
|
|
_sound->ambientMute(_ambientMuted, _effectsVolume);
|
|
}
|
|
|
|
if (_midiEnabled)
|
|
_midi->syncSoundSettings();
|
|
}
|
|
|
|
} // End of namespace AGOS
|