mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-10 12:55:24 +00:00
![Colin Snover](/assets/img/avatar_default.png)
This flag is removed for a few reasons: * Engines universally set this flag to true for widths > 320, which made it redundant everywhere; * This flag functioned primarily as a "force 1x scaler" flag, since its behaviour was almost completely undocumented and users would need to figure out that they'd need an explicit non-default scaler set to get a scaler to operate at widths > 320; * (Most importantly) engines should not be in the business of deciding how the backend may choose to render its virtual screen. The choice of rendering behaviour belongs to the user, and the backend, in that order. A nearby future commit restores the default1x scaler behaviour in the SDL backend code for the moment, but in the future it is my hope that there will be a better configuration UI to allow users to specify how they want scaling to work for high resolutions.
387 lines
10 KiB
C++
387 lines
10 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 "base/plugins.h"
|
|
|
|
#include "common/config-manager.h"
|
|
#include "common/events.h"
|
|
#include "common/file.h"
|
|
#include "common/fs.h"
|
|
#include "common/savefile.h"
|
|
#include "common/system.h"
|
|
#include "common/textconsole.h"
|
|
|
|
#include "engines/util.h"
|
|
|
|
#include "queen/queen.h"
|
|
#include "queen/bankman.h"
|
|
#include "queen/command.h"
|
|
#include "queen/cutaway.h"
|
|
#include "queen/debug.h"
|
|
#include "queen/display.h"
|
|
#include "queen/graphics.h"
|
|
#include "queen/grid.h"
|
|
#include "queen/input.h"
|
|
#include "queen/logic.h"
|
|
#include "queen/resource.h"
|
|
#include "queen/sound.h"
|
|
#include "queen/talk.h"
|
|
#include "queen/walk.h"
|
|
|
|
namespace Queen {
|
|
|
|
QueenEngine::QueenEngine(OSystem *syst)
|
|
: Engine(syst), _debugger(0), randomizer("queen") {
|
|
}
|
|
|
|
QueenEngine::~QueenEngine() {
|
|
delete _bam;
|
|
delete _resource;
|
|
delete _bankMan;
|
|
delete _command;
|
|
delete _debugger;
|
|
delete _display;
|
|
delete _graphics;
|
|
delete _grid;
|
|
delete _input;
|
|
delete _logic;
|
|
delete _sound;
|
|
delete _walk;
|
|
}
|
|
|
|
void QueenEngine::registerDefaultSettings() {
|
|
ConfMan.registerDefault("talkspeed", Logic::DEFAULT_TALK_SPEED);
|
|
ConfMan.registerDefault("subtitles", true);
|
|
_subtitles = true;
|
|
}
|
|
|
|
void QueenEngine::checkOptionSettings() {
|
|
// check talkspeed value
|
|
if (_talkSpeed < MIN_TEXT_SPEED) {
|
|
_talkSpeed = MIN_TEXT_SPEED;
|
|
} else if (_talkSpeed > MAX_TEXT_SPEED) {
|
|
_talkSpeed = MAX_TEXT_SPEED;
|
|
}
|
|
|
|
// demo and interview versions don't have speech at all
|
|
if (_sound->speechOn() && (_resource->isDemo() || _resource->isInterview())) {
|
|
_sound->speechToggle(false);
|
|
}
|
|
|
|
// ensure text is always on when voice is off
|
|
if (!_sound->speechOn()) {
|
|
_subtitles = true;
|
|
}
|
|
}
|
|
|
|
void QueenEngine::syncSoundSettings() {
|
|
Engine::syncSoundSettings();
|
|
|
|
readOptionSettings();
|
|
}
|
|
|
|
void QueenEngine::readOptionSettings() {
|
|
bool mute = false;
|
|
if (ConfMan.hasKey("mute"))
|
|
mute = ConfMan.getBool("mute");
|
|
|
|
_sound->setVolume(ConfMan.getInt("music_volume"));
|
|
_sound->musicToggle(!(mute || ConfMan.getBool("music_mute")));
|
|
_sound->sfxToggle(!(mute || ConfMan.getBool("sfx_mute")));
|
|
_sound->speechToggle(!(mute || ConfMan.getBool("speech_mute")));
|
|
_talkSpeed = (ConfMan.getInt("talkspeed") * (MAX_TEXT_SPEED - MIN_TEXT_SPEED) + 255 / 2) / 255 + MIN_TEXT_SPEED;
|
|
_subtitles = ConfMan.getBool("subtitles");
|
|
checkOptionSettings();
|
|
}
|
|
|
|
void QueenEngine::writeOptionSettings() {
|
|
ConfMan.setInt("music_volume", _sound->getVolume());
|
|
ConfMan.setBool("music_mute", !_sound->musicOn());
|
|
ConfMan.setBool("sfx_mute", !_sound->sfxOn());
|
|
ConfMan.setInt("talkspeed", ((_talkSpeed - MIN_TEXT_SPEED) * 255 + (MAX_TEXT_SPEED - MIN_TEXT_SPEED) / 2) / (MAX_TEXT_SPEED - MIN_TEXT_SPEED));
|
|
ConfMan.setBool("speech_mute", !_sound->speechOn());
|
|
ConfMan.setBool("subtitles", _subtitles);
|
|
ConfMan.flushToDisk();
|
|
}
|
|
|
|
void QueenEngine::update(bool checkPlayerInput) {
|
|
_debugger->onFrame();
|
|
|
|
_graphics->update(_logic->currentRoom());
|
|
_logic->update();
|
|
|
|
int frameDelay = (_lastUpdateTime + Input::DELAY_NORMAL - _system->getMillis());
|
|
if (frameDelay <= 0) {
|
|
frameDelay = 1;
|
|
}
|
|
_input->delay(frameDelay);
|
|
_lastUpdateTime = _system->getMillis();
|
|
|
|
if (!_resource->isInterview()) {
|
|
_display->palCustomScroll(_logic->currentRoom());
|
|
}
|
|
BobSlot *joe = _graphics->bob(0);
|
|
_display->update(joe->active, joe->x, joe->y);
|
|
|
|
_input->checkKeys();
|
|
if (_input->debugger()) {
|
|
_input->debuggerReset();
|
|
_debugger->attach();
|
|
}
|
|
if (canLoadOrSave()) {
|
|
if (_input->quickSave()) {
|
|
_input->quickSaveReset();
|
|
saveGameState(SLOT_QUICKSAVE, "Quicksave");
|
|
}
|
|
if (_input->quickLoad()) {
|
|
_input->quickLoadReset();
|
|
loadGameState(SLOT_QUICKSAVE);
|
|
}
|
|
if (shouldPerformAutoSave(_lastSaveTime)) {
|
|
saveGameState(SLOT_AUTOSAVE, "Autosave");
|
|
_lastSaveTime = _system->getMillis();
|
|
}
|
|
}
|
|
if (!_input->cutawayRunning()) {
|
|
if (checkPlayerInput) {
|
|
_command->updatePlayer();
|
|
}
|
|
if (_input->idleTime() >= Input::DELAY_SCREEN_BLANKER) {
|
|
_display->blankScreen();
|
|
}
|
|
}
|
|
_sound->updateMusic();
|
|
}
|
|
|
|
bool QueenEngine::canLoadOrSave() const {
|
|
return !_input->cutawayRunning() && !(_resource->isDemo() || _resource->isInterview());
|
|
}
|
|
|
|
bool QueenEngine::canLoadGameStateCurrently() {
|
|
return canLoadOrSave();
|
|
}
|
|
|
|
bool QueenEngine::canSaveGameStateCurrently() {
|
|
return canLoadOrSave();
|
|
}
|
|
|
|
Common::Error QueenEngine::saveGameState(int slot, const Common::String &desc) {
|
|
debug(3, "Saving game to slot %d", slot);
|
|
char name[20];
|
|
Common::Error err = Common::kNoError;
|
|
makeGameStateName(slot, name);
|
|
Common::OutSaveFile *file = _saveFileMan->openForSaving(name);
|
|
if (file) {
|
|
// save data
|
|
byte *saveData = new byte[SAVESTATE_MAX_SIZE];
|
|
byte *p = saveData;
|
|
_bam->saveState(p);
|
|
_grid->saveState(p);
|
|
_logic->saveState(p);
|
|
_sound->saveState(p);
|
|
uint32 dataSize = p - saveData;
|
|
assert(dataSize < SAVESTATE_MAX_SIZE);
|
|
|
|
// write header
|
|
file->writeUint32BE('SCVM');
|
|
file->writeUint32BE(SAVESTATE_CUR_VER);
|
|
file->writeUint32BE(0);
|
|
file->writeUint32BE(dataSize);
|
|
char description[32];
|
|
Common::strlcpy(description, desc.c_str(), sizeof(description));
|
|
file->write(description, sizeof(description));
|
|
|
|
// write save data
|
|
file->write(saveData, dataSize);
|
|
file->finalize();
|
|
|
|
// check for errors
|
|
if (file->err()) {
|
|
warning("Can't write file '%s'. (Disk full?)", name);
|
|
err = Common::kWritingFailed;
|
|
}
|
|
delete[] saveData;
|
|
delete file;
|
|
} else {
|
|
warning("Can't create file '%s', game not saved", name);
|
|
err = Common::kCreatingFileFailed;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
Common::Error QueenEngine::loadGameState(int slot) {
|
|
debug(3, "Loading game from slot %d", slot);
|
|
Common::Error err = Common::kNoError;
|
|
GameStateHeader header;
|
|
Common::InSaveFile *file = readGameStateHeader(slot, &header);
|
|
if (file && header.dataSize != 0) {
|
|
byte *saveData = new byte[header.dataSize];
|
|
byte *p = saveData;
|
|
if (file->read(saveData, header.dataSize) != header.dataSize) {
|
|
warning("Error reading savegame file");
|
|
err = Common::kReadingFailed;
|
|
} else {
|
|
_bam->loadState(header.version, p);
|
|
_grid->loadState(header.version, p);
|
|
_logic->loadState(header.version, p);
|
|
_sound->loadState(header.version, p);
|
|
if (header.dataSize != (uint32)(p - saveData)) {
|
|
warning("Corrupted savegame file");
|
|
err = Common::kReadingFailed; // FIXME
|
|
} else {
|
|
_logic->setupRestoredGame();
|
|
}
|
|
}
|
|
delete[] saveData;
|
|
delete file;
|
|
} else {
|
|
err = Common::kReadingFailed;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
Common::InSaveFile *QueenEngine::readGameStateHeader(int slot, GameStateHeader *gsh) {
|
|
char name[20];
|
|
makeGameStateName(slot, name);
|
|
Common::InSaveFile *file = _saveFileMan->openForLoading(name);
|
|
if (file && file->readUint32BE() == MKTAG('S','C','V','M')) {
|
|
gsh->version = file->readUint32BE();
|
|
gsh->flags = file->readUint32BE();
|
|
gsh->dataSize = file->readUint32BE();
|
|
file->read(gsh->description, sizeof(gsh->description));
|
|
} else {
|
|
memset(gsh, 0, sizeof(GameStateHeader));
|
|
}
|
|
return file;
|
|
}
|
|
|
|
void QueenEngine::makeGameStateName(int slot, char *buf) const {
|
|
if (slot == SLOT_LISTPREFIX) {
|
|
strcpy(buf, "queen.s??");
|
|
} else if (slot == SLOT_AUTOSAVE) {
|
|
strcpy(buf, "queen.asd");
|
|
} else {
|
|
assert(slot >= 0);
|
|
sprintf(buf, "queen.s%02d", slot);
|
|
}
|
|
}
|
|
|
|
int QueenEngine::getGameStateSlot(const char *filename) const {
|
|
int i = -1;
|
|
const char *slot = strrchr(filename, '.');
|
|
if (slot && (slot[1] == 's' || slot[1] == 'S')) {
|
|
i = atoi(slot + 2);
|
|
}
|
|
return i;
|
|
}
|
|
|
|
void QueenEngine::findGameStateDescriptions(char descriptions[100][32]) {
|
|
char prefix[20];
|
|
makeGameStateName(SLOT_LISTPREFIX, prefix);
|
|
Common::StringArray filenames = _saveFileMan->listSavefiles(prefix);
|
|
for (Common::StringArray::const_iterator it = filenames.begin(); it != filenames.end(); ++it) {
|
|
int i = getGameStateSlot(it->c_str());
|
|
if (i >= 0 && i < SAVESTATE_MAX_NUM) {
|
|
GameStateHeader header;
|
|
Common::InSaveFile *f = readGameStateHeader(i, &header);
|
|
strcpy(descriptions[i], header.description);
|
|
delete f;
|
|
}
|
|
}
|
|
}
|
|
|
|
GUI::Debugger *QueenEngine::getDebugger() {
|
|
return _debugger;
|
|
}
|
|
|
|
bool Queen::QueenEngine::hasFeature(EngineFeature f) const {
|
|
return
|
|
(f == kSupportsRTL) ||
|
|
(f == kSupportsLoadingDuringRuntime) ||
|
|
(f == kSupportsSavingDuringRuntime) ||
|
|
(f == kSupportsSubtitleOptions);
|
|
}
|
|
|
|
Common::Error QueenEngine::run() {
|
|
initGraphics(GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT);
|
|
|
|
_resource = new Resource();
|
|
|
|
_bam = new BamScene(this);
|
|
_bankMan = new BankManager(_resource);
|
|
_command = new Command(this);
|
|
_debugger = new Debugger(this);
|
|
_display = new Display(this, _system);
|
|
_graphics = new Graphics(this);
|
|
_grid = new Grid(this);
|
|
_input = new Input(_resource->getLanguage(), _system);
|
|
|
|
if (_resource->isDemo()) {
|
|
_logic = new LogicDemo(this);
|
|
} else if (_resource->isInterview()) {
|
|
_logic = new LogicInterview(this);
|
|
} else {
|
|
_logic = new LogicGame(this);
|
|
}
|
|
|
|
_sound = Sound::makeSoundInstance(_mixer, this, _resource->getCompression());
|
|
|
|
_walk = new Walk(this);
|
|
//_talkspeedScale = (MAX_TEXT_SPEED - MIN_TEXT_SPEED) / 255.0;
|
|
|
|
registerDefaultSettings();
|
|
|
|
// Setup mixer
|
|
syncSoundSettings();
|
|
|
|
_logic->start();
|
|
if (ConfMan.hasKey("save_slot") && canLoadOrSave()) {
|
|
loadGameState(ConfMan.getInt("save_slot"));
|
|
}
|
|
_lastSaveTime = _lastUpdateTime = _system->getMillis();
|
|
|
|
while (!shouldQuit()) {
|
|
if (_logic->newRoom() > 0) {
|
|
_logic->update();
|
|
_logic->oldRoom(_logic->currentRoom());
|
|
_logic->currentRoom(_logic->newRoom());
|
|
_logic->changeRoom();
|
|
_display->fullscreen(false);
|
|
if (_logic->currentRoom() == _logic->newRoom()) {
|
|
_logic->newRoom(0);
|
|
}
|
|
} else if (_logic->joeWalk() == JWM_EXECUTE) {
|
|
_logic->joeWalk(JWM_NORMAL);
|
|
_command->executeCurrentAction();
|
|
} else {
|
|
_logic->joeWalk(JWM_NORMAL);
|
|
update(true);
|
|
}
|
|
}
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
} // End of namespace Queen
|