Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
/* 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/scummsys.h"
#if defined(__amigaos4__)
#include "backends/fs/amigaos/amigaos-fs.h"
#include "backends/platform/sdl/amigaos/amigaos.h"
#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
int main(int argc, char *argv[]) {
// Update support (AmiUpdate):
// This will save ScummVM's system application name and add it's binary
// path to a variable in the platforms native ENV(ARC) system.
const char *const appname = "ScummVM";
BPTR lock;
APTR reqwin;
// Obtain a lock to it's home directory.
if ((lock = IDOS->GetProgramDir())) {
TEXT progpath[2048];
TEXT apppath[1024] = "AppPaths";
if (IDOS->DevNameFromLock(lock, progpath, sizeof(progpath), DN_FULLPATH)) {
// Stop any "Please insert volume ..." type system requester.
reqwin = IDOS->SetProcWindow((APTR)-1);
// Set the AppPaths variable to the path the binary was run from.
IDOS->AddPart(apppath, appname, 1024);
IDOS->SetVar(apppath, progpath, -1, GVF_GLOBAL_ONLY|GVF_SAVE_VAR);
// Turn system requester back on.
IDOS->SetProcWindow(reqwin);
}
}
// Set a stack cookie to avoid crashes from a too low stack.
static const char *stack_cookie __attribute__((used)) = "$STACK: 4096000";
// Create our OSystem instance.
g_system = new OSystem_AmigaOS();
assert(g_system);
// Pre-initialize the backend.
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point.
int res = scummvm_main(argc, argv);
// Free OSystem.
g_system->destroy();
return res;
}
#endif

View File

@@ -0,0 +1,156 @@
/* 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/scummsys.h"
#ifdef __amigaos4__
#include "backends/platform/sdl/amigaos/amigaos.h"
#include "backends/fs/amigaos/amigaos-fs-factory.h"
#include "backends/dialogs/amigaos/amigaos-dialogs.h"
static bool cleanupDone = false;
#if SDL_VERSION_ATLEAST(3, 0, 0)
static bool sdlGLLoadLibrary(const char *path) {
return SDL_GL_LoadLibrary(path);
}
#else
static bool sdlGLLoadLibrary(const char *path) {
return SDL_GL_LoadLibrary(path) != 0;
}
#endif
static void cleanup() {
if (!cleanupDone)
g_system->destroy();
}
OSystem_AmigaOS::~OSystem_AmigaOS() {
cleanupDone = true;
}
void OSystem_AmigaOS::init() {
// Register cleanup function to avoid unfreed signals
if (atexit(cleanup))
warning("Failed to register cleanup function via atexit()");
// Initialize File System Factory
_fsFactory = new AmigaOSFilesystemFactory();
// Invoke parent implementation of this method
OSystem_SDL::init();
#if defined(USE_SYSDIALOGS)
_dialogManager = new AmigaOSDialogManager();
#endif
}
bool OSystem_AmigaOS::hasFeature(Feature f) {
#if defined(USE_SYSDIALOGS)
if (f == kFeatureSystemBrowserDialog)
return true;
#endif
return OSystem_SDL::hasFeature(f);
}
void OSystem_AmigaOS::initBackend() {
// AmigaOS4 SDL provides two OpenGL implementations
// (OpenGL 1.3 with miniGL and OpenGL ES with OGLES2)
// This is chosen by setting the profile mask attribute
// before the first window creation but after init
int force = 0;
if (ConfMan.hasKey("opengl_implementation")) {
Common::String implem = ConfMan.get("opengl_implementation");
if (implem == "gl") {
force = 1;;
} else if (implem == "gles2") {
force = 2;
}
}
// If not forcing, try OGLES2 first
if (!force || force == 2) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
if (!sdlGLLoadLibrary(NULL)) {
if (force) {
warning("OpenGL implementation chosen is unsupported, falling back");
force = 0;
}
// SDL doesn't seem to be clean when loading fail
SDL_GL_UnloadLibrary();
SDL_GL_ResetAttributes();
} else {
// Loading succeeded, don't try anything more
force = 2;
}
}
// If not forcing, next try miniGL
if (!force || force == 1) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
if (!sdlGLLoadLibrary(NULL)) {
if (force) {
warning("OpenGL implementation chosen is unsupported, falling back");
force = 0;
}
// SDL doesn't seem to be clean when loading fail
SDL_GL_UnloadLibrary();
SDL_GL_ResetAttributes();
} else {
// Loading succeeded, don't try anything more
force = 1;
}
}
// First time user defaults
ConfMan.registerDefault("audio_buffer_size", "2048");
ConfMan.registerDefault("extrapath", Common::Path("extras/"));
ConfMan.registerDefault("iconspath", Common::Path("icons/"));
ConfMan.registerDefault("pluginspath", Common::Path("plugins/"));
ConfMan.registerDefault("savepath", Common::Path("saves/"));
ConfMan.registerDefault("themepath", Common::Path("themes/"));
// First time .ini defaults
if (!ConfMan.hasKey("audio_buffer_size")) {
ConfMan.set("audio_buffer_size", "2048");
}
if (!ConfMan.hasKey("extrapath")) {
ConfMan.setPath("extrapath", "extras/");
}
if (!ConfMan.hasKey("iconspath")) {
ConfMan.setPath("iconspath", "icons/");
}
if (!ConfMan.hasKey("pluginspath")) {
ConfMan.setPath("pluginspath", "plugins/");
}
if (!ConfMan.hasKey("savepath")) {
ConfMan.setPath("savepath", "saves/");
}
if (!ConfMan.hasKey("themepath")) {
ConfMan.setPath("themepath", "themes/");
}
OSystem_SDL::initBackend();
}
#endif

View File

@@ -0,0 +1,38 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_AMIGAOS_H
#define PLATFORM_SDL_AMIGAOS_H
#include "backends/platform/sdl/sdl.h"
class OSystem_AmigaOS : public OSystem_SDL {
public:
OSystem_AmigaOS() {}
virtual ~OSystem_AmigaOS();
bool hasFeature(Feature f) override;
void init() override;
void initBackend() override;
};
#endif

View File

@@ -0,0 +1,74 @@
# Special target to create an AmigaOS snapshot installation.
#
# WORKAROUNDS:
#
# 'mkdir' seems to incorrectly set permissions to path/dirs on AmigaOS.
# Once a vanilla installation is created, none of the corresponding subdirs
# are found or accessible (extras, themes, plugins), instead ScummVM will
# report missing theme files and a missing valid translation.dat. Same with
# cross-partition access (which make we wonder if it's a FS bug afterall).
# Switching to AmigaOS' own "makedir" until there is a fix or other solution.
#
amigaosdist: $(EXECUTABLE) $(PLUGINS)
# Releases should always be completely fresh installs.
rm -rf $(AMIGAOSPATH)
makedir all $(AMIGAOSPATH)
$(CP) ${srcdir}/dists/amigaos/scummvm_drawer.info $(patsubst %/,%,$(AMIGAOSPATH)).info
$(CP) ${srcdir}/dists/amigaos/scummvm.info $(AMIGAOSPATH)/$(EXECUTABLE).info
ifdef DIST_FILES_DOCS
makedir all $(AMIGAOSPATH)/doc
$(CP) $(DIST_FILES_DOCS) $(AMIGAOSPATH)/doc
$(foreach lang, $(DIST_FILES_DOCS_languages), makedir all $(AMIGAOSPATH)/doc/$(lang); $(CP) $(DIST_FILES_DOCS_$(lang)) $(AMIGAOSPATH)/doc/$(lang);)
# README.md and corresponding scripts must be in cwd
# when building out of tree.
$(CP) ${srcdir}/README.md README.tmp
$(CP) ${srcdir}/dists/amigaos/md2ag.rexx .
# (buildbot) LC_ALL is here to work around Debian bug #973647
LC_ALL=C rx md2ag.rexx README.tmp $(AMIGAOSPATH)/doc/
rm -f md2ag.rexx README.tmp
endif
# Copy mandatory installation files.
makedir all $(AMIGAOSPATH)/extras
ifdef DIST_FILES_ENGINEDATA
$(CP) $(DIST_FILES_ENGINEDATA) $(AMIGAOSPATH)/extras
endif
ifdef DIST_FILES_NETWORKING
$(CP) $(DIST_FILES_NETWORKING) $(AMIGAOSPATH)/extras
endif
ifdef DIST_FILES_VKEYBD
$(CP) $(DIST_FILES_VKEYBD) $(AMIGAOSPATH)/extras
endif
ifdef DIST_FILES_THEMES
makedir all $(AMIGAOSPATH)/themes
$(CP) $(DIST_FILES_THEMES) $(AMIGAOSPATH)/themes
endif
ifneq ($(DIST_FILES_SHADERS),)
makedir all $(AMIGAOSPATH)/extras/shaders
$(CP) $(DIST_FILES_SHADERS) $(AMIGAOSPATH)/extras/shaders
endif
ifdef DYNAMIC_MODULES
makedir all $(AMIGAOSPATH)/plugins
# Catch edge-case when no engines/plugins are compiled
# otherwise cp/strip will error out due to missing source files.
ifneq ($(PLUGINS),)
ifdef DEBUG_BUILD
# Preserve all debug information on debug builds
$(CP) $(PLUGINS) $(AMIGAOSPATH)/plugins/$(plugin)
else
$(foreach plugin, $(PLUGINS), $(STRIP) $(plugin) -o $(AMIGAOSPATH)/$(plugin);)
endif
endif
makedir all $(AMIGAOSPATH)/sobjs
# AmigaOS installations, especially vanilla ones, won't have every
# mandatory shared library in place, let alone the correct versions.
# Extract and install compiled-in shared libraries to their own subdir.
$(CP) ${srcdir}/dists/amigaos/install_deps.rexx .
rx install_deps.rexx $(EXECUTABLE) $(AMIGAOSPATH)
rm -f install_deps.rexx
endif
ifdef DEBUG_BUILD
# Preserve all debug information on debug builds
$(CP) $(EXECUTABLE) $(AMIGAOSPATH)/$(EXECUTABLE)
else
$(STRIP) $(EXECUTABLE) -o $(AMIGAOSPATH)/$(EXECUTABLE)
endif

View File

@@ -0,0 +1,50 @@
/* 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/scummsys.h"
#if defined(__EMSCRIPTEN__)
#include "backends/platform/sdl/emscripten/emscripten.h"
#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
int main(int argc, char *argv[]) {
// Create our OSystem instance
g_system = new OSystem_Emscripten();
assert(g_system);
// Pre initialize the backend
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
return res;
}
#endif

View File

@@ -0,0 +1,261 @@
/* 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/>.
*
*/
#ifdef __EMSCRIPTEN__
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
#define FORBIDDEN_SYMBOL_EXCEPTION_getenv
#include <emscripten.h>
#include "backends/events/emscriptensdl/emscriptensdl-events.h"
#include "backends/fs/emscripten/emscripten-fs-factory.h"
#include "backends/mutex/null/null-mutex.h"
#include "backends/fs/emscripten/emscripten-fs-factory.h"
#include "backends/platform/sdl/emscripten/emscripten.h"
#include "backends/timer/default/default-timer.h"
#include "common/file.h"
#ifdef USE_TTS
#include "backends/text-to-speech/emscripten/emscripten-text-to-speech.h"
#endif
// Inline JavaScript, see https://emscripten.org/docs/api_reference/emscripten.h.html#inline-assembly-javascript for details
EM_JS(bool, isFullscreen, (), {
return !!document.fullscreenElement;
});
EM_JS(void, toggleFullscreen, (bool enable), {
let canvas = document.getElementById('canvas');
if (enable && !document.fullscreenElement) {
canvas.requestFullscreen();
}
if (!enable && document.fullscreenElement) {
document.exitFullscreen();
}
});
EM_JS(void, downloadFile, (const char *filenamePtr, char *dataPtr, int dataSize), {
const view = new Uint8Array(Module.HEAPU8.buffer, dataPtr, dataSize);
const blob = new Blob([view], {
type:
'octet/stream'
});
const filename = UTF8ToString(filenamePtr);
setTimeout(() => {
const a = document.createElement('a');
a.style = 'display:none';
document.body.appendChild(a);
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}, 0);
});
#ifdef USE_CLOUD
/* Listener to feed the activation JSON from the wizard at cloud.scummvm.org back
* Usage: Run the following on the final page of the activation flow:
* window.opener.postMessage(document.getElementById("json").value,"*")
*/
EM_JS(bool, cloud_connection_open_oauth_window, (char const *url), {
oauth_window = window.open(UTF8ToString(url));
window.addEventListener("message", (event) => {
Module._cloud_connection_json_callback(stringToNewUTF8( JSON.stringify(event.data)));
oauth_window.close()
}, {once : true});
return true;
});
#endif
extern "C" {
#ifdef USE_CLOUD
void EMSCRIPTEN_KEEPALIVE cloud_connection_json_callback(char *str) {
warning("cloud_connection_callback: %s", str);
OSystem_Emscripten *emscripten_g_system = dynamic_cast<OSystem_Emscripten *>(g_system);
if (emscripten_g_system->_cloudConnectionCallback) {
(*emscripten_g_system->_cloudConnectionCallback)(new Common::String(str));
} else {
warning("No Storage Connection Callback Registered!");
}
}
#endif
}
// Overridden functions
void OSystem_Emscripten::initBackend() {
#ifdef USE_TTS
// Initialize Text to Speech manager
_textToSpeechManager = new EmscriptenTextToSpeechManager();
#endif
// SDL Timers don't work in Emscripten unless threads are enabled or Asyncify is disabled.
// We can do neither, so we use the DefaultTimerManager instead.
_timerManager = new DefaultTimerManager();
// Event source
_eventSource = new EmscriptenSdlEventSource();
// Invoke parent implementation of this method
OSystem_POSIX::initBackend();
}
void OSystem_Emscripten::init() {
// Initialze File System Factory
EmscriptenFilesystemFactory *fsFactory = new EmscriptenFilesystemFactory();
_fsFactory = fsFactory;
// Invoke parent implementation of this method
OSystem_SDL::init();
}
bool OSystem_Emscripten::hasFeature(Feature f) {
if (f == kFeatureFullscreenMode)
return true;
if (f == kFeatureNoQuit)
return true;
return OSystem_POSIX::hasFeature(f);
}
bool OSystem_Emscripten::getFeatureState(Feature f) {
if (f == kFeatureFullscreenMode) {
return isFullscreen();
} else {
return OSystem_POSIX::getFeatureState(f);
}
}
void OSystem_Emscripten::setFeatureState(Feature f, bool enable) {
if (f == kFeatureFullscreenMode) {
toggleFullscreen(enable);
} else {
OSystem_POSIX::setFeatureState(f, enable);
}
}
Common::Path OSystem_Emscripten::getDefaultLogFileName() {
return Common::Path("/tmp/scummvm.log");
}
Common::Path OSystem_Emscripten::getDefaultConfigFileName() {
return Common::Path(Common::String::format("%s/scummvm.ini", getenv("HOME")));
}
Common::Path OSystem_Emscripten::getScreenshotsPath() {
return Common::Path("/tmp/");
}
Common::Path OSystem_Emscripten::getDefaultIconsPath() {
return Common::Path(DATA_PATH"/gui-icons/");
}
bool OSystem_Emscripten::displayLogFile() {
if (_logFilePath.empty())
return false;
exportFile(_logFilePath);
return true;
}
#ifdef USE_OPENGL
OSystem_SDL::GraphicsManagerType OSystem_Emscripten::getDefaultGraphicsManager() const {
return GraphicsManagerOpenGL;
}
#endif
void OSystem_Emscripten::exportFile(const Common::Path &filename) {
Common::File file;
Common::FSNode node(filename);
file.open(node);
if (!file.isOpen()) {
warning("Could not open file %s!", filename.toString(Common::Path::kNativeSeparator).c_str());
return;
}
Common::String exportName = filename.getLastComponent().toString(Common::Path::kNativeSeparator);
const int32 size = file.size();
char *bytes = new char[size + 1];
file.read(bytes, size);
file.close();
downloadFile(exportName.c_str(), bytes, size);
delete[] bytes;
}
void OSystem_Emscripten::updateTimers() {
// avoid a recursion loop if a timer callback decides to call OSystem::delayMillis()
static bool inTimer = false;
if (!inTimer) {
inTimer = true;
((DefaultTimerManager *)_timerManager)->checkTimers();
inTimer = false;
} else {
const Common::ConfigManager::Domain *activeDomain = ConfMan.getActiveDomain();
assert(activeDomain);
warning("%s/%s calls update() from timer",
activeDomain->getValOrDefault("engineid").c_str(),
activeDomain->getValOrDefault("gameid").c_str());
}
}
Common::MutexInternal *OSystem_Emscripten::createMutex() {
return new NullMutexInternal();
}
void OSystem_Emscripten::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
// Add the global DATA_PATH (and some sub-folders) to the directory search list
// Note: gui-icons folder is added in GuiManager::initIconsSet
Common::FSNode dataNode(DATA_PATH);
if (dataNode.exists() && dataNode.isDirectory()) {
s.addDirectory(dataNode, priority, 2, false);
}
}
void OSystem_Emscripten::delayMillis(uint msecs) {
static uint32 lastThreshold = 0;
const uint32 threshold = getMillis() + msecs;
if (msecs == 0 && threshold - lastThreshold < 10) {
return;
}
uint32 pause = 0;
do {
#ifdef ENABLE_EVENTRECORDER
if (!g_eventRec.processDelayMillis())
#endif
SDL_Delay(pause);
updateTimers();
pause = getMillis() > threshold ? 0 : threshold - getMillis(); // Avoid negative values
pause = pause > 10 ? 10 : pause; // ensure we don't pause for too long
} while (pause > 0);
lastThreshold = threshold;
}
#ifdef USE_CLOUD
bool OSystem_Emscripten::openUrl(const Common::String &url) {
if(url.hasPrefix("https://cloud.scummvm.org/")){
return cloud_connection_open_oauth_window(url.c_str());
}
return OSystem_SDL::openUrl(url);
}
#endif
#endif

View File

@@ -0,0 +1,74 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_EMSCRIPTEN_H
#define PLATFORM_SDL_EMSCRIPTEN_H
#include "backends/platform/sdl/posix/posix.h"
#ifdef USE_CLOUD
#include "backends/networking/http/request.h"
#include "common/ustr.h"
typedef Common::BaseCallback<const Common::String *> *CloudConnectionCallback;
#endif
extern "C" {
void cloud_connection_json_callback(char *str); // pass cloud storage activation data from JS to setup wizard
}
class OSystem_Emscripten : public OSystem_POSIX {
#ifdef USE_CLOUD
friend void ::cloud_connection_json_callback(char *str);
#endif
protected:
#ifdef USE_CLOUD
CloudConnectionCallback _cloudConnectionCallback;
#endif
public:
void initBackend() override;
bool hasFeature(Feature f) override;
void setFeatureState(Feature f, bool enable) override;
bool getFeatureState(Feature f) override;
bool displayLogFile() override;
Common::Path getScreenshotsPath() override;
Common::Path getDefaultIconsPath() override;
#ifdef USE_OPENGL
GraphicsManagerType getDefaultGraphicsManager() const override;
#endif
Common::MutexInternal *createMutex() override;
void exportFile(const Common::Path &filename);
void delayMillis(uint msecs) override;
void init() override;
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority) override;
#ifdef USE_CLOUD
void setCloudConnectionCallback(CloudConnectionCallback cb) { _cloudConnectionCallback = cb; }
bool openUrl(const Common::String &url) override;
#endif // USE_CLOUD
protected:
Common::Path getDefaultConfigFileName() override;
Common::Path getDefaultLogFileName() override;
private:
void updateTimers();
};
#endif

View File

@@ -0,0 +1,53 @@
# use system python as fallback
# if EMSDK_PYTHON is not set
EMSDK_PYTHON ?= python3
# Special generic target for emscripten static file hosting bundle
dist-emscripten: $(EXECUTABLE) $(PLUGINS)
mkdir -p ./build-emscripten/
mkdir -p ./build-emscripten/data
mkdir -p ./build-emscripten/data/games
mkdir -p ./build-emscripten/data/gui-icons
mkdir -p ./build-emscripten/doc
cp $(EXECUTABLE) ./build-emscripten/
cp $(EXECUTABLE:html=wasm) ./build-emscripten/
cp $(EXECUTABLE:html=js) ./build-emscripten/
cp $(DIST_FILES_DOCS) ./build-emscripten/doc
cp $(DIST_FILES_THEMES) ./build-emscripten/data
zip -d ./build-emscripten/data/shaders.dat anti-aliasing/aa-shader-4.0.glslp anti-aliasing/reverse-aa.glslp cel/MMJ_Cel_Shader_MP.glslp \
crt/crt-guest-dr-venom-fast.glslp crt/crt-guest-dr-venom.glslp crt/crt-hyllian-glow.glslp crt/crt-hyllian.glslp \
crt/crtsim.glslp crt/gtuv50.glslp crt/yee64.glslp crt/yeetron.glslp cubic/cubic-gamma-correct.glslp \
cubic/cubic.glslp denoisers/crt-fast-bilateral-super-xbr.glslp denoisers/fast-bilateral-super-xbr-4p.glslp \
denoisers/fast-bilateral-super-xbr-6p.glslp denoisers/fast-bilateral-super-xbr.glslp dithering/bayer-matrix-dithering.glslp \
dithering/gendither.glslp hqx/hq2x-halphon.glslp interpolation/bandlimit-pixel.glslp interpolation/controlled_sharpness.glslp \
sabr/sabr-hybrid-deposterize.glslp scalefx/scalefx+rAA.glslp scalefx/scalefx-hybrid.glslp scalefx/scalefx.glslp \
scalenx/scale2xSFX.glslp scalenx/scale3x.glslp sharpen/adaptive-sharpen-multipass.glslp sharpen/adaptive-sharpen.glslp \
sharpen/super-xbr-super-res.glslp xbr/2xBR-lv1-multipass.glslp xbr/super-xbr-2p.glslp xbr/super-xbr-3p-smoother.glslp \
xbr/super-xbr-6p-adaptive.glslp xbr/super-xbr-6p-small-details.glslp xbr/super-xbr-6p.glslp xbr/super-xbr-deposterize.glslp \
xbr/xbr-hybrid.glslp xbr/xbr-lv2-3d.glslp xbr/xbr-lv2-noblend.glslp xbr/xbr-lv2.glslp xbr/xbr-lv3-multipass.glslp \
xbr/xbr-lv3.glslp xbr/xbr-mlv4-multipass.glslp
ifdef DIST_FILES_ENGINEDATA
cp $(DIST_FILES_ENGINEDATA) ./build-emscripten/data
endif
ifdef DIST_FILES_NETWORKING
cp $(DIST_FILES_NETWORKING) ./build-emscripten/data
endif
ifdef DIST_FILES_VKEYBD
cp $(DIST_FILES_VKEYBD) ./build-emscripten/data
endif
ifdef DIST_FILES_SOUNDFONTS
cp $(DIST_FILES_SOUNDFONTS) ./build-emscripten/data
endif
ifdef DIST_FILES_SHADERS
mkdir -p ./build-emscripten/data/shaders
cp $(DIST_FILES_SHADERS) ./build-emscripten/data/shaders
endif
ifeq ($(DYNAMIC_MODULES),1)
mkdir -p ./build-emscripten/data/plugins
@for i in $(PLUGINS); do cp $$i ./build-emscripten/data/plugins; done
endif
$(EMSDK_PYTHON) "$(srcdir)/dists/emscripten/build-make_http_index.py" ./build-emscripten/data
cp "$(srcdir)/dists/emscripten/assets/"* ./build-emscripten/
cp "$(srcdir)/gui/themes/common-svg/logo.svg" ./build-emscripten/
cp "$(srcdir)/icons/scummvm.ico" ./build-emscripten/favicon.ico

View File

@@ -0,0 +1,11 @@
#!/bin/bash
set -e
export KOS32_SDK_DIR=$HOME/kolibrios/contrib/sdk
export KOS32_AUTOBUILD=$HOME/autobuild
# Use plugins for both engines and detection as KolibriOS has a limit per executable module
./configure --host=kos32 --enable-release --enable-plugins --default-dynamic --enable-detection-dynamic --with-vorbis-prefix=$KOS32_SDK_DIR/sources/libvorbis-1.3.7 --with-ogg-prefix=$KOS32_SDK_DIR/sources/libogg-1.3.5 --enable-engine=testbed
make -j12 all zip-root scummvm-zip

View File

@@ -0,0 +1,48 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/scummsys.h"
#include "backends/platform/sdl/kolibrios/kolibrios.h"
#include "backends/plugins/kolibrios/kolibrios-provider.h"
#include "base/main.h"
extern "C" int kolibrios_main(int argc, char *argv[]) {
// Create our OSystem instance
g_system = new OSystem_KolibriOS(argv[0]);
assert(g_system);
// Pre initialize the backend
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new KolibriOSPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
return res;
}

View File

@@ -0,0 +1,117 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_getenv
#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
#define FORBIDDEN_SYMBOL_EXCEPTION_exit
#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
#include "common/scummsys.h"
#include "backends/audiocd/default/default-audiocd.h"
#include "backends/platform/sdl/kolibrios/kolibrios.h"
#include "backends/saves/kolibrios/kolibrios-saves.h"
#include "backends/fs/kolibrios/kolibrios-fs-factory.h"
#include "backends/fs/kolibrios/kolibrios-fs.h"
#include "common/textconsole.h"
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
OSystem_KolibriOS::OSystem_KolibriOS(const char *exeName) : _exeName(exeName) {
}
void OSystem_KolibriOS::init() {
_exePath = Common::Path(_exeName).getParent();
if (KolibriOS::assureDirectoryExists("scummvm-home", _exePath.toString().c_str())) {
debug("Using <exec>/scummvm-home");
_writablePath = _exePath.join("scummvm-home");
} else {
KolibriOS::assureDirectoryExists("scummvm", "/tmp0/1");
_writablePath = "/tmp0/1/scummvm";
debug("Using /tmp0/1");
}
// Initialze File System Factory
_fsFactory = new KolibriOSFilesystemFactory();
// Invoke parent implementation of this method
OSystem_SDL::init();
}
void OSystem_KolibriOS::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
Common::FSNode dataNode(_exePath);
s.add("exePath", new Common::FSDirectory(dataNode, 4), priority);
}
void OSystem_KolibriOS::initBackend() {
Common::Path defaultThemePath = _exePath.join("themes");
Common::Path defaultEngineData = _exePath.join("engine-data");
ConfMan.registerDefault("themepath", defaultThemePath);
ConfMan.registerDefault("extrapath", defaultEngineData);
if (!ConfMan.hasKey("themepath")) {
ConfMan.setPath("themepath", defaultThemePath);
}
if (!ConfMan.hasKey("extrapath")) {
ConfMan.setPath("extrapath", defaultEngineData);
}
// Create the savefile manager
if (_savefileManager == 0)
_savefileManager = new KolibriOSSaveFileManager(_writablePath);
// Invoke parent implementation of this method
OSystem_SDL::initBackend();
}
Common::Path OSystem_KolibriOS::getDefaultConfigFileName() {
return _writablePath.join("scummvm.ini");
}
Common::Path OSystem_KolibriOS::getDefaultIconsPath() {
return _exePath.join("icons");
}
Common::Path OSystem_KolibriOS::getScreenshotsPath() {
// If the user has configured a screenshots path, use it
const Common::Path path = OSystem_SDL::getScreenshotsPath();
if (!path.empty()) {
return path;
}
static const char *const SCREENSHOTS_DIR_NAME = "ScummVM Screenshots";
if (!KolibriOS::assureDirectoryExists(SCREENSHOTS_DIR_NAME, _writablePath.toString(Common::Path::kNativeSeparator).c_str())) {
return "";
}
return _writablePath.join(SCREENSHOTS_DIR_NAME);
}
Common::Path OSystem_KolibriOS::getDefaultLogFileName() {
return _writablePath.join("scummvm.log");
}
AudioCDManager *OSystem_KolibriOS::createAudioCDManager() {
return new DefaultAudioCDManager();
}

View File

@@ -0,0 +1,52 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_KOLIBRIOS_H
#define PLATFORM_SDL_KOLIBRIOS_H
#include "backends/platform/sdl/sdl.h"
class OSystem_KolibriOS : public OSystem_SDL {
public:
OSystem_KolibriOS(const char *exeName);
void init() override;
void initBackend() override;
// Default paths
Common::Path getDefaultIconsPath() override;
Common::Path getScreenshotsPath() override;
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority) override;
const Common::Path& getExePath() const { return _exePath; }
protected:
Common::Path getDefaultConfigFileName() override;
Common::Path getDefaultLogFileName() override;
AudioCDManager *createAudioCDManager() override;
private:
Common::Path _exePath;
Common::Path _writablePath;
Common::String _exeName;
};
#endif

View File

@@ -0,0 +1,35 @@
bundle = zip-root
all: scummvm.kos $(EXECUTABLE)
scummvm.kos: $(srcdir)/backends/platform/sdl/kolibrios/wrapper-main.c
+$(QUIET_CC)$(CXX) -I$(KOS32_SDK_DIR)/sources/newlib/libc/include -specs=$(srcdir)/backends/platform/sdl/kolibrios/kolibrios.spec -x c -o $@.coff $<
+$(QUIET)$(KOS32_AUTOBUILD)/tools/win32/bin/kos32-objcopy $@.coff -O binary $@
$(bundle): all
$(RM) -rf $(bundle)
$(MKDIR) -p $(bundle)/scummvm
$(CP) $(DIST_FILES_DOCS) $(bundle)/scummvm
$(MKDIR) $(bundle)/scummvm/themes
$(CP) $(DIST_FILES_THEMES) $(bundle)/scummvm/themes/
ifdef DIST_FILES_ENGINEDATA
$(MKDIR) $(bundle)/scummvm/engine-data
$(CP) $(DIST_FILES_ENGINEDATA) $(bundle)/scummvm/engine-data/
endif
ifdef DIST_FILES_NETWORKING
$(CP) $(DIST_FILES_NETWORKING) $(bundle)/scummvm
endif
ifdef DIST_FILES_VKEYBD
$(CP) $(DIST_FILES_VKEYBD) $(bundle)/scummvm
endif
ifdef DYNAMIC_MODULES
$(MKDIR) $(bundle)/scummvm/plugins/
$(CP) $(PLUGINS) $(bundle)/scummvm/plugins/
endif
$(CP) scummvm.kos $(bundle)/scummvm/scummvm
$(CP) scummvm.dll $(bundle)/scummvm/scummvm.dll
scummvm-zip: $(bundle)
$(RM) scummvm_kolibrios.zip
cd $(bundle) && zip -r ../scummvm_kolibri.zip scummvm

View File

@@ -0,0 +1,15 @@
*lib:
-lc %{!static:-ldll}
*libgcc:
-lsupc++ -lgcc
*link:
%{mdll:%{shared: %eshared and mdll are not compatible} %{static: %estatic and mdll are not compatible}} -L%:getenv(KOS32_SDK_DIR /lib) %{shared|mdll: -shared --entry _DllStartup} %{shared:-T%:getenv(KOS32_SDK_DIR /sources/newlib/dll.lds)} %{static: -static -T%:getenv(KOS32_SDK_DIR /sources/newlib/app.lds)} %{!mdll:%{!static:%{!shared: -call_shared -T%:getenv(KOS32_SDK_DIR /sources/newlib/app-dynamic.lds)}}} %{!mdll:-s --image-base 0} %{mdll:--enable-auto-image-base} %(shared_libgcc_undefs)
*startfile:
*endfile:

View File

@@ -0,0 +1,59 @@
/* 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 <stdio.h>
#include <string.h>
void* get_proc_address(void *handle, const char *proc_name);
void* load_library(const char *name);
/* This is just a small wrapper so that the main scummvm is loaded as dll. */
int kolibrios_main(int argc, char *argv[]);
int main(int argc, char *argv[]) {
printf("Loading SCUMMVM\n");
if (argc < 1 || strnlen(argv[0], 3005) > 3000) {
fprintf(stderr, "Couldn't determine exe path");
return 1;
}
const char *r = strrchr(argv[0], '/');
static char dllName[4000];
int p = 0;
if (r) {
p = r - argv[0] + 1;
memcpy(dllName, argv[0], p);
}
memcpy(dllName + p, "scummvm.dll", sizeof("scummvm.dll"));
void *dlHandle = load_library(dllName);
if (!dlHandle) {
fprintf(stderr, "Couldn't load %s", dllName);
return 2;
}
void (*kolibrios_main) (int argc, char *argv[]) = get_proc_address(dlHandle, "kolibrios_main");
if (!kolibrios_main) {
fprintf(stderr, "Failed to located kolibrios_main");
return 3;
}
kolibrios_main(argc, argv);
}

View File

@@ -0,0 +1,32 @@
/* 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/>.
*
*/
#ifndef APPMENU_OSX_H
#define APPMENU_OSX_H
#if defined(MACOSX)
void replaceApplicationMenuItems();
void releaseMenu();
#endif // MACOSX
#endif

View File

@@ -0,0 +1,350 @@
/* 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/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/platform/sdl/macosx/appmenu_osx.h"
#include "common/translation.h"
#include "common/ustr.h"
#include "backends/platform/sdl/macosx/macosx-compat.h"
#include <Cocoa/Cocoa.h>
#include <AppKit/NSWorkspace.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
#define NSEventModifierFlagCommand NSCommandKeyMask
#define NSEventModifierFlagOption NSAlternateKeyMask
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10
#define NSEventModifierFlags NSUInteger
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Cocoa64BitGuide/64BitChangesCocoa/64BitChangesCocoa.html
#if __LP64__ || NS_BUILD_32_LIKE_64
typedef unsigned long NSUInteger;
#else
typedef unsigned int NSUInteger;
#endif
// Those are not defined in the 10.4 SDK, but they are defined when targeting
// Mac OS X 10.4 or above in the 10.5 SDK, and they do work with 10.4.
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
enum {
NSUTF32StringEncoding = 0x8c000100,
NSUTF32BigEndianStringEncoding = 0x98000100,
NSUTF32LittleEndianStringEncoding = 0x9c000100
};
#endif
#endif
// Apple removed setAppleMenu from the header files in 10.4,
// but as the method still exists we declare it ourselves here.
// Yes, this works :)
@interface NSApplication(MissingFunction)
- (void)setAppleMenu:(NSMenu *)menu;
@end
// However maybe we should conditionally use it depending on the system on which we run ScummVM (and not
// the one on which we compile) to only do it on OS X 10.5.
// Here is the relevant bit from the release notes for 10.6:
// In Leopard and earlier, apps that tried to construct a menu bar without a nib would get an undesirable
// stubby application menu that could not be removed. To work around this problem on Leopard, you can call
// the undocumented setAppleMenu: method and pass it the application menu, like so:
// [NSApp setAppleMenu:[[[NSApp mainMenu] itemAtIndex:0] submenu]];
// In SnowLeopard, this workaround is unnecessary and should not be used. Under SnowLeopard, the first menu
// is always identified as the application menu.
static void openFromBundle(NSString *file, NSString *subdir = nil) {
NSString *path = nil;
NSArray *types = [NSArray arrayWithObjects:@"rtf", @"html", @"txt", @"", @"md", nil];
NSEnumerator *typeEnum = [types objectEnumerator];
NSString *type;
while ((type = [typeEnum nextObject])) {
if (subdir)
path = [[NSBundle mainBundle] pathForResource:file ofType:type inDirectory:subdir];
else
path = [[NSBundle mainBundle] pathForResource:file ofType:type];
if (path)
break;
}
// RTF, TXT, and HTML files are widely recognized and we can rely on the default
// file association working for those. For the other ones this might not be
// the case so we explicitly indicate they should be open with TextEdit.
if (path) {
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_15
if ([path hasSuffix:@".html"] || [path hasSuffix:@".rtf"] || [path hasSuffix:@".txt"])
[[NSWorkspace sharedWorkspace] openFile:path];
else
[[NSWorkspace sharedWorkspace] openFile:path withApplication:@"TextEdit"];
#else
NSURL *pathUrl = [NSURL fileURLWithPath:path isDirectory:NO];
if ([path hasSuffix:@".html"] || [path hasSuffix:@".rtf"] || [path hasSuffix:@".txt"]) {
[[NSWorkspace sharedWorkspace] openURL:pathUrl];
} else {
[[NSWorkspace sharedWorkspace] openURLs:[NSArray arrayWithObjects:pathUrl, nil]
withApplicationAtURL:[[NSWorkspace sharedWorkspace] URLForApplicationWithBundleIdentifier:@"com.apple.TextEdit"]
configuration:[NSWorkspaceOpenConfiguration configuration]
completionHandler:nil
];
}
#endif
}
}
@interface ScummVMMenuHandler : NSObject {
}
- (void) openReadme;
- (void) openLicenseGPL;
- (void) openLicenseApache;
- (void) openLicenseBSD;
- (void) openLicenseBSL;
- (void) openLicenseGLAD;
- (void) openLicenseISC;
- (void) openLicenseLGPL;
- (void) openLicenseLUA;
- (void) openLicenseMIT;
- (void) openLicenseMKV;
- (void) openLicenseMPL;
- (void) openLicenseOFL;
- (void) openLicenseTinyGL;
- (void) openLicenseCatharon;
- (void) openNews;
- (void) openUserManual;
- (void) openCredits;
@end
@implementation ScummVMMenuHandler : NSObject
- (void)openReadme {
openFromBundle(@"README");
}
- (void)openLicenseGPL {
openFromBundle(@"COPYING", @"licenses");
}
- (void)openLicenseApache {
openFromBundle(@"COPYING-Apache", @"licenses");
}
- (void)openLicenseBSD {
openFromBundle(@"COPYING-BSD", @"licenses");
}
- (void)openLicenseBSL {
openFromBundle(@"COPYING-BSL", @"licenses");
}
- (void)openLicenseGLAD {
openFromBundle(@"COPYING-GLAD", @"licenses");
}
- (void)openLicenseISC {
openFromBundle(@"COPYING-ISC", @"licenses");
}
- (void)openLicenseLGPL {
openFromBundle(@"COPYING-LGPL", @"licenses");
}
- (void)openLicenseLUA {
openFromBundle(@"COPYING-LUA", @"licenses");
}
- (void)openLicenseMIT {
openFromBundle(@"COPYING-MIT", @"licenses");
}
- (void)openLicenseMKV {
openFromBundle(@"COPYING-MKV", @"licenses");
}
- (void)openLicenseMPL {
openFromBundle(@"COPYING-MPL", @"licenses");
}
- (void)openLicenseOFL {
openFromBundle(@"COPYING-OFL", @"licenses");
}
- (void)openLicenseTinyGL {
openFromBundle(@"COPYING-TINYGL", @"licenses");
}
- (void)openLicenseCatharon {
openFromBundle(@"CatharonLicense", @"licenses");
}
- (void)openNews {
openFromBundle(@"NEWS");
}
- (void)openUserManual {
NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
// If present locally in the bundle, open that file.
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:bundlePath];
#else
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:bundlePath error:nil];
#endif
if (dirContents != nil) {
NSEnumerator *dirEnum = [dirContents objectEnumerator];
NSString *file;
while ((file = [dirEnum nextObject])) {
if ([file hasPrefix:@"ScummVM Manual"] && [file hasSuffix:@".pdf"]) {
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_15
[[NSWorkspace sharedWorkspace] openFile:[bundlePath stringByAppendingPathComponent:file]];
#else
NSURL *fileUrl = [NSURL fileURLWithPath:[bundlePath stringByAppendingPathComponent:file] isDirectory:NO];
[[NSWorkspace sharedWorkspace] openURL:fileUrl];
#endif
return;
}
}
}
// Otherwise try to access the only version.
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://docs.scummvm.org/"]];
}
- (void)openCredits {
openFromBundle(@"AUTHORS");
}
@end
NSString *constructNSStringFromU32String(const Common::U32String &rawU32String) {
#ifdef SCUMM_LITTLE_ENDIAN
NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
#else
NSStringEncoding stringEncoding = NSUTF32BigEndianStringEncoding;
#endif
return [[NSString alloc] initWithBytes:rawU32String.c_str() length:4*rawU32String.size() encoding: stringEncoding];
}
static NSMenu *addMenu(const Common::U32String &title, NSString *key, SEL setAs) {
if (setAs && ![NSApp respondsToSelector:setAs]) {
return nil;
}
NSString *str = constructNSStringFromU32String(title);
NSMenu *menu = [[NSMenu alloc] initWithTitle:str];
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:str action:nil keyEquivalent:key];
[menuItem setSubmenu:menu];
[[NSApp mainMenu] addItem:menuItem];
if (setAs) {
[NSApp performSelector:setAs withObject:menu];
}
[str release];
[menuItem release];
return menu;
}
static void addMenuItem(const Common::U32String &title, id target, SEL selector, NSString *key, NSMenu *parent, NSEventModifierFlags flags = 0) {
NSString *nsString = constructNSStringFromU32String(title);
NSMenuItem *menuItem = [[NSMenuItem alloc]
initWithTitle:nsString
action:selector
keyEquivalent:key];
if (target) {
[menuItem setTarget:target];
}
if (flags) {
[menuItem setKeyEquivalentModifierMask:flags];
}
[parent addItem:menuItem];
[nsString release];
}
static ScummVMMenuHandler *delegate = nullptr;
void releaseMenu() {
[delegate release];
delegate = nullptr;
}
void replaceApplicationMenuItems() {
// We cannot use [[NSApp mainMenu] removeAllItems] as removeAllItems was added in OS X 10.6
// So remove the SDL generated menus one by one instead.
while ([[NSApp mainMenu] numberOfItems] > 0) {
[[NSApp mainMenu] removeItemAtIndex:0];
}
NSMenu *appleMenu = addMenu(Common::U32String("ScummVM"), @"", @selector(setAppleMenu:));
if (appleMenu) {
addMenuItem(_("About ScummVM"), nil, @selector(orderFrontStandardAboutPanel:), @"", appleMenu);
[appleMenu addItem:[NSMenuItem separatorItem]];
addMenuItem(_("Hide ScummVM"), nil, @selector(hide:), @"h", appleMenu);
addMenuItem(_("Hide Others"), nil, @selector(hideOtherApplications:), @"h", appleMenu, (NSEventModifierFlagOption|NSEventModifierFlagCommand));
addMenuItem(_("Show All"), nil, @selector(unhideAllApplications:), @"", appleMenu);
[appleMenu addItem:[NSMenuItem separatorItem]];
addMenuItem(_("Quit ScummVM"), nil, @selector(terminate:), @"q", appleMenu);
}
NSMenu *windowMenu = addMenu(_("Window"), @"", @selector(setWindowsMenu:));
if (windowMenu) {
addMenuItem(_("Minimize"), nil, @selector(performMiniaturize:), @"m", windowMenu);
}
// Note: special care must be taken for the Help menu before 10.6,
// as setHelpMenu didn't exist yet: give an explicit nil for it in
// addMenu(), and also make sure it's created last.
SEL helpMenuSelector = [NSApp respondsToSelector:@selector(setHelpMenu:)] ? @selector(setHelpMenu:) : nil;
NSMenu *helpMenu = addMenu(_("Help"), @"", helpMenuSelector);
if (helpMenu) {
if (!delegate) {
delegate = [[ScummVMMenuHandler alloc] init];
}
addMenuItem(_("User Manual"), delegate, @selector(openUserManual), @"", helpMenu);
[helpMenu addItem:[NSMenuItem separatorItem]];
addMenuItem(_("General Information"), delegate, @selector(openReadme), @"", helpMenu);
addMenuItem(_("What's New in ScummVM"), delegate, @selector(openNews), @"", helpMenu);
[helpMenu addItem:[NSMenuItem separatorItem]];
addMenuItem(_("Credits"), delegate, @selector(openCredits), @"", helpMenu);
addMenuItem(_("GPL License"), delegate, @selector(openLicenseGPL), @"", helpMenu);
addMenuItem(_("LGPL License"), delegate, @selector(openLicenseLGPL), @"", helpMenu);
addMenuItem(_("OFL License"), delegate, @selector(openLicenseOFL), @"", helpMenu);
addMenuItem(_("BSD License"), delegate, @selector(openLicenseBSD), @"", helpMenu);
addMenuItem(_("Apache License"), delegate, @selector(openLicenseApache), @"", helpMenu);
addMenuItem(_("BSL License"), delegate, @selector(openLicenseBSL), @"", helpMenu);
addMenuItem(_("GLAD License"), delegate, @selector(openLicenseGLAD), @"", helpMenu);
addMenuItem(_("ISC License"), delegate, @selector(openLicenseISC), @"", helpMenu);
addMenuItem(_("Lua License"), delegate, @selector(openLicenseLUA), @"", helpMenu);
addMenuItem(_("MIT License"), delegate, @selector(openLicenseMIT), @"", helpMenu);
addMenuItem(_("MKV License"), delegate, @selector(openLicenseMKV), @"", helpMenu);
addMenuItem(_("MPL License"), delegate, @selector(openLicenseMPL), @"", helpMenu);
addMenuItem(_("TinyGL License"), delegate, @selector(openLicenseTinyGL), @"", helpMenu);
addMenuItem(_("Catharon License"), delegate, @selector(openLicenseCatharon), @"", helpMenu);
}
[appleMenu release];
[windowMenu release];
[helpMenu release];
}

View File

@@ -0,0 +1,51 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_MACOSX_COMPAT_H
#define PLATFORM_SDL_MACOSX_COMPAT_H
#include <AvailabilityMacros.h>
#ifndef MAC_OS_X_VERSION_10_5
#define MAC_OS_X_VERSION_10_5 1050
#endif
#ifndef MAC_OS_X_VERSION_10_6
#define MAC_OS_X_VERSION_10_6 1060
#endif
#ifndef MAC_OS_X_VERSION_10_7
#define MAC_OS_X_VERSION_10_7 1070
#endif
#ifndef MAC_OS_X_VERSION_10_10
#define MAC_OS_X_VERSION_10_10 101000
#endif
#ifndef MAC_OS_X_VERSION_10_12
#define MAC_OS_X_VERSION_10_12 101200
#endif
#ifndef MAC_OS_X_VERSION_10_15
#define MAC_OS_X_VERSION_10_15 101500
#endif
#endif

View File

@@ -0,0 +1,52 @@
/* 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/scummsys.h"
#ifdef MACOSX
#include "backends/platform/sdl/macosx/macosx.h"
#include "backends/plugins/sdl/macosx/macosx-provider.h"
#include "base/main.h"
int main(int argc, char *argv[]) {
// Create our OSystem instance
g_system = new OSystem_MacOSX();
assert(g_system);
// Pre initialize the backend
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new MacOSXPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
return res;
}
#endif

View File

@@ -0,0 +1,33 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_MACOSX_TOUCHBAR_H
#define PLATFORM_SDL_MACOSX_TOUCHBAR_H
#if defined(MACOSX)
void macOSTouchbarCreate();
void macOSTouchbarDestroy();
void macOSTouchbarUpdate(const char *message);
#endif // MACOSX
#endif

View File

@@ -0,0 +1,135 @@
/* 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/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/platform/sdl/macosx/appmenu_osx.h"
#include "backends/platform/sdl/macosx/macosx-compat.h"
#include "common/system.h"
#include "common/events.h"
#include <Cocoa/Cocoa.h>
#include <AppKit/NSWorkspace.h>
#if defined(MAC_OS_X_VERSION_10_12_2) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2
@interface ScummVMlTouchbarDelegate : NSResponder <NSTouchBarDelegate>
@end
@implementation ScummVMlTouchbarDelegate
NSColor *font_color;
NSColor *back_color;
NSButton *tbButton;
- (instancetype)init {
if (self = [super init]) {
font_color = [NSColor whiteColor];
back_color = [NSColor colorWithCalibratedRed:0 green:0.8 blue:0.2 alpha:1.0f];
tbButton = [[NSButton alloc] init];
[[tbButton cell] setBackgroundColor:back_color];
[tbButton setAction:@selector(actionKey:)];
[tbButton setTarget:self];
[self setButton:nil];
}
return self;
}
- (NSTouchBar *)makeTouchBar {
NSTouchBar *bar = [[NSTouchBar alloc] init];
bar.delegate = self;
bar.customizationIdentifier = @"org.ScummVM.Touchbar.Customization";
bar.defaultItemIdentifiers = @[@"textButton"];
return bar;
}
- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
NSCustomTouchBarItem *customItem = [[NSCustomTouchBarItem alloc] initWithIdentifier:@"textButton"];
customItem.view = tbButton;
customItem.visibilityPriority = NSTouchBarItemPriorityHigh;
return customItem;
}
- (void)setButton : (const char *)title {
NSString *ns_title = nil;
if (title) {
ns_title = [NSString stringWithUTF8String:title];
} else {
ns_title = [NSString stringWithUTF8String:"ScummVM"];
}
NSMutableAttributedString *att_title = [[NSMutableAttributedString alloc] initWithString:ns_title];
[tbButton setAttributedTitle:att_title];
[tbButton invalidateIntrinsicContentSize];
}
- (IBAction) actionKey : (id) sender {
Common::Event event;
event.type = Common::EVENT_MAINMENU;
g_system->getEventManager()->pushEvent(event);
}
@end
static ScummVMlTouchbarDelegate *g_tb_delegate = nil;
void macOSTouchbarUpdate(const char *message) {
[g_tb_delegate setButton:message];
}
void macOSTouchbarCreate() {
if (g_tb_delegate)
return;
if (NSAppKitVersionNumber < NSAppKitVersionNumber10_12_2)
return;
NSApplication *app = [NSApplication sharedApplication];
if (!app)
return;
g_tb_delegate = [[ScummVMlTouchbarDelegate alloc] init];
if (g_tb_delegate) {
g_tb_delegate.nextResponder = app.nextResponder;
app.nextResponder = g_tb_delegate;
}
}
void macOSTouchbarDestroy() {
}
#else
void macOSTouchbarCreate() {}
void macOSTouchbarDestroy() {}
void macOSTouchbarUpdate(const char *message) {}
#endif

View File

@@ -0,0 +1,38 @@
/* 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/>.
*
*/
#ifndef BACKENDS_PLATFORM_SDL_MACOSX_MACOSX_WINDOW_H
#define BACKENDS_PLATFORM_SDL_MACOSX_MACOSX_WINDOW_H
#ifdef MACOSX
#include "backends/platform/sdl/sdl-window.h"
class SdlWindow_MacOSX final : public SdlWindow {
public:
// Use an iconless window on macOS, as we use a nicer external icon there.
void setupIcon() override {}
float getDpiScalingFactor() const override;
};
#endif
#endif

View File

@@ -0,0 +1,42 @@
/* 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/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/platform/sdl/macosx/macosx-window.h"
#include "backends/platform/sdl/macosx/macosx-compat.h"
#include <AppKit/NSWindow.h>
float SdlWindow_MacOSX::getDpiScalingFactor() const {
#if !SDL_VERSION_ATLEAST(3, 0, 0) && SDL_VERSION_ATLEAST(2, 0, 0) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
SDL_SysWMinfo wmInfo;
if (getSDLWMInformation(&wmInfo)) {
NSWindow *nswindow = wmInfo.info.cocoa.window;
if ([nswindow respondsToSelector:@selector(backingScaleFactor)]) {
debug(4, "Reported DPI ratio: %g", [nswindow backingScaleFactor]);
return [nswindow backingScaleFactor];
}
}
#endif
return SdlWindow::getDpiScalingFactor();
}

View File

@@ -0,0 +1,303 @@
/* 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/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/scummsys.h"
#ifdef MACOSX
#include "backends/audiocd/macosx/macosx-audiocd.h"
#include "backends/platform/sdl/macosx/appmenu_osx.h"
#include "backends/platform/sdl/macosx/macosx.h"
#include "backends/platform/sdl/macosx/macosx-touchbar.h"
#include "backends/platform/sdl/macosx/macosx-window.h"
#include "backends/updates/macosx/macosx-updates.h"
#include "backends/taskbar/macosx/macosx-taskbar.h"
#include "backends/text-to-speech/macosx/macosx-text-to-speech.h"
#include "backends/dialogs/macosx/macosx-dialogs.h"
#include "backends/platform/sdl/macosx/macosx_wrapper.h"
#include "backends/fs/posix/posix-fs.h"
#include "common/archive.h"
#include "common/config-manager.h"
#include "common/fs.h"
#include "common/translation.h"
#include <ApplicationServices/ApplicationServices.h> // for LSOpenFSRef
#include <CoreFoundation/CoreFoundation.h> // for CF* stuff
// For querying number of MIDI devices
#include <pthread.h>
#include <CoreMIDI/CoreMIDI.h>
void *coreMIDIthread(void *threadarg) {
(void)MIDIGetNumberOfDestinations();
pthread_exit(NULL);
return NULL;
}
OSystem_MacOSX::~OSystem_MacOSX() {
releaseMenu();
#if defined(USE_OSD)
macOSTouchbarDestroy();
#endif
}
void OSystem_MacOSX::init() {
initSDL();
_window = new SdlWindow_MacOSX();
#if defined(USE_TASKBAR)
// Initialize taskbar manager
_taskbarManager = new MacOSXTaskbarManager();
#endif
#if defined(USE_SYSDIALOGS)
// Initialize dialog manager
_dialogManager = new MacOSXDialogManager();
#endif
#if defined(USE_OSD)
macOSTouchbarCreate();
#endif
// The call to query the number of MIDI devices is ubiquitously slow
// on the first run. This is apparent when opening Options in GUI,
// which takes 2-3 secs.
//
// Thus, we are launching it now, in a separate thread, so
// the subsequent calls are instantaneous
pthread_t thread;
pthread_create(&thread, NULL, coreMIDIthread, NULL);
// Invoke parent implementation of this method
OSystem_POSIX::init();
}
void OSystem_MacOSX::initBackend() {
#ifdef USE_TRANSLATION
// We need to initialize the translation manager here for the following
// call to replaceApplicationMenuItems() work correctly
TransMan.setLanguage(ConfMan.get("gui_language").c_str());
#endif // USE_TRANSLATION
// Replace the SDL generated menu items with our own translated ones on macOS
replaceApplicationMenuItems();
#ifdef USE_SPARKLE
// Initialize updates manager
_updateManager = new MacOSXUpdateManager();
#endif
#ifdef USE_TTS
// Initialize Text to Speech manager
_textToSpeechManager = new MacOSXTextToSpeechManager();
#endif
// Migrate savepath.
// It used to be in ~/Documents/ScummVM Savegames/, but was changed to use the application support
// directory. To migrate old config files we use a flag to indicate if the config file was migrated.
// This allows detecting old config files. If the flag is not set we:
// 1. Set the flag
// 2. If the config file has no custom savepath and has some games, we set the savepath to the old default.
if (!ConfMan.hasKey("macos_savepath_migrated", Common::ConfigManager::kApplicationDomain)) {
if (!ConfMan.hasKey("savepath", Common::ConfigManager::kApplicationDomain) && !ConfMan.getGameDomains().empty()) {
ConfMan.set("savepath", getDocumentsPathMacOSX() + "/ScummVM Savegames", Common::ConfigManager::kApplicationDomain);
}
ConfMan.setBool("macos_savepath_migrated", true, Common::ConfigManager::kApplicationDomain);
ConfMan.flushToDisk();
}
// Invoke parent implementation of this method
OSystem_POSIX::initBackend();
}
#ifdef USE_OPENGL
OSystem_SDL::GraphicsManagerType OSystem_MacOSX::getDefaultGraphicsManager() const {
return GraphicsManagerOpenGL;
}
#endif
void OSystem_MacOSX::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
// Invoke parent implementation of this method
OSystem_POSIX::addSysArchivesToSearchSet(s, priority);
// Get URL of the Resource directory of the .app bundle
Common::Path bundlePath(getResourceAppBundlePathMacOSX(), Common::Path::kNativeSeparator);
if (!bundlePath.empty()) {
// Success: search with a depth of 2 so the shaders are found
s.add("__OSX_BUNDLE__", new Common::FSDirectory(bundlePath, 2), priority);
}
}
bool OSystem_MacOSX::hasFeature(Feature f) {
if (f == kFeatureDisplayLogFile || f == kFeatureClipboardSupport || f == kFeatureOpenUrl)
return true;
#ifdef USE_SYSDIALOGS
if (f == kFeatureSystemBrowserDialog)
return true;
#endif
return OSystem_POSIX::hasFeature(f);
}
bool OSystem_MacOSX::displayLogFile() {
// Use LaunchServices to open the log file, if possible.
if (_logFilePath.empty())
return false;
Common::String logFilePath(_logFilePath.toString(Common::Path::kNativeSeparator));
CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)logFilePath.c_str(), logFilePath.size(), false);
OSStatus err = LSOpenCFURLRef(url, NULL);
CFRelease(url);
return err != noErr;
}
bool OSystem_MacOSX::openUrl(const Common::String &url) {
CFURLRef urlRef = CFURLCreateWithBytes (NULL, (const UInt8*)url.c_str(), url.size(), kCFStringEncodingASCII, NULL);
OSStatus err = LSOpenCFURLRef(urlRef, NULL);
CFRelease(urlRef);
return err == noErr;
}
Common::String OSystem_MacOSX::getSystemLanguage() const {
#if defined(USE_DETECTLANG) && defined(USE_TRANSLATION)
CFArrayRef availableLocalizations = CFBundleCopyBundleLocalizations(CFBundleGetMainBundle());
if (availableLocalizations) {
CFArrayRef preferredLocalizations = CFBundleCopyPreferredLocalizationsFromArray(availableLocalizations);
CFRelease(availableLocalizations);
if (preferredLocalizations) {
CFIndex localizationsSize = CFArrayGetCount(preferredLocalizations);
// Since we have a list of sorted preferred localization, I would like here to
// check that they are supported by the TranslationManager and take the first
// one that is supported. The listed localizations are taken from the Bundle
// plist file, so they should all be supported, unless the plist file is not
// synchronized with the translations.dat file. So this is not really a big
// issue. And because getSystemLanguage() is called from the constructor of
// TranslationManager (therefore before the instance pointer is set), calling
// TransMan here results in an infinite loop and creation of a lot of TransMan
// instances.
/*
for (CFIndex i = 0 ; i < localizationsSize ; ++i) {
CFStringRef language = (CFStringRef)CFArrayGetValueAtIndex(preferredLocalizations, i);
char buffer[10];
CFStringGetCString(language, buffer, sizeof(buffer), kCFStringEncodingASCII);
int32 languageId = TransMan.findMatchingLanguage(buffer);
if (languageId != -1) {
CFRelease(preferredLocalizations);
return TransMan.getLangById(languageId);
}
}
*/
if (localizationsSize > 0) {
CFStringRef language = (CFStringRef)CFArrayGetValueAtIndex(preferredLocalizations, 0);
char buffer[10];
CFStringGetCString(language, buffer, sizeof(buffer), kCFStringEncodingASCII);
CFRelease(preferredLocalizations);
return buffer;
}
CFRelease(preferredLocalizations);
}
}
// Fallback to POSIX implementation
return OSystem_POSIX::getSystemLanguage();
#else // USE_DETECTLANG
return OSystem_POSIX::getSystemLanguage();
#endif // USE_DETECTLANG
}
Common::Path OSystem_MacOSX::getDefaultConfigFileName() {
const Common::String baseConfigName = "Library/Preferences/" + getMacBundleName() + " Preferences";
Common::Path configFile;
Common::String prefix = getenv("HOME");
if (!prefix.empty() && (prefix.size() + 1 + baseConfigName.size()) < MAXPATHLEN) {
configFile = prefix;
configFile.joinInPlace(baseConfigName);
} else {
configFile = baseConfigName;
}
return configFile;
}
Common::Path OSystem_MacOSX::getDefaultLogFileName() {
const char *prefix = getenv("HOME");
if (prefix == nullptr) {
return Common::Path();
}
if (!Posix::assureDirectoryExists("Library/Logs", prefix)) {
return Common::Path();
}
Common::String appName = getMacBundleName();
appName.toLowercase();
return Common::Path(prefix).join(Common::String("Library/Logs/") + appName + ".log");
}
Common::Path OSystem_MacOSX::getDefaultIconsPath() {
const Common::String defaultIconsPath = getAppSupportPathMacOSX() + "/Icons";
if (!Posix::assureDirectoryExists(defaultIconsPath)) {
return Common::Path();
}
return Common::Path(defaultIconsPath);
}
Common::Path OSystem_MacOSX::getDefaultDLCsPath() {
const Common::Path defaultDLCsPath(getAppSupportPathMacOSX() + "/DLCs");
if (!Posix::assureDirectoryExists(defaultDLCsPath.toString(Common::Path::kNativeSeparator))) {
return Common::Path();
}
return defaultDLCsPath;
}
Common::Path OSystem_MacOSX::getScreenshotsPath() {
// If the user has configured a screenshots path, use it
const Common::Path path = OSystem_SDL::getScreenshotsPath();
if (!path.empty())
return path;
Common::Path desktopPath(getDesktopPathMacOSX(), Common::Path::kNativeSeparator);
return desktopPath;
}
AudioCDManager *OSystem_MacOSX::createAudioCDManager() {
return createMacOSXAudioCDManager();
}
#endif

View File

@@ -0,0 +1,66 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_MACOSX_H
#define PLATFORM_SDL_MACOSX_H
#include "backends/platform/sdl/posix/posix.h"
class OSystem_MacOSX : public OSystem_POSIX {
public:
~OSystem_MacOSX();
bool hasFeature(Feature f) override;
bool displayLogFile() override;
bool hasTextInClipboard() override;
Common::U32String getTextFromClipboard() override;
bool setTextInClipboard(const Common::U32String &text) override;
bool openUrl(const Common::String &url) override;
Common::String getSystemLanguage() const override;
void init() override;
void initBackend() override;
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0) override;
void updateStartSettings(const Common::String &executable, Common::String &command, Common::StringMap &settings, Common::StringArray& additionalArgs) override;
#ifdef USE_OPENGL
GraphicsManagerType getDefaultGraphicsManager() const override;
#endif
// Default paths
Common::Path getDefaultIconsPath() override;
Common::Path getDefaultDLCsPath() override;
Common::Path getScreenshotsPath() override;
protected:
Common::Path getDefaultConfigFileName() override;
Common::Path getDefaultLogFileName() override;
// Override createAudioCDManager() to get our Mac-specific
// version.
AudioCDManager *createAudioCDManager() override;
};
#endif

View File

@@ -0,0 +1,187 @@
/* 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/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
// Needs to be included first as system headers redefine NO and YES, which clashes
// with the DisposeAfterUse::Flag enum used in Common stream classes.
#include "common/file.h"
#include "backends/platform/sdl/macosx/macosx.h"
#include "backends/platform/sdl/macosx/macosx-compat.h"
#include "base/version.h"
#include <Foundation/NSBundle.h>
#include <Foundation/NSData.h>
#include <Foundation/NSFileManager.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSPathUtilities.h>
#include <Foundation/NSUserDefaults.h>
#include <AppKit/NSPasteboard.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
#define NSPasteboardTypeString NSStringPboardType
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Cocoa64BitGuide/64BitChangesCocoa/64BitChangesCocoa.html
#if __LP64__ || NS_BUILD_32_LIKE_64
typedef unsigned long NSUInteger;
#else
typedef unsigned int NSUInteger;
#endif
// Those are not defined in the 10.4 SDK, but they are defined when targeting
// Mac OS X 10.4 or above in the 10.5 SDK, and they do work with 10.4.
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
enum {
NSUTF32StringEncoding = 0x8c000100,
NSUTF32BigEndianStringEncoding = 0x98000100,
NSUTF32LittleEndianStringEncoding = 0x9c000100
};
#endif
#endif
void OSystem_MacOSX::updateStartSettings(const Common::String & executable, Common::String &command, Common::StringMap &settings, Common::StringArray& additionalArgs) {
NSBundle* bundle = [NSBundle mainBundle];
// Check if scummvm is running from an app bundle
if (!bundle || ![bundle bundleIdentifier]) {
// Use default autostart implementation
OSystem_POSIX::updateStartSettings(executable, command, settings, additionalArgs);
return;
}
// If the bundle contains a scummvm.ini, use it as initial config
NSString *iniPath = [bundle pathForResource:@"scummvm" ofType:@"ini"];
if (iniPath && !settings.contains("initial-cfg"))
settings["initial-cfg"] = Common::String([iniPath fileSystemRepresentation]);
// If a command was specified on the command line, do not override it
if (!command.empty())
return;
// Check if we have an autorun file with additional arguments
NSString *autorunPath = [bundle pathForResource:@"scummvm-autorun" ofType:nil];
if (autorunPath) {
Common::File autorun;
Common::String line;
if (autorun.open(Common::FSNode([autorunPath fileSystemRepresentation]))) {
while (!autorun.eos()) {
line = autorun.readLine();
if (!line.empty() && line[0] != '#')
additionalArgs.push_back(line);
}
}
autorun.close();
}
// If the bundle contains a game directory, auto-detect it
NSString *gamePath = [[bundle resourcePath] stringByAppendingPathComponent:@"game"];
BOOL isDir = false;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:gamePath isDirectory:&isDir];
if (exists && isDir) {
// Use auto-detection
command = "auto-detect";
settings["path"] = [gamePath fileSystemRepresentation];
return;
}
// The rest of the function has some commands executed only the first time after each version change
// Check the last version stored in the user settings.
NSString *versionString = [NSString stringWithUTF8String:gScummVMFullVersion];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *lastVersion = [defaults stringForKey:@"lastVersion"];
if (lastVersion && [lastVersion isEqualToString:versionString])
return;
[defaults setObject:versionString forKey:@"lastVersion"];
// If the bundle contains a games directory, add them to the launcher
NSString *gamesPath = [[bundle resourcePath] stringByAppendingPathComponent:@"games"];
isDir = false;
exists = [[NSFileManager defaultManager] fileExistsAtPath:gamesPath isDirectory:&isDir];
if (exists && isDir) {
// Detect and add games
command = "add";
settings["path"] = [gamesPath fileSystemRepresentation];
settings["recursive"] = "true";
settings["exit"] = "false";
return;
}
}
bool OSystem_MacOSX::hasTextInClipboard() {
return [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObject:NSPasteboardTypeString]] != nil;
}
Common::U32String OSystem_MacOSX::getTextFromClipboard() {
if (!hasTextInClipboard())
return Common::U32String();
NSPasteboard *pb = [NSPasteboard generalPasteboard];
NSString *str = [pb stringForType:NSPasteboardTypeString];
if (str == nil)
return Common::U32String();
// If translations are supported, use the current TranslationManager charset and otherwise
// use ASCII. If the string cannot be represented using the requested encoding we get a null
// pointer below, which is fine as ScummVM would not know what to do with the string anyway.
#ifdef SCUMM_LITTLE_ENDIAN
NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
#else
NSStringEncoding stringEncoding = NSUTF32BigEndianStringEncoding;
#endif
NSData *data = [str dataUsingEncoding:stringEncoding];
if (data == nil)
return Common::U32String();
NSUInteger byteLength = [data length];
if (byteLength % 4 != 0)
return Common::U32String();
NSUInteger textLength = byteLength / 4;
Common::u32char_type_t *text = new Common::u32char_type_t[textLength];
// note: Using the `-getBytes:...:remainingRange:` API would make this code
// a bit simpler, but it's missing from the 10.4 SDK headers (although the
// Foundation framework seems to contain some hidden symbol for it...)
[data getBytes:text length:byteLength];
Common::U32String u32String(text, textLength);
delete[] text;
return u32String;
}
bool OSystem_MacOSX::setTextInClipboard(const Common::U32String &text) {
NSPasteboard *pb = [NSPasteboard generalPasteboard];
[pb declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil];
#ifdef SCUMM_LITTLE_ENDIAN
NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
#else
NSStringEncoding stringEncoding = NSUTF32BigEndianStringEncoding;
#endif
NSString *nsstring = [[NSString alloc] initWithBytes:text.c_str() length:4*text.size() encoding: stringEncoding];
bool status = [pb setString:nsstring forType:NSPasteboardTypeString];
[nsstring release];
return status;
}

View File

@@ -0,0 +1,33 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_MACOSX_WRAPPER_H
#define PLATFORM_SDL_MACOSX_WRAPPER_H
#include "common/str.h"
Common::String getDesktopPathMacOSX();
Common::String getDocumentsPathMacOSX();
Common::String getResourceAppBundlePathMacOSX();
Common::String getAppSupportPathMacOSX();
Common::String getMacBundleName();
#endif

View File

@@ -0,0 +1,84 @@
/* 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/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/platform/sdl/macosx/macosx_wrapper.h"
#include "backends/platform/sdl/macosx/macosx-compat.h"
#include <Foundation/NSArray.h>
#include <Foundation/NSBundle.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSPathUtilities.h>
#include <AvailabilityMacros.h>
#include <CoreFoundation/CFString.h>
#include <CoreFoundation/CFBundle.h>
Common::String getDesktopPathMacOSX() {
// The recommended method is to use NSFileManager.
// NSUrl *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDesktopDirectory inDomains:NSUserDomainMask] firstObject];
// However it is only available in OS X 10.6+. So use NSSearchPathForDirectoriesInDomains instead (available since OS X 10.0)
// [NSArray firstObject] is also only available in OS X 10.6+. So we need to use [NSArray count] and [NSArray objectAtIndex:]
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES);
if ([paths count] == 0)
return Common::String();
NSString *path = [paths objectAtIndex:0];
if (path == nil)
return Common::String();
return Common::String([path fileSystemRepresentation]);
}
Common::String getDocumentsPathMacOSX() {
// See comment in getDesktopPathMacOSX()
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if ([paths count] == 0)
return Common::String();
NSString *path = [paths objectAtIndex:0];
if (path == nil)
return Common::String();
return Common::String([path fileSystemRepresentation]);
}
Common::String getResourceAppBundlePathMacOSX() {
NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
if (bundlePath == nil)
return Common::String();
return Common::String([bundlePath fileSystemRepresentation]);
}
Common::String getAppSupportPathMacOSX() {
// See comments in getDesktopPathMacOSX() as we use the same methods
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
if ([paths count] == 0)
return Common::String();
NSString *path = [paths objectAtIndex:0];
if (path == nil)
return Common::String();
return Common::String([path fileSystemRepresentation]) + "/ScummVM";
}
Common::String getMacBundleName() {
NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(id)kCFBundleNameKey];
if (!appName)
return Common::String("ScummVM");
return Common::String([appName UTF8String]);
}

View File

@@ -0,0 +1,23 @@
[ScummVM-Miyoo README]
Controls
========
Dpad - Mouse
Dpad+R - Slow Mouse
A - Left mouse click
B - Right mouse click
Y - Escape
L - Game Menu (F5)
Start - Global Menu
Select - Virtual Keyboard
All buttons are available for (re)mapping in keymapper
Troubleshooting
===============
In case you need to submit a bugreport, you may find the log file at the
following path:
SDCARD/.scummvm/scummvm.log
The log file is being overwritten at every ScummVM run.

View File

@@ -0,0 +1,13 @@
#!/bin/bash
set -e
TOOLCHAIN=/opt/miyoo
SYSROOT=$TOOLCHAIN/arm-miyoo-linux-uclibcgnueabi
export PATH=$TOOLCHAIN/usr/bin:$SYSROOT/usr/include:$TOOLCHAIN/bin:$PATH
export CXX=arm-linux-g++
./configure --host=miyoo --enable-release --disable-detection-full --enable-plugins --default-dynamic --enable-engine=testbed
make -j5 all sd-root sd-zip

View File

@@ -0,0 +1,13 @@
#!/bin/bash
set -e
TOOLCHAIN=/opt/miyoo-musl
SYSROOT=$TOOLCHAIN/arm-miyoo-linux-musleabi
export PATH=$TOOLCHAIN/usr/bin:$SYSROOT/usr/include:$TOOLCHAIN/bin:$PATH
export CXX=arm-linux-g++
./configure --host=miyoo --enable-release --disable-detection-full --enable-plugins --default-dynamic --enable-engine=testbed
make -j5 all sd-root sd-zip

View File

@@ -0,0 +1,13 @@
#!/bin/bash
set -e
TOOLCHAIN=/opt/miyoomini-toolchain
SYSROOT=$TOOLCHAIN/arm-linux-gnueabihf
export PATH=$TOOLCHAIN/usr/bin:$SYSROOT/usr/include:$TOOLCHAIN/bin:$PATH
export CXX=arm-linux-gnueabihf-g++
./configure --host=miyoomini --enable-release --enable-plugins --default-dynamic --enable-engine=testbed --enable-ext-neon --with-freetype2-prefix=/opt/miyoomini-toolchain/arm-linux-gnueabihf/libc/usr/bin/
make -j5 all sd-root sd-zip

View File

@@ -0,0 +1,45 @@
/* 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 "backends/platform/sdl/miyoo/miyoo.h"
#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
int main(int argc, char* argv[]) {
g_system = new OSystem_SDL_Miyoo();
assert(g_system);
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
return res;
}

View File

@@ -0,0 +1,240 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_system
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/translation.h"
#ifdef MIYOOMINI
#include "backends/graphics/miyoo/miyoomini-graphics.h"
#endif
#include "backends/platform/sdl/miyoo/miyoo.h"
#include "backends/fs/posix/posix-fs-factory.h"
#include "backends/fs/posix/posix-fs.h"
#include "backends/saves/default/default-saves.h"
#include "backends/keymapper/action.h"
#include "backends/keymapper/keymapper-defaults.h"
#include "backends/keymapper/hardware-input.h"
#include "backends/keymapper/keymap.h"
#include "backends/keymapper/keymapper.h"
#ifdef MIYOOMINI
#define SCUMM_DIR "/mnt/SDCARD/.scummvm"
#define CONFIG_FILE "/mnt/SDCARD/.scummvmrc"
#define SAVE_PATH "/mnt/SDCARD/.scummvm/saves"
#define LOG_FILE "/mnt/SDCARD/.scummvm/scummvm.log"
#else
#define SCUMM_DIR "/mnt/.scummvm"
#define CONFIG_FILE "/mnt/.scummvmrc"
#define SAVE_PATH "/mnt/.scummvm/saves"
#define LOG_FILE "/mnt/.scummvm/scummvm.log"
#endif
#define JOYSTICK_DIR "/sys/devices/platform/joystick"
static const Common::KeyTableEntry odKeyboardButtons[] = {
#ifdef MIYOOMINI
// I18N: Hardware key
{ "JOY_A", Common::KEYCODE_SPACE, _s("A") },
// I18N: Hardware key
{ "JOY_B", Common::KEYCODE_LCTRL, _s("B") },
// I18N: Hardware key
{ "JOY_X", Common::KEYCODE_LSHIFT, _s("X") },
// I18N: Hardware key
{ "JOY_Y", Common::KEYCODE_LALT, _s("Y") },
// I18N: Hardware key
{ "JOY_BACK", Common::KEYCODE_RCTRL, _s("Select") },
// I18N: Hardware key
{ "JOY_START", Common::KEYCODE_RETURN, _s("Start") },
// I18N: Hardware key
{ "JOY_LEFT_SHOULDER", Common::KEYCODE_e, _s("L") },
// I18N: Hardware key
{ "JOY_RIGHT_SHOULDER", Common::KEYCODE_t, _s("R") },
{ "JOY_UP", Common::KEYCODE_UP, _s("D-pad Up") },
{ "JOY_DOWN", Common::KEYCODE_DOWN, _s("D-pad Down") },
{ "JOY_LEFT", Common::KEYCODE_LEFT, _s("D-pad Left") },
{ "JOY_RIGHT", Common::KEYCODE_RIGHT, _s("D-pad Right") },
// I18N: Hardware key
{ "JOY_LEFT_STICK", Common::KEYCODE_TAB, _s("L2") },
// I18N: Hardware key
{ "JOY_RIGHT_STICK", Common::KEYCODE_BACKSPACE, _s("R2") },
// I18N: Hardware key
{ "JOY_GUIDE", Common::KEYCODE_ESCAPE, _s("Menu") },
#else
// I18N: Hardware key
{ "JOY_A", Common::KEYCODE_LALT, _s("A") },
// I18N: Hardware key
{ "JOY_B", Common::KEYCODE_LCTRL, _s("B") },
// I18N: Hardware key
{ "JOY_X", Common::KEYCODE_LSHIFT, _s("X") },
// I18N: Hardware key
{ "JOY_Y", Common::KEYCODE_SPACE, _s("Y") },
// I18N: Hardware key
{ "JOY_BACK", Common::KEYCODE_ESCAPE, _s("Select") },
// I18N: Hardware key
{ "JOY_START", Common::KEYCODE_RETURN, _s("Start") },
// I18N: Hardware key
{ "JOY_LEFT_SHOULDER", Common::KEYCODE_TAB, _s("L") },
// I18N: Hardware key
{ "JOY_RIGHT_SHOULDER", Common::KEYCODE_BACKSPACE, _s("R") },
{ "JOY_UP", Common::KEYCODE_UP, _s("D-pad Up") },
{ "JOY_DOWN", Common::KEYCODE_DOWN, _s("D-pad Down") },
{ "JOY_LEFT", Common::KEYCODE_LEFT, _s("D-pad Left") },
{ "JOY_RIGHT", Common::KEYCODE_RIGHT, _s("D-pad Right") },
// I18N: Hardware key
{ "JOY_LEFT_STICK", Common::KEYCODE_PAGEUP, _s("L2") },
// I18N: Hardware key
{ "JOY_RIGHT_STICK", Common::KEYCODE_PAGEDOWN, _s("R2") },
// I18N: Hardware key
{ "JOY_LEFT_TRIGGER", Common::KEYCODE_RALT, _s("L3") },
// I18N: Hardware key
{ "JOY_RIGHT_TRIGGER", Common::KEYCODE_RSHIFT, _s("R3") },
// I18N: Hardware key
{ "JOY_GUIDE", Common::KEYCODE_RCTRL, _s("Menu") },
#endif
{nullptr, Common::KEYCODE_INVALID, nullptr }
};
Common::KeymapperDefaultBindings *OSystem_SDL_Miyoo::getKeymapperDefaultBindings() {
Common::KeymapperDefaultBindings *keymapperDefaultBindings = new Common::KeymapperDefaultBindings();
if (!Posix::assureDirectoryExists(JOYSTICK_DIR)) {
keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "VMOUSEUP", "JOY_UP");
keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "VMOUSEDOWN", "JOY_DOWN");
keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "VMOUSELEFT", "JOY_LEFT");
keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "VMOUSERIGHT", "JOY_RIGHT");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "UP", "");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "DOWN", "");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "LEFT", "");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "RIGHT", "");
keymapperDefaultBindings->setDefaultBinding("engine-default", "UP", "");
keymapperDefaultBindings->setDefaultBinding("engine-default", "DOWN", "");
keymapperDefaultBindings->setDefaultBinding("engine-default", "LEFT", "");
keymapperDefaultBindings->setDefaultBinding("engine-default", "RIGHT", "");
}
return keymapperDefaultBindings;
}
void OSystem_SDL_Miyoo::init() {
_fsFactory = new POSIXFilesystemFactory();
if (!Posix::assureDirectoryExists(SCUMM_DIR)) {
system("mkdir " SCUMM_DIR);
}
// Invoke parent implementation of this method
OSystem_SDL::init();
}
void OSystem_SDL_Miyoo::initBackend() {
ConfMan.registerDefault("fullscreen", true);
ConfMan.registerDefault("aspect_ratio", true);
ConfMan.registerDefault("themepath", Common::Path("./themes"));
ConfMan.registerDefault("extrapath", Common::Path("./engine-data"));
ConfMan.registerDefault("gui_theme", "builtin");
ConfMan.registerDefault("scale_factor", "1");
ConfMan.setBool("fullscreen", true);
ConfMan.setInt("joystick_num", 0);
if (!ConfMan.hasKey("aspect_ratio")) {
ConfMan.setBool("aspect_ratio", true);
}
if (!ConfMan.hasKey("themepath")) {
ConfMan.setPath("themepath", "./themes");
}
if (!ConfMan.hasKey("extrapath")) {
ConfMan.setPath("extrapath", "./engine-data");
}
if (!ConfMan.hasKey("savepath")) {
ConfMan.setPath("savepath", SAVE_PATH);
}
if (!ConfMan.hasKey("gui_theme")) {
ConfMan.set("gui_theme", "builtin");
}
if (!ConfMan.hasKey("scale_factor")) {
ConfMan.set("scale_factor", "1");
}
if (!ConfMan.hasKey("opl_driver")) {
ConfMan.set("opl_driver", "db");
}
if (!ConfMan.hasKey("kbdmouse_speed")) {
ConfMan.setInt("kbdmouse_speed", 2);
}
// Create the savefile manager
if (_savefileManager == nullptr) {
_savefileManager = new DefaultSaveFileManager(SAVE_PATH);
}
#ifdef MIYOOMINI
if (!_eventSource)
_eventSource = new SdlEventSource();
if (!_graphicsManager)
_graphicsManager = new MiyooMiniGraphicsManager(_eventSource, _window);
#endif
OSystem_SDL::initBackend();
}
Common::Path OSystem_SDL_Miyoo::getDefaultConfigFileName() {
return CONFIG_FILE;
}
Common::Path OSystem_SDL_Miyoo::getDefaultLogFileName() {
return LOG_FILE;
}
bool OSystem_SDL_Miyoo::hasFeature(Feature f) {
switch (f) {
case kFeatureFullscreenMode:
case kFeatureAspectRatioCorrection:
return false;
case kFeatureKbdMouseSpeed:
return true;
default:
return OSystem_SDL::hasFeature(f);
}
}
void OSystem_SDL_Miyoo::setFeatureState(Feature f, bool enable) {
OSystem_SDL::setFeatureState(f, enable);
}
bool OSystem_SDL_Miyoo::getFeatureState(Feature f) {
return OSystem_SDL::getFeatureState(f);
}
Common::HardwareInputSet *OSystem_SDL_Miyoo::getHardwareInputSet() {
using namespace Common;
CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
// Users may use USB mice - keyboards currently not possible with SDL1 as it conflicts with gpios
inputSet->addHardwareInputSet(new MouseHardwareInputSet(defaultMouseButtons));
inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(odKeyboardButtons, defaultModifiers));
return inputSet;
}

View File

@@ -0,0 +1,42 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_MIYOO_H
#define PLATFORM_SDL_MIYOO_H
#include "backends/platform/sdl/sdl.h"
class OSystem_SDL_Miyoo : public OSystem_SDL {
public:
void init() override;
void initBackend() override;
bool hasFeature(Feature f) override;
void setFeatureState(Feature f, bool enable) override;
bool getFeatureState(Feature f) override;
Common::HardwareInputSet *getHardwareInputSet() override;
Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() override;
protected:
Common::Path getDefaultConfigFileName() override;
Common::Path getDefaultLogFileName() override;
};
#endif

View File

@@ -0,0 +1,64 @@
OD_EXE_STRIPPED := scummvm_stripped$(EXEEXT)
bundle = sd-root
ifeq ($(MIYOO_TARGET), miyoomini)
G2X_CATEGORY = App
else
G2X_CATEGORY = games
endif
all: $(OD_EXE_STRIPPED)
$(OD_EXE_STRIPPED): $(EXECUTABLE)
$(STRIP) $< -o $@
$(bundle): all
$(RM) -rf $(bundle)
$(MKDIR) -p $(bundle)/$(G2X_CATEGORY)/scummvm
$(CP) $(DIST_FILES_DOCS) $(bundle)/$(G2X_CATEGORY)/scummvm
$(MKDIR) $(bundle)/$(G2X_CATEGORY)/scummvm/themes
$(CP) $(DIST_FILES_THEMES) $(bundle)/$(G2X_CATEGORY)/scummvm/themes/
ifdef DIST_FILES_ENGINEDATA
$(MKDIR) $(bundle)/$(G2X_CATEGORY)/scummvm/engine-data
$(CP) $(DIST_FILES_ENGINEDATA) $(bundle)/$(G2X_CATEGORY)/scummvm/engine-data/
endif
ifdef DIST_FILES_NETWORKING
$(CP) $(DIST_FILES_NETWORKING) $(bundle)/$(G2X_CATEGORY)/scummvm
endif
ifdef DIST_FILES_VKEYBD
$(CP) $(DIST_FILES_VKEYBD) $(bundle)/$(G2X_CATEGORY)/scummvm
endif
ifdef DYNAMIC_MODULES
$(MKDIR) $(bundle)/$(G2X_CATEGORY)/scummvm/plugins/
$(CP) $(PLUGINS) $(bundle)/$(G2X_CATEGORY)/scummvm/plugins/
endif
$(CP) $(EXECUTABLE) $(bundle)/$(G2X_CATEGORY)/scummvm/scummvm
ifeq ($(MIYOO_TARGET), miyoomini)
$(CP) $(srcdir)/dists/miyoo/scummvm-miyoomini.png $(bundle)/$(G2X_CATEGORY)/scummvm/scummvm.png
endif
$(CP) $(srcdir)/backends/platform/sdl/miyoo/README.MIYOO $(bundle)/$(G2X_CATEGORY)/scummvm/README.man.txt
echo >> $(bundle)/$(G2X_CATEGORY)/scummvm/README.man.txt
echo '[General README]' >> $(bundle)/$(G2X_CATEGORY)/scummvm/README.man.txt
echo >> $(bundle)/$(G2X_CATEGORY)/scummvm/README.man.txt
cat $(srcdir)/README.md | sed -e 's/\[/⟦/g' -e 's/\]/⟧/g' -e '/^1\.1)/,$$ s/^[0-9][0-9]*\.[0-9][0-9]*.*/\[&\]/' >> $(bundle)/$(G2X_CATEGORY)/scummvm/README.man.txt
echo '[General README]' >> $(bundle)/$(G2X_CATEGORY)/scummvm/README.man.txt
ifeq ($(MIYOO_TARGET), miyoomini)
$(CP) $(srcdir)/dists/miyoo/launch.miyoomini.sh $(bundle)/$(G2X_CATEGORY)/scummvm/launch.sh
$(CP) $(srcdir)/dists/miyoo/config.miyoomini.json $(bundle)/$(G2X_CATEGORY)/scummvm/config.json
# Workaround for mismatch between SDK and actual device
$(CP) /opt/miyoomini-toolchain/arm-linux-gnueabihf/libc/usr/lib/libpng16.so.16.* $(bundle)/$(G2X_CATEGORY)/scummvm/libpng16.so.16
$(CP) /opt/miyoomini-toolchain/arm-linux-gnueabihf/libc/usr/lib/libz.so.1.2.11 $(bundle)/$(G2X_CATEGORY)/scummvm/libz.so.1
else
$(MKDIR) -p $(bundle)/gmenu2x/sections/$(G2X_CATEGORY)
$(CP) $(srcdir)/dists/miyoo/scummvm.miyoo $(bundle)/gmenu2x/sections/$(G2X_CATEGORY)/scummvm
endif
$(STRIP) $(bundle)/$(G2X_CATEGORY)/scummvm/scummvm
sd-zip: $(bundle)
$(RM) scummvm_$(MIYOO_TARGET).zip
ifeq ($(MIYOO_TARGET), miyoomini)
cd $(bundle) && zip -r ../scummvm_$(MIYOO_TARGET).zip $(G2X_CATEGORY)
else
cd $(bundle) && zip -r ../scummvm_$(MIYOO_TARGET).zip $(G2X_CATEGORY) gmenu2x
endif

View File

@@ -0,0 +1,104 @@
MODULE := backends/platform/sdl
MODULE_OBJS := \
sdl.o \
sdl-window.o
ifdef KOLIBRIOS
MODULE_OBJS += \
kolibrios/kolibrios-main.o \
kolibrios/kolibrios.o
endif
ifdef POSIX
MODULE_OBJS += \
posix/posix-main.o \
posix/posix.o
endif
ifdef MACOSX
MODULE_OBJS += \
macosx/macosx-main.o \
macosx/macosx.o \
macosx/macosx-touchbar.o \
macosx/macosx-window.o \
macosx/macosx_wrapper.o \
macosx/macosx_osys_misc.o \
macosx/appmenu_osx.o
endif
ifdef WIN32
MODULE_OBJS += \
win32/win32-main.o \
win32/win32-window.o \
win32/win32_wrapper.o \
win32/win32.o
endif
ifdef AMIGAOS
MODULE_OBJS += \
amigaos/amigaos-main.o \
amigaos/amigaos.o
endif
ifdef RISCOS
MODULE_OBJS += \
riscos/riscos-main.o \
riscos/riscos-utils.o \
riscos/riscos.o
endif
ifdef MIYOO
MODULE_OBJS += \
miyoo/miyoo-main.o \
miyoo/miyoo.o
endif
ifdef MORPHOS
MODULE_OBJS += \
morphos/morphos-main.o \
morphos/morphos.o
endif
ifdef OPENDINGUX
MODULE_OBJS += \
opendingux/opendingux-main.o \
opendingux/opendingux.o
endif
ifdef PLAYSTATION3
MODULE_OBJS += \
ps3/ps3-main.o \
ps3/ps3.o
endif
ifdef PSP2
CC=arm-vita-eabi-gcc
MODULE_OBJS += \
psp2/psp2-main.o \
psp2/psp2.o
endif
ifdef SAILFISH
MODULE_OBJS += \
sailfish/sailfish-main.o \
sailfish/sailfish-window.o \
sailfish/sailfish.o
endif
ifdef SWITCH
MODULE_OBJS += \
switch/switch-main.o \
switch/switch.o
endif
ifdef EMSCRIPTEN
MODULE_OBJS += \
emscripten/emscripten-main.o \
emscripten/emscripten.o
endif
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
OBJS := $(MODULE_OBJS) $(OBJS)
MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))

View File

@@ -0,0 +1,56 @@
/* 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/scummsys.h"
#if defined(__MORPHOS__)
#include "backends/fs/morphos/morphos-fs.h"
#include "backends/platform/sdl/morphos/morphos.h"
#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
int main(int argc, char *argv[]) {
// Set a stack cookie to avoid crashes from a too low stack.
static const char *stack_cookie __attribute__((used)) = "$STACK: 4096000";
// Create our OSystem instance.
g_system = new OSystem_MorphOS();
assert(g_system);
// Pre-initialize the backend.
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point.
int res = scummvm_main(argc, argv);
// Free OSystem.
g_system->destroy();
return res;
}
#endif

View File

@@ -0,0 +1,96 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
#include "common/scummsys.h"
#ifdef __MORPHOS__
#include "backends/platform/sdl/morphos/morphos.h"
#include "backends/fs/morphos/morphos-fs-factory.h"
#include "backends/dialogs/morphos/morphos-dialogs.h"
static bool cleanupDone = false;
static void cleanup() {
if (!cleanupDone)
g_system->destroy();
}
OSystem_MorphOS::~OSystem_MorphOS() {
cleanupDone = true;
}
void OSystem_MorphOS::init() {
// Register cleanup function to avoid unfreed signals
if (atexit(cleanup))
warning("Failed to register cleanup function via atexit()");
// Initialze File System Factory
_fsFactory = new MorphOSFilesystemFactory();
// Invoke parent implementation of this method
OSystem_SDL::init();
#if defined(USE_SYSDIALOGS)
_dialogManager = new MorphosDialogManager();
#endif
}
bool OSystem_MorphOS::hasFeature(Feature f) {
#if defined(USE_SYSDIALOGS)
if (f == kFeatureSystemBrowserDialog)
return true;
#endif
return OSystem_SDL::hasFeature(f);
}
void OSystem_MorphOS::initBackend() {
// First time user defaults
ConfMan.registerDefault("audio_buffer_size", "2048");
ConfMan.registerDefault("extrapath", Common::Path("PROGDIR:extras/"));
ConfMan.registerDefault("savepath", Common::Path("PROGDIR:saves/"));
ConfMan.registerDefault("themepath", Common::Path("PROGDIR:themes/"));
// First time .ini defaults
if (!ConfMan.hasKey("audio_buffer_size")) {
ConfMan.set("audio_buffer_size", "2048");
}
if (!ConfMan.hasKey("extrapath")) {
ConfMan.setPath("extrapath", "PROGDIR:extras/");
}
if (!ConfMan.hasKey("savepath")) {
ConfMan.setPath("savepath", "PROGDIR:saves/");
}
if (!ConfMan.hasKey("themepath")) {
ConfMan.setPath("themepath", "PROGDIR:themes/");
}
OSystem_SDL::initBackend();
}
void OSystem_MorphOS::logMessage(LogMessageType::Type type, const char * message) {
#ifdef DEBUG_BUILD
printf("%s\n", message);
#endif
}
#endif

View File

@@ -0,0 +1,41 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_MORPHOS_H
#define PLATFORM_SDL_MORPHOS_H
#include "backends/platform/sdl/sdl.h"
#include "backends/base-backend.h"
class OSystem_MorphOS : public OSystem_SDL {
public:
OSystem_MorphOS() {}
virtual ~OSystem_MorphOS();
bool hasFeature(Feature f) override;
void init() override;
void initBackend() override;
void logMessage(LogMessageType::Type type, const char *message) override;
};
#endif

View File

@@ -0,0 +1,25 @@
# Special target to create an MorphOS snapshot installation.
# MorphOS shell doesn't like indented comments.
morphosdist: $(EXECUTABLE) $(PLUGINS)
mkdir -p $(MORPHOSPATH)extras
cp ${srcdir}/dists/amiga/scummvm.info $(MORPHOSPATH)/$(EXECUTABLE).info
ifdef DIST_FILES_DOCS
mkdir -p $(MORPHOSPATH)/doc
cp $(DIST_FILES_DOCS) $(MORPHOSPATH)doc/
$(foreach lang, $(DIST_FILES_DOCS_languages), makedir all $(MORPHOSPATH)/doc/$(lang); cp $(DIST_FILES_DOCS_$(lang)) $(MORPHOSPATH)/doc/$(lang);)
endif
ifdef DIST_FILES_ENGINEDATA
cp $(DIST_FILES_ENGINEDATA) $(MORPHOSPATH)extras/
endif
ifdef DIST_FILES_NETWORKING
cp $(DIST_FILES_NETWORKING) $(MORPHOSPATH)extras/
endif
ifdef DIST_FILES_VKEYBD
cp $(DIST_FILES_VKEYBD) $(MORPHOSPATH)extras/
endif
ifdef DIST_FILES_THEMES
mkdir -p $(MORPHOSPATH)themes
cp $(DIST_FILES_THEMES) $(MORPHOSPATH)themes/
endif
# Strip
$(STRIP) $(EXECUTABLE) -o $(MORPHOSPATH)$(EXECUTABLE)

View File

@@ -0,0 +1,50 @@
Build instructions
==================
Running Linux on an x86/amd64 machine:
1. Download and install the desired toolchain (https://github.com/OpenDingux/buildroot/releases) in /opt/
For example, for gcw0:
curl -L https://github.com/OpenDingux/buildroot/releases/download/od-2022.09.22/opendingux-gcw0-toolchain.2022-09-22.tar.xz -o gcw0-toolchain.tar.xz && \
sudo mkdir -p /opt/gcw0-toolchain && sudo chown -R "${USER}:" /opt/gcw0-toolchain && \
tar -C /opt -xf gcw0-toolchain.tar.xz && \
cd /opt/gcw0-toolchain && \
./relocate-sdk.sh
2. git clone the ScummVM repository
3. Run 'backends/platform/sdl/opendingux/build_odbeta.sh x'
where x=gcw0|lepus|rs90
the rs90 build applies to the rg99
Or if you want a dual opk with one launcher capable of starting games directly
for e.g. simplemenu integration :
'backends/platform/sdl/opendingux/build_odbeta.sh x dualopk'
4. Copy the resulting file scummvm_$(target).opk or scummvm_$(target)_dual.opk to your device
Game Auto-Detection (dualopk only)
==================================
1) add a blank text file 'detect.svm' alongside your individual game folders, for example:
---------------
| - roms/scummvm/
| - detect.svm
| - Game Folder/
| - game files
------------------
2) load ScummVM, navigate to and select 'detect.svm'
- the loading screen will show while the script runs
- this may take longer if you have many games
- .svm files will be generated for each of your games
3) load one of the .svm files to start your game directly
Troubleshooting
===============
In case you need to submit a bugreport, you may find the log file at the
following path:
~/.scummvm/scummvm.log
The log file is being overwritten at every ScummVM run.

View File

@@ -0,0 +1,39 @@
[ScummVM-Opendingux README]
Controls
========
Left Stick - Mouse
Left Stick+R - Slow Mouse
A - Left mouse click
B - Right mouse click
Y - Escape
L - Game Menu (F5)
Start - Global Menu
Select - Virtual Keyboard
Dpad - Keypad Cursor Keys
On devices that have no stick, d-pad is mouse, cursor keys are not binded
Game Auto-Detection (dualopk only)
==================================
1) add a blank text file 'detect.svm' alongside your individual game folders, for example:
---------------
| - roms/scummvm/
| - detect.svm
| - Game Folder/
| - game files
------------------
2) load ScummVM, navigate to and select 'detect.svm'
- the loading screen will show while the script runs
- this may take longer if you have many games
- .svm files will be generated for each of your games
3) load one of the .svm files to start your game directly
Troubleshooting
===============
In case you need to submit a bugreport, you may find the log file at the
following path:
~/.scummvm/scummvm.log
The log file is being overwritten at every ScummVM run.

View File

@@ -0,0 +1,38 @@
#!/bin/bash
set -e
target=$1
if [ "$2" = "dualopk" ]; then
dualopk="dualopk=yes"
else
dualopk=
fi
case $target in
gcw0)
libc=uclibc
;;
lepus | rs90)
libc=musl
;;
*)
echo "please provide a valid target for the build: gcw0, lepus or rs90"
exit 1
;;
esac
TOOLCHAIN=/opt/$target-toolchain
SYSROOT=$TOOLCHAIN/mipsel-$target-linux-$libc
export PATH=$TOOLCHAIN/usr/bin:$SYSROOT/usr/include:$TOOLCHAIN/bin:$PATH
export CXX=mipsel-linux-g++
./configure --host=opendingux-$target --enable-release --disable-detection-full --default-dynamic --enable-plugins
make -j12 od-make-opk $dualopk
ls -lh scummvm_$target*.opk

View File

@@ -0,0 +1,44 @@
/* 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 "backends/platform/sdl/opendingux/opendingux.h"
#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
int main(int argc, char* argv[]) {
g_system = new OSystem_SDL_Opendingux();
assert(g_system);
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
return res;
}

View File

@@ -0,0 +1,217 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_system
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/translation.h"
#include "backends/graphics/opendingux/opendingux-graphics.h"
#include "backends/platform/sdl/opendingux/opendingux.h"
#include "backends/fs/posix/posix-fs-factory.h"
#include "backends/fs/posix/posix-fs.h"
#include "backends/saves/default/default-saves.h"
#include "backends/keymapper/action.h"
#include "backends/keymapper/keymapper-defaults.h"
#include "backends/keymapper/hardware-input.h"
#include "backends/keymapper/keymap.h"
#include "backends/keymapper/keymapper.h"
#define SCUMM_DIR "~/.scummvm"
#define CONFIG_FILE "~/.scummvmrc"
#define SAVE_PATH "~/.scummvm/saves"
#define LOG_FILE "~/.scummvm/scummvm.log"
#define JOYSTICK_DIR "/sys/devices/platform/joystick"
static const Common::KeyTableEntry odKeyboardButtons[] = {
// I18N: Hardware key
{ "JOY_A", Common::KEYCODE_LCTRL, _s("A") },
// I18N: Hardware key
{ "JOY_B", Common::KEYCODE_LALT, _s("B") },
// I18N: Hardware key
{ "JOY_X", Common::KEYCODE_SPACE, _s("X") },
// I18N: Hardware key
{ "JOY_Y", Common::KEYCODE_LSHIFT, _s("Y") },
// I18N: Hardware key
{ "JOY_BACK", Common::KEYCODE_ESCAPE, _s("Select") },
// I18N: Hardware key
{ "JOY_START", Common::KEYCODE_RETURN, _s("Start") },
// I18N: Hardware key
{ "JOY_LEFT_SHOULDER", Common::KEYCODE_TAB, _s("L") },
// I18N: Hardware key
{ "JOY_RIGHT_SHOULDER", Common::KEYCODE_BACKSPACE, _s("R") },
{ "JOY_UP", Common::KEYCODE_UP, _s("D-pad Up") },
{ "JOY_DOWN", Common::KEYCODE_DOWN, _s("D-pad Down") },
{ "JOY_LEFT", Common::KEYCODE_LEFT, _s("D-pad Left") },
{ "JOY_RIGHT", Common::KEYCODE_RIGHT, _s("D-pad Right") },
{nullptr, Common::KEYCODE_INVALID, nullptr }
};
static const Common::HardwareInputTableEntry odJoystickButtons[] = {
// I18N: Hardware key
{ "JOY_LEFT_TRIGGER", Common::JOYSTICK_BUTTON_LEFT_STICK, _s("L3") },
{ nullptr, 0, nullptr }
};
static const Common::AxisTableEntry odJoystickAxes[] = {
{ "JOY_LEFT_STICK_X", Common::JOYSTICK_AXIS_LEFT_STICK_X, Common::kAxisTypeFull, _s("Left Stick X") },
{ "JOY_LEFT_STICK_Y", Common::JOYSTICK_AXIS_LEFT_STICK_Y, Common::kAxisTypeFull, _s("Left Stick Y") },
{ nullptr, 0, Common::kAxisTypeFull, nullptr }
};
Common::KeymapperDefaultBindings *OSystem_SDL_Opendingux::getKeymapperDefaultBindings() {
Common::KeymapperDefaultBindings *keymapperDefaultBindings = new Common::KeymapperDefaultBindings();
if (!Posix::assureDirectoryExists(JOYSTICK_DIR)) {
keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "VMOUSEUP", "JOY_UP");
keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "VMOUSEDOWN", "JOY_DOWN");
keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "VMOUSELEFT", "JOY_LEFT");
keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "VMOUSERIGHT", "JOY_RIGHT");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "UP", "");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "DOWN", "");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "LEFT", "");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "RIGHT", "");
keymapperDefaultBindings->setDefaultBinding("engine-default", "UP", "");
keymapperDefaultBindings->setDefaultBinding("engine-default", "DOWN", "");
keymapperDefaultBindings->setDefaultBinding("engine-default", "LEFT", "");
keymapperDefaultBindings->setDefaultBinding("engine-default", "RIGHT", "");
}
return keymapperDefaultBindings;
}
void OSystem_SDL_Opendingux::init() {
_fsFactory = new POSIXFilesystemFactory();
if (!Posix::assureDirectoryExists(SCUMM_DIR)) {
system("mkdir " SCUMM_DIR);
}
// Invoke parent implementation of this method
OSystem_SDL::init();
}
void OSystem_SDL_Opendingux::initBackend() {
#ifdef RS90
ConfMan.registerDefault("fullscreen", false);
#else
ConfMan.registerDefault("fullscreen", true);
#endif
ConfMan.registerDefault("aspect_ratio", true);
ConfMan.registerDefault("themepath", Common::Path("./themes"));
ConfMan.registerDefault("extrapath", Common::Path("./engine-data"));
ConfMan.registerDefault("gui_theme", "builtin");
ConfMan.registerDefault("scale_factor", "1");
ConfMan.setBool("fullscreen", true);
ConfMan.setInt("joystick_num", 0);
if (!ConfMan.hasKey("aspect_ratio")) {
ConfMan.setBool("aspect_ratio", true);
}
if (!ConfMan.hasKey("themepath")) {
ConfMan.setPath("themepath", "./themes");
}
if (!ConfMan.hasKey("extrapath")) {
ConfMan.setPath("extrapath", "./engine-data");
}
if (!ConfMan.hasKey("savepath")) {
ConfMan.setPath("savepath", SAVE_PATH);
}
if (!ConfMan.hasKey("gui_theme")) {
ConfMan.set("gui_theme", "builtin");
}
if (!ConfMan.hasKey("scale_factor")) {
ConfMan.set("scale_factor", "1");
}
if (!ConfMan.hasKey("opl_driver")) {
ConfMan.set("opl_driver", "db");
}
if (!ConfMan.hasKey("kbdmouse_speed")) {
ConfMan.setInt("kbdmouse_speed", 2);
}
#ifdef LEPUS
if (!ConfMan.hasKey("output_rate")) {
ConfMan.set("output_rate", "22050");
}
#elif RS90
if (!ConfMan.hasKey("output_rate")) {
ConfMan.set("output_rate", "11025");
}
#endif
// Create the savefile manager
if (_savefileManager == nullptr) {
_savefileManager = new DefaultSaveFileManager(SAVE_PATH);
}
if (!_eventSource)
_eventSource = new SdlEventSource();
if (!_graphicsManager)
_graphicsManager = new OpenDinguxGraphicsManager(_eventSource, _window);
OSystem_SDL::initBackend();
}
Common::Path OSystem_SDL_Opendingux::getDefaultConfigFileName() {
return CONFIG_FILE;
}
Common::Path OSystem_SDL_Opendingux::getDefaultLogFileName() {
return LOG_FILE;
}
bool OSystem_SDL_Opendingux::hasFeature(Feature f) {
switch (f) {
case kFeatureFullscreenMode:
case kFeatureAspectRatioCorrection:
return false;
case kFeatureKbdMouseSpeed:
return true;
default:
return OSystem_SDL::hasFeature(f);
}
}
void OSystem_SDL_Opendingux::setFeatureState(Feature f, bool enable) {
OSystem_SDL::setFeatureState(f, enable);
}
bool OSystem_SDL_Opendingux::getFeatureState(Feature f) {
return OSystem_SDL::getFeatureState(f);
}
Common::HardwareInputSet *OSystem_SDL_Opendingux::getHardwareInputSet() {
using namespace Common;
CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
// Users may use USB mice - keyboards currently not possible with SDL1 as it conflicts with gpios
inputSet->addHardwareInputSet(new MouseHardwareInputSet(defaultMouseButtons));
//inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(odKeyboardButtons, defaultModifiers));
inputSet->addHardwareInputSet(new JoystickHardwareInputSet(odJoystickButtons, odJoystickAxes));
return inputSet;
}

View File

@@ -0,0 +1,42 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_OPENDINGUX_H
#define PLATFORM_SDL_OPENDINGUX_H
#include "backends/platform/sdl/sdl.h"
class OSystem_SDL_Opendingux : public OSystem_SDL {
public:
void init() override;
void initBackend() override;
bool hasFeature(Feature f) override;
void setFeatureState(Feature f, bool enable) override;
bool getFeatureState(Feature f) override;
Common::HardwareInputSet *getHardwareInputSet() override;
Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() override;
protected:
Common::Path getDefaultConfigFileName() override;
Common::Path getDefaultLogFileName() override;
};
#endif

View File

@@ -0,0 +1,55 @@
OD_EXE_STRIPPED := scummvm_stripped$(EXEEXT)
bundle = od-opk
OPKNAME = $(OPENDINGUX_TARGET)
all: $(OD_EXE_STRIPPED)
$(OD_EXE_STRIPPED): $(EXECUTABLE)
$(STRIP) $< -o $@
$(bundle): all
$(MKDIR) $(bundle)
$(CP) $(DIST_FILES_DOCS) $(bundle)/
ifneq ($(OPENDINGUX_TARGET), rs90)
$(MKDIR) $(bundle)/themes
$(CP) $(DIST_FILES_THEMES) $(bundle)/themes/
endif
ifdef DIST_FILES_ENGINEDATA
$(MKDIR) $(bundle)/engine-data
$(CP) $(DIST_FILES_ENGINEDATA) $(bundle)/engine-data/
endif
ifdef DIST_FILES_NETWORKING
$(CP) $(DIST_FILES_NETWORKING) $(bundle)/
endif
ifdef DIST_FILES_VKEYBD
$(CP) $(DIST_FILES_VKEYBD) $(bundle)/
endif
ifdef DYNAMIC_MODULES
$(MKDIR) $(bundle)/plugins
$(CP) $(PLUGINS) $(bundle)/plugins/
endif
$(CP) $(EXECUTABLE) $(bundle)/scummvm
$(CP) $(srcdir)/dists/opendingux/scummvm.png $(bundle)/
$(CP) $(srcdir)/dists/opendingux/startUI.$(OPENDINGUX_TARGET).desktop $(bundle)/
ifdef dualopk
$(CP) $(srcdir)/dists/opendingux/startGame.$(OPENDINGUX_TARGET).desktop $(bundle)/
$(CP) $(srcdir)/dists/opendingux/scummvm.sh $(bundle)/
endif
$(CP) $(srcdir)/backends/platform/sdl/opendingux/README.OPENDINGUX $(bundle)/README.man.txt
echo >> $(bundle)/README.man.txt
echo '[General README]' >> $(bundle)/README.man.txt
echo >> $(bundle)/README.man.txt
cat $(srcdir)/README.md | sed -e 's/\[/⟦/g' -e 's/\]/⟧/g' -e '/^1\.1)/,$$ s/^[0-9][0-9]*\.[0-9][0-9]*.*/\[&\]/' >> $(bundle)/README.man.txt
od-make-opk: $(bundle)
$(STRIP) $(bundle)/scummvm
ifdef dualopk
$(srcdir)/dists/opendingux/make-opk.sh -d $(bundle) -o scummvm_$(OPKNAME)_dual
else
$(srcdir)/dists/opendingux/make-opk.sh -d $(bundle) -o scummvm_$(OPKNAME)
endif

View File

@@ -0,0 +1,52 @@
/* 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/scummsys.h"
#if defined(POSIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(MAEMO) && !defined(OPENDINGUX) && !defined(OPENPANDORA) && !defined(PLAYSTATION3) && !defined(PSP2) && !defined(NINTENDO_SWITCH) && !defined(__EMSCRIPTEN__) && !defined(MIYOO) && !defined(MIYOOMINI) && !defined(SAILFISH)
#include "backends/platform/sdl/posix/posix.h"
#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
int main(int argc, char *argv[]) {
// Create our OSystem instance
g_system = new OSystem_POSIX();
assert(g_system);
// Pre initialize the backend
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
return res;
}
#endif

View File

@@ -0,0 +1,483 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_getenv
#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
#define FORBIDDEN_SYMBOL_EXCEPTION_exit
#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h //On IRIX, sys/stat.h includes sys/time.h
#define FORBIDDEN_SYMBOL_EXCEPTION_system
#define FORBIDDEN_SYMBOL_EXCEPTION_random
#define FORBIDDEN_SYMBOL_EXCEPTION_srandom
#include "common/scummsys.h"
#ifdef POSIX
#include "backends/platform/sdl/posix/posix.h"
#include "backends/saves/posix/posix-saves.h"
#include "backends/fs/posix/posix-fs-factory.h"
#include "backends/fs/posix/posix-fs.h"
#include "backends/taskbar/unity/unity-taskbar.h"
#include "backends/dialogs/gtk/gtk-dialogs.h"
#ifdef USE_LINUXCD
#include "backends/audiocd/linux/linux-audiocd.h"
#endif
#include "common/textconsole.h"
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#ifdef HAS_POSIX_SPAWN
#include <spawn.h>
#endif
#if defined(USE_SPEECH_DISPATCHER) && defined(USE_TTS)
#include "backends/text-to-speech/linux/linux-text-to-speech.h"
#endif
extern char **environ;
void OSystem_POSIX::init() {
// Initialze File System Factory
_fsFactory = new POSIXFilesystemFactory();
#if defined(USE_TASKBAR) && defined(USE_UNITY)
// Initialize taskbar manager
_taskbarManager = new UnityTaskbarManager();
#endif
#if defined(USE_SYSDIALOGS) && defined(USE_GTK)
// Initialize dialog manager
_dialogManager = new GtkDialogManager();
#endif
// Invoke parent implementation of this method
OSystem_SDL::init();
}
void OSystem_POSIX::initBackend() {
// Create the savefile manager
if (_savefileManager == 0)
_savefileManager = new POSIXSaveFileManager();
#if defined(USE_SPEECH_DISPATCHER) && defined(USE_TTS)
// Initialize Text to Speech manager
_textToSpeechManager = new SpeechDispatcherManager();
#endif
// Invoke parent implementation of this method
OSystem_SDL::initBackend();
#if defined(USE_TASKBAR) && defined(USE_UNITY)
// Register the taskbar manager as an event source (this is necessary for the glib event loop to be run)
_eventManager->getEventDispatcher()->registerSource((UnityTaskbarManager *)_taskbarManager, false);
#endif
}
bool OSystem_POSIX::hasFeature(Feature f) {
if (f == kFeatureDisplayLogFile)
return true;
#ifdef HAS_POSIX_SPAWN
if (f == kFeatureOpenUrl)
return true;
#endif
#if defined(USE_SYSDIALOGS) && defined(USE_GTK)
if (f == kFeatureSystemBrowserDialog)
return true;
#endif
return OSystem_SDL::hasFeature(f);
}
Common::Path OSystem_POSIX::getDefaultConfigFileName() {
const Common::String baseConfigName = "scummvm.ini";
Common::String configFile;
Common::String prefix;
// Our old configuration file path for POSIX systems was ~/.scummvmrc.
// If that file exists, we still use it.
const char *envVar = getenv("HOME");
if (envVar && *envVar) {
configFile = envVar;
configFile += '/';
configFile += ".scummvmrc";
if (configFile.size() < MAXPATHLEN) {
struct stat sb;
if (stat(configFile.c_str(), &sb) == 0) {
return Common::Path(configFile, '/');
}
}
}
// On POSIX systems we follow the XDG Base Directory Specification for
// where to store files. The version we based our code upon can be found
// over here: https://specifications.freedesktop.org/basedir-spec/basedir-spec-0.8.html
envVar = getenv("XDG_CONFIG_HOME");
if (!envVar || !*envVar) {
envVar = getenv("HOME");
if (envVar && *envVar) {
if (Posix::assureDirectoryExists(".config", envVar)) {
prefix = envVar;
prefix += "/.config";
}
}
} else {
prefix = envVar;
}
if (!prefix.empty() && Posix::assureDirectoryExists("scummvm", prefix.c_str())) {
prefix += "/scummvm";
}
if (!prefix.empty() && (prefix.size() + 1 + baseConfigName.size()) < MAXPATHLEN) {
configFile = prefix;
configFile += '/';
configFile += baseConfigName;
} else {
configFile = baseConfigName;
}
return Common::Path(configFile, '/');
}
Common::String OSystem_POSIX::getXdgUserDir(const char *name) {
// The xdg-user-dirs configuration path is stored in the XDG config
// home directory. We start by retrieving this value.
Common::String configHome = getenv("XDG_CONFIG_HOME");
if (configHome.empty()) {
const char *home = getenv("HOME");
if (!home) {
return "";
}
configHome = Common::String::format("%s/.config", home);
}
// Find the requested directory line in the xdg-user-dirs configuration file
// Example line value: XDG_PICTURES_DIR="$HOME/Pictures"
Common::FSNode userDirsFile(Common::Path(configHome + "/user-dirs.dirs", '/'));
if (!userDirsFile.exists() || !userDirsFile.isReadable() || userDirsFile.isDirectory()) {
return "";
}
Common::SeekableReadStream *userDirsStream = userDirsFile.createReadStream();
if (!userDirsStream) {
return "";
}
Common::String dirLinePrefix = Common::String::format("XDG_%s_DIR=", name);
Common::String directoryValue;
while (!userDirsStream->eos() && !userDirsStream->err()) {
Common::String userDirsLine = userDirsStream->readLine();
userDirsLine.trim();
if (userDirsLine.hasPrefix(dirLinePrefix)) {
directoryValue = Common::String(userDirsLine.c_str() + dirLinePrefix.size());
break;
}
}
delete userDirsStream;
// Extract the path from the value
// Example value: "$HOME/Pictures"
if (directoryValue.empty() || directoryValue[0] != '"') {
return "";
}
if (directoryValue[directoryValue.size() - 1] != '"') {
return "";
}
// According to the spec the value is shell-escaped, and would need to be
// unescaped to be used, but neither the GTK+ nor the Qt implementation seem to
// properly perform that step, it's probably fine if we don't do it either.
Common::String directoryPath(directoryValue.c_str() + 1, directoryValue.size() - 2);
if (directoryPath.hasPrefix("$HOME/")) {
const char *home = getenv("HOME");
directoryPath = Common::String::format("%s%s", home, directoryPath.c_str() + 5);
}
// At this point, the path must be absolute
if (directoryPath.empty() || directoryPath[0] != '/') {
return "";
}
return directoryPath;
}
Common::Path OSystem_POSIX::getDefaultIconsPath() {
Common::String iconsPath;
// On POSIX systems we follow the XDG Base Directory Specification for
// where to store files. The version we based our code upon can be found
// over here: https://specifications.freedesktop.org/basedir-spec/basedir-spec-0.8.html
const char *prefix = getenv("XDG_CACHE_HOME");
if (prefix == nullptr || !*prefix) {
prefix = getenv("HOME");
if (prefix == nullptr) {
return Common::Path();
}
iconsPath = ".cache/";
}
iconsPath += "scummvm/icons";
if (!Posix::assureDirectoryExists(iconsPath, prefix)) {
return Common::Path();
}
return Common::Path(prefix).join(iconsPath);
}
Common::Path OSystem_POSIX::getDefaultDLCsPath() {
Common::String dlcsPath;
// On POSIX systems we follow the XDG Base Directory Specification for
// where to store files. The version we based our code upon can be found
// over here: https://specifications.freedesktop.org/basedir-spec/basedir-spec-0.8.html
const char *prefix = getenv("XDG_CACHE_HOME");
if (prefix == nullptr || !*prefix) {
prefix = getenv("HOME");
if (prefix == nullptr) {
return Common::Path();
}
dlcsPath = ".cache/";
}
dlcsPath += "scummvm/dlcs";
if (!Posix::assureDirectoryExists(dlcsPath, prefix)) {
return Common::Path();
}
return Common::Path(prefix).join(dlcsPath);
}
Common::Path OSystem_POSIX::getScreenshotsPath() {
// If the user has configured a screenshots path, use it
const Common::Path path = OSystem_SDL::getScreenshotsPath();
if (!path.empty()) {
return path;
}
// Otherwise, the default screenshots path is the "ScummVM Screenshots"
// directory in the XDG "Pictures" user directory, as defined in the
// xdg-user-dirs spec: https://www.freedesktop.org/wiki/Software/xdg-user-dirs/
Common::String picturesPath = getXdgUserDir("PICTURES");
if (picturesPath.empty()) {
return "";
}
if (!picturesPath.hasSuffix("/")) {
picturesPath += "/";
}
static const char *const SCREENSHOTS_DIR_NAME = "ScummVM Screenshots";
if (!Posix::assureDirectoryExists(SCREENSHOTS_DIR_NAME, picturesPath.c_str())) {
return "";
}
return Common::Path(picturesPath).join(SCREENSHOTS_DIR_NAME);
}
void OSystem_POSIX::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
#ifdef DATA_PATH
const char *path = nullptr;
if (!path) {
path = getenv("SNAP");
}
if (!path) {
path = getenv("APPDIR");
}
if (path) {
Common::Path dataPath(path);
dataPath.joinInPlace(DATA_PATH);
Common::FSNode dataNode(dataPath);
if (dataNode.exists() && dataNode.isDirectory()) {
// This is the same priority which is used for the data path (below),
// but we insert this one first, so it will be searched first.
s.addDirectory(dataNode, priority, 4);
}
}
#endif
// For now, we always add the data path, just in case SNAP doesn't make sense.
OSystem_SDL::addSysArchivesToSearchSet(s, priority);
}
Common::Path OSystem_POSIX::getDefaultLogFileName() {
Common::String logFile;
// On POSIX systems we follow the XDG Base Directory Specification for
// where to store files. The version we based our code upon can be found
// over here: https://specifications.freedesktop.org/basedir-spec/basedir-spec-0.8.html
const char *prefix = getenv("XDG_CACHE_HOME");
if (prefix == nullptr || !*prefix) {
prefix = getenv("HOME");
if (prefix == nullptr) {
return Common::Path();
}
logFile = ".cache/";
}
logFile += "scummvm/logs";
if (!Posix::assureDirectoryExists(logFile, prefix)) {
return Common::Path();
}
Common::Path logPath(prefix);
logPath.joinInPlace(logFile);
logPath.joinInPlace("scummvm.log");
return logPath;
}
bool OSystem_POSIX::displayLogFile() {
if (_logFilePath.empty())
return false;
// FIXME: This may not work perfectly when in fullscreen mode.
// On my system it drops from fullscreen without ScummVM noticing,
// so the next Alt-Enter does nothing, going from windowed to windowed.
// (wjp, 20110604)
pid_t pid = fork();
if (pid < 0) {
// failed to fork
return false;
} else if (pid == 0) {
// Try xdg-open first
execlp("xdg-open", "xdg-open", _logFilePath.toString(Common::Path::kNativeSeparator).c_str(), (char *)0);
// If we're here, that clearly failed.
// TODO: We may also want to try detecting the case where
// xdg-open is successfully executed but returns an error code.
// Try xterm+less next
execlp("xterm", "xterm", "-e", "less", _logFilePath.toString(Common::Path::kNativeSeparator).c_str(), (char *)0);
// TODO: If less does not exist we could fall back to 'more'.
// However, we'll have to use 'xterm -hold' for that to prevent the
// terminal from closing immediately (for short log files) or
// unexpectedly.
exit(127);
}
int status;
// Wait for viewer to close.
// (But note that xdg-open may have spawned a viewer in the background.)
// FIXME: We probably want the viewer to always open in the background.
// This may require installing a SIGCHLD handler.
pid = waitpid(pid, &status, 0);
if (pid < 0) {
// Probably nothing sensible to do in this error situation
return false;
}
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
}
#ifdef HAS_POSIX_SPAWN
bool OSystem_POSIX::openUrl(const Common::String &url) {
// inspired by Qt's "qdesktopservices_x11.cpp"
// try "standards"
if (launchBrowser("xdg-open", url))
return true;
if (launchBrowser(getenv("DEFAULT_BROWSER"), url))
return true;
if (launchBrowser(getenv("BROWSER"), url))
return true;
// try desktop environment specific tools
if (launchBrowser("gnome-open", url)) // gnome
return true;
if (launchBrowser("kfmclient", url)) // kde
return true;
if (launchBrowser("exo-open", url)) // xfce
return true;
// try browser names
if (launchBrowser("firefox", url))
return true;
if (launchBrowser("mozilla", url))
return true;
if (launchBrowser("netscape", url))
return true;
if (launchBrowser("opera", url))
return true;
if (launchBrowser("chromium-browser", url))
return true;
if (launchBrowser("google-chrome", url))
return true;
warning("openUrl() (POSIX) failed to open URL");
return false;
}
bool OSystem_POSIX::launchBrowser(const Common::String &client, const Common::String &url) {
pid_t pid;
const char *argv[] = {
client.c_str(),
url.c_str(),
NULL,
NULL
};
if (client == "kfmclient") {
argv[2] = argv[1];
argv[1] = "openURL";
}
if (posix_spawnp(&pid, client.c_str(), NULL, NULL, const_cast<char **>(argv), environ) != 0) {
return false;
}
return (waitpid(pid, NULL, WNOHANG) != -1);
}
#endif
AudioCDManager *OSystem_POSIX::createAudioCDManager() {
#ifdef USE_LINUXCD
return createLinuxAudioCDManager();
#else
return OSystem_SDL::createAudioCDManager();
#endif
}
#endif

View File

@@ -0,0 +1,60 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_POSIX_H
#define PLATFORM_SDL_POSIX_H
#include "backends/platform/sdl/sdl.h"
class OSystem_POSIX : public OSystem_SDL {
public:
bool hasFeature(Feature f) override;
bool displayLogFile() override;
void init() override;
void initBackend() override;
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0) override;
// Default paths
Common::Path getDefaultIconsPath() override;
Common::Path getDefaultDLCsPath() override;
Common::Path getScreenshotsPath() override;
protected:
Common::Path getDefaultConfigFileName() override;
Common::Path getDefaultLogFileName() override;
Common::String getXdgUserDir(const char *name);
AudioCDManager *createAudioCDManager() override;
#ifdef HAS_POSIX_SPAWN
public:
bool openUrl(const Common::String &url) override;
protected:
bool launchBrowser(const Common::String& client, const Common::String &url);
#endif
};
#endif

View File

@@ -0,0 +1,63 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/scummsys.h"
#include "backends/platform/sdl/ps3/ps3.h"
#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
#include <net/net.h>
#include <sys/process.h>
// Set program stack size from default 64KB to 256KB
SYS_PROCESS_PARAM(1000, 0x40000)
int main(int argc, char *argv[]) {
#if defined(USE_LIBCURL) || defined(USE_SDL_NET)
netInitialize();
#endif
// Create our OSystem instance
g_system = new OSystem_PS3();
assert(g_system);
// Pre initialize the backend
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
#if defined(USE_LIBCURL) || defined(USE_SDL_NET)
netDeinitialize();
#endif
return res;
}

View File

@@ -0,0 +1,139 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h // sys/stat.h includes sys/time.h
#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/translation.h"
#include "backends/platform/sdl/ps3/ps3.h"
#include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
#include "backends/saves/default/default-saves.h"
#include "backends/fs/ps3/ps3-fs-factory.h"
#include "backends/events/ps3sdl/ps3sdl-events.h"
#include "backends/keymapper/hardware-input.h"
#include <dirent.h>
#include <sys/stat.h>
static const Common::HardwareInputTableEntry playstationJoystickButtons[] = {
{ "JOY_A", Common::JOYSTICK_BUTTON_A, _s("Cross") },
{ "JOY_B", Common::JOYSTICK_BUTTON_B, _s("Circle") },
{ "JOY_X", Common::JOYSTICK_BUTTON_X, _s("Square") },
{ "JOY_Y", Common::JOYSTICK_BUTTON_Y, _s("Triangle") },
{ "JOY_BACK", Common::JOYSTICK_BUTTON_BACK, _s("Select") },
{ "JOY_GUIDE", Common::JOYSTICK_BUTTON_GUIDE, _s("PS") },
{ "JOY_START", Common::JOYSTICK_BUTTON_START, _s("Start") },
{ "JOY_LEFT_STICK", Common::JOYSTICK_BUTTON_LEFT_STICK, _s("L3") },
{ "JOY_RIGHT_STICK", Common::JOYSTICK_BUTTON_RIGHT_STICK, _s("R3") },
{ "JOY_LEFT_SHOULDER", Common::JOYSTICK_BUTTON_LEFT_SHOULDER, _s("L1") },
{ "JOY_RIGHT_SHOULDER", Common::JOYSTICK_BUTTON_RIGHT_SHOULDER, _s("R1") },
{ "JOY_UP", Common::JOYSTICK_BUTTON_DPAD_UP, _s("D-pad Up") },
{ "JOY_DOWN", Common::JOYSTICK_BUTTON_DPAD_DOWN, _s("D-pad Down") },
{ "JOY_LEFT", Common::JOYSTICK_BUTTON_DPAD_LEFT, _s("D-pad Left") },
{ "JOY_RIGHT", Common::JOYSTICK_BUTTON_DPAD_RIGHT, _s("D-pad Right") },
{ nullptr, 0, nullptr }
};
static const Common::AxisTableEntry playstationJoystickAxes[] = {
{ "JOY_LEFT_TRIGGER", Common::JOYSTICK_AXIS_LEFT_TRIGGER, Common::kAxisTypeHalf, _s("L2") },
{ "JOY_RIGHT_TRIGGER", Common::JOYSTICK_AXIS_RIGHT_TRIGGER, Common::kAxisTypeHalf, _s("R2") },
{ "JOY_LEFT_STICK_X", Common::JOYSTICK_AXIS_LEFT_STICK_X, Common::kAxisTypeFull, _s("Left Stick X") },
{ "JOY_LEFT_STICK_Y", Common::JOYSTICK_AXIS_LEFT_STICK_Y, Common::kAxisTypeFull, _s("Left Stick Y") },
{ "JOY_RIGHT_STICK_X", Common::JOYSTICK_AXIS_RIGHT_STICK_X, Common::kAxisTypeFull, _s("Right Stick X") },
{ "JOY_RIGHT_STICK_Y", Common::JOYSTICK_AXIS_RIGHT_STICK_Y, Common::kAxisTypeFull, _s("Right Stick Y") },
{ nullptr, 0, Common::kAxisTypeFull, nullptr }
};
int access(const char *pathname, int mode) {
struct stat sb;
if (stat(pathname, &sb) == -1) {
return -1;
}
return 0;
}
void OSystem_PS3::init() {
// Initialze File System Factory
_fsFactory = new PS3FilesystemFactory();
// Invoke parent implementation of this method
OSystem_SDL::init();
}
void OSystem_PS3::initBackend() {
ConfMan.set("joystick_num", 0);
ConfMan.registerDefault("fullscreen", true);
ConfMan.registerDefault("aspect_ratio", true);
ConfMan.setBool("fullscreen", true);
if (!ConfMan.hasKey("aspect_ratio"))
ConfMan.setBool("aspect_ratio", true);
// Create the savefile manager
if (_savefileManager == 0)
_savefileManager = new DefaultSaveFileManager(PREFIX "/saves");
// Event source
if (_eventSource == 0)
_eventSource = new PS3SdlEventSource();
// Invoke parent implementation of this method
OSystem_SDL::initBackend();
}
Common::Path OSystem_PS3::getDefaultConfigFileName() {
return PREFIX "/scummvm.ini";
}
Common::Path OSystem_PS3::getDefaultLogFileName() {
return PREFIX "/scummvm.log";
}
Common::HardwareInputSet *OSystem_PS3::getHardwareInputSet() {
using namespace Common;
CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
// Users may use USB / bluetooth mice and keyboards
inputSet->addHardwareInputSet(new MouseHardwareInputSet(defaultMouseButtons));
inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
inputSet->addHardwareInputSet(new JoystickHardwareInputSet(playstationJoystickButtons, playstationJoystickAxes));
return inputSet;
}
bool OSystem_PS3::hasFeature(Feature f) {
if (f == kFeatureDisplayLogFile ||
f == kFeatureFullscreenMode ||
f == kFeatureIconifyWindow ||
f == kFeatureOpenUrl ||
f == kFeatureSystemBrowserDialog ||
f == kFeatureClipboardSupport) {
return false;
}
return OSystem_SDL::hasFeature(f);
}

View File

@@ -0,0 +1,39 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_PS3_H
#define PLATFORM_SDL_PS3_H
#include "backends/platform/sdl/sdl.h"
class OSystem_PS3 : public OSystem_SDL {
public:
void init() override;
void initBackend() override;
bool hasFeature(Feature f) override;
Common::HardwareInputSet *getHardwareInputSet() override;
protected:
Common::Path getDefaultConfigFileName() override;
Common::Path getDefaultLogFileName() override;
};
#endif

View File

@@ -0,0 +1,34 @@
ps3pkg: $(EXECUTABLE)
$(STRIP) $(EXECUTABLE)
sprxlinker $(EXECUTABLE)
mkdir -p ps3pkg/USRDIR/data/
mkdir -p ps3pkg/USRDIR/doc/
mkdir -p ps3pkg/USRDIR/saves/
make_self_npdrm "$(EXECUTABLE)" ps3pkg/USRDIR/EBOOT.BIN UP0001-SCUM12000_00-0000000000000000
cp $(DIST_FILES_THEMES) ps3pkg/USRDIR/data/
ifdef DIST_FILES_ENGINEDATA
cp $(DIST_FILES_ENGINEDATA) ps3pkg/USRDIR/data/
endif
ifdef DIST_FILES_NETWORKING
cp $(DIST_FILES_NETWORKING) ps3pkg/USRDIR/data/
endif
ifdef DIST_FILES_VKEYBD
cp $(DIST_FILES_VKEYBD) ps3pkg/USRDIR/data/
endif
ifdef DIST_PS3_EXTRA_FILES
@cp -a $(DIST_PS3_EXTRA_FILES) ps3pkg/USRDIR/data/
endif
cp $(DIST_FILES_DOCS) ps3pkg/USRDIR/doc/
cp $(srcdir)/dists/ps3/readme-ps3.md ps3pkg/USRDIR/doc/
cp $(srcdir)/dists/ps3/ICON0.PNG ps3pkg/
cp $(srcdir)/dists/ps3/PIC1.PNG ps3pkg/
sfo.py -f $(srcdir)/dists/ps3/sfo.xml ps3pkg/PARAM.SFO
pkg.py --contentid UP0001-SCUM12000_00-0000000000000000 ps3pkg/ scummvm-ps3.pkg
ps3run: $(EXECUTABLE)
$(STRIP) $(EXECUTABLE)
sprxlinker $(EXECUTABLE)
make_self $(EXECUTABLE) $(EXECUTABLE).self
ps3load $(EXECUTABLE).self
.PHONY: ps3pkg ps3run

View File

@@ -0,0 +1,107 @@
/* 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 <psp2/kernel/processmgr.h>
#include <psp2/power.h>
#include <psp2/appmgr.h>
#include "common/scummsys.h"
#include "backends/platform/sdl/psp2/psp2.h"
#include "backends/plugins/psp2/psp2-provider.h"
#include "base/main.h"
#ifdef ENABLE_PROFILING
#include <vitagprof.h>
#endif
int _newlib_heap_size_user = 192 * 1024 * 1024;
char boot_params[1024];
int main(int argc, char *argv[]) {
scePowerSetArmClockFrequency(444);
scePowerSetBusClockFrequency(222);
scePowerSetGpuClockFrequency(222);
scePowerSetGpuXbarClockFrequency(166);
// Create our OSystem instance
g_system = new OSystem_PSP2();
assert(g_system);
// Pre initialize the backend
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new PSP2PluginProvider());
#endif
sceAppMgrGetAppParam(boot_params);
int res;
if (strstr(boot_params,"psgm:play"))
{
char *path_param = strstr(boot_params, "&path=");
char *gameid_param = strstr(boot_params, "&game_id=");
if (path_param != NULL && gameid_param != NULL)
{
char path[256];
char game_id[64];
if (gameid_param > path_param)
{
// handle case where gameid param follows path param
path_param += 6;
memcpy(path, path_param, gameid_param - path_param);
path[gameid_param-path_param] = 0;
snprintf(game_id, 64, gameid_param + 9);
}
else
{
// handle case where path param follows gameid param
gameid_param += 9;
memcpy(game_id, gameid_param, path_param - gameid_param);
game_id[path_param-gameid_param] = 0;
snprintf(path, 256, path_param + 6);
}
const char* args[4];
args[0] = "ux0:app/VSCU00001/eboot.bin";
args[1] = "-p";
args[2] = path;
args[3] = game_id;
res = scummvm_main(4, args);
goto exit;
}
}
// Invoke the actual ScummVM main entry point:
res = scummvm_main(argc, argv);
exit:
// Free OSystem
g_system->destroy();
#ifdef ENABLE_PROFILING
gprof_stop("ux0:/data/gmon.out", 1);
#endif
return res;
}

View File

@@ -0,0 +1,178 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h // sys/stat.h includes sys/time.h
#define FORBIDDEN_SYMBOL_EXCEPTION_printf // used by sceClibPrintf()
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/translation.h"
#include "backends/platform/sdl/psp2/psp2.h"
#include "backends/saves/default/default-saves.h"
#include "backends/fs/posix-drives/posix-drives-fs-factory.h"
#include "backends/events/psp2sdl/psp2sdl-events.h"
#include "backends/keymapper/hardware-input.h"
#include <sys/stat.h>
#include <psp2/io/stat.h>
#include <psp2/kernel/clib.h>
static const Common::HardwareInputTableEntry psp2JoystickButtons[] = {
{ "JOY_A", Common::JOYSTICK_BUTTON_A, _s("Cross") },
{ "JOY_B", Common::JOYSTICK_BUTTON_B, _s("Circle") },
{ "JOY_X", Common::JOYSTICK_BUTTON_X, _s("Square") },
{ "JOY_Y", Common::JOYSTICK_BUTTON_Y, _s("Triangle") },
{ "JOY_BACK", Common::JOYSTICK_BUTTON_BACK, _s("Select") },
{ "JOY_START", Common::JOYSTICK_BUTTON_START, _s("Start") },
{ "JOY_LEFT_SHOULDER", Common::JOYSTICK_BUTTON_LEFT_SHOULDER, _s("L") },
{ "JOY_RIGHT_SHOULDER", Common::JOYSTICK_BUTTON_RIGHT_SHOULDER, _s("R") },
{ "JOY_UP", Common::JOYSTICK_BUTTON_DPAD_UP, _s("D-pad Up") },
{ "JOY_DOWN", Common::JOYSTICK_BUTTON_DPAD_DOWN, _s("D-pad Down") },
{ "JOY_LEFT", Common::JOYSTICK_BUTTON_DPAD_LEFT, _s("D-pad Left") },
{ "JOY_RIGHT", Common::JOYSTICK_BUTTON_DPAD_RIGHT, _s("D-pad Right") },
{ nullptr, 0, nullptr }
};
static const Common::AxisTableEntry psp2JoystickAxes[] = {
{ "JOY_LEFT_STICK_X", Common::JOYSTICK_AXIS_LEFT_STICK_X, Common::kAxisTypeFull, _s("Left Stick X") },
{ "JOY_LEFT_STICK_Y", Common::JOYSTICK_AXIS_LEFT_STICK_Y, Common::kAxisTypeFull, _s("Left Stick Y") },
{ "JOY_RIGHT_STICK_X", Common::JOYSTICK_AXIS_RIGHT_STICK_X, Common::kAxisTypeFull, _s("Right Stick X") },
{ "JOY_RIGHT_STICK_Y", Common::JOYSTICK_AXIS_RIGHT_STICK_Y, Common::kAxisTypeFull, _s("Right Stick Y") },
{ nullptr, 0, Common::kAxisTypeFull, nullptr }
};
int access(const char *pathname, int mode) {
struct stat sb;
if (stat(pathname, &sb) == -1) {
return -1;
}
return 0;
}
void OSystem_PSP2::init() {
// Initialize File System Factory
sceIoMkdir("ux0:data", 0755);
sceIoMkdir("ux0:data/scummvm", 0755);
sceIoMkdir("ux0:data/scummvm/saves", 0755);
DrivesPOSIXFilesystemFactory *fsFactory = new DrivesPOSIXFilesystemFactory();
fsFactory->addDrive("ux0:");
fsFactory->addDrive("uma0:");
_fsFactory = fsFactory;
// Invoke parent implementation of this method
OSystem_SDL::init();
}
void OSystem_PSP2::initBackend() {
ConfMan.set("joystick_num", 0);
ConfMan.registerDefault("fullscreen", true);
ConfMan.registerDefault("aspect_ratio", false);
ConfMan.registerDefault("gfx_mode", "2x");
ConfMan.registerDefault("filtering", true);
ConfMan.registerDefault("kbdmouse_speed", 3);
ConfMan.registerDefault("joystick_deadzone", 2);
ConfMan.registerDefault("touchpad_mouse_mode", false);
ConfMan.registerDefault("frontpanel_touchpad_mode", false);
ConfMan.setBool("fullscreen", true);
if (!ConfMan.hasKey("aspect_ratio")) {
ConfMan.setBool("aspect_ratio", false);
}
if (!ConfMan.hasKey("gfx_mode")) {
ConfMan.set("gfx_mode", "2x");
}
if (!ConfMan.hasKey("filtering")) {
ConfMan.setBool("filtering", true);
}
if (!ConfMan.hasKey("touchpad_mouse_mode")) {
ConfMan.setBool("touchpad_mouse_mode", false);
}
if (!ConfMan.hasKey("frontpanel_touchpad_mode")) {
ConfMan.setBool("frontpanel_touchpad_mode", false);
}
// Create the savefile manager
if (_savefileManager == 0)
_savefileManager = new DefaultSaveFileManager("ux0:data/scummvm/saves");
// Controller mappings for Vita, various names have been used in various SDL versions
SDL_GameControllerAddMapping("50535669746120436f6e74726f6c6c65,PSVita Controller,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,dpdown:b6,dpleft:b7,dpup:b8,dpright:b9,back:b10,start:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,");
SDL_GameControllerAddMapping("50535669746120636f6e74726f6c6c65,PSVita controller,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,dpdown:b6,dpleft:b7,dpup:b8,dpright:b9,back:b10,start:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,");
SDL_GameControllerAddMapping("50535669746120636f6e74726f6c6c65,PSVita controller 2,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,dpdown:b6,dpleft:b7,dpup:b8,dpright:b9,back:b10,start:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,");
SDL_GameControllerAddMapping("50535669746120636f6e74726f6c6c65,PSVita controller 3,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,dpdown:b6,dpleft:b7,dpup:b8,dpright:b9,back:b10,start:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,");
SDL_GameControllerAddMapping("50535669746120636f6e74726f6c6c65,PSVita controller 4,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,dpdown:b6,dpleft:b7,dpup:b8,dpright:b9,back:b10,start:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,");
SDL_GameControllerAddMapping("505356697461206275696c74696e206a,PSVita builtin joypad,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,dpdown:b6,dpleft:b7,dpup:b8,dpright:b9,back:b10,start:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,");
// Event source
if (_eventSource == 0)
_eventSource = new PSP2EventSource();
// Invoke parent implementation of this method
OSystem_SDL::initBackend();
}
bool OSystem_PSP2::hasFeature(Feature f) {
if (f == kFeatureFullscreenMode)
return false;
return (f == kFeatureKbdMouseSpeed ||
f == kFeatureJoystickDeadzone ||
f == kFeatureTouchpadMode ||
OSystem_SDL::hasFeature(f));
}
void OSystem_PSP2::logMessage(LogMessageType::Type type, const char *message) {
sceClibPrintf(message);
// Log only error messages to file
if (type == LogMessageType::kError && _logger)
_logger->print(message);
}
Common::Path OSystem_PSP2::getDefaultConfigFileName() {
return "ux0:data/scummvm/scummvm.ini";
}
Common::Path OSystem_PSP2::getDefaultLogFileName() {
return "ux0:data/scummvm/scummvm.log";
}
Common::HardwareInputSet *OSystem_PSP2::getHardwareInputSet() {
using namespace Common;
CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
// Users may use USB / bluetooth mice and keyboards
inputSet->addHardwareInputSet(new MouseHardwareInputSet(defaultMouseButtons));
inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
inputSet->addHardwareInputSet(new JoystickHardwareInputSet(psp2JoystickButtons, psp2JoystickAxes));
return inputSet;
}

View File

@@ -0,0 +1,40 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_PSP2_H
#define PLATFORM_SDL_PSP2_H
#include "backends/platform/sdl/sdl.h"
class OSystem_PSP2 : public OSystem_SDL {
public:
void init() override;
void initBackend() override;
bool hasFeature(Feature f) override;
void logMessage(LogMessageType::Type type, const char *message) override;
Common::HardwareInputSet *getHardwareInputSet() override;
protected:
Common::Path getDefaultConfigFileName() override;
Common::Path getDefaultLogFileName() override;
};
#endif

View File

@@ -0,0 +1,50 @@
PSP2_EXE_STRIPPED := scummvm_stripped$(EXEEXT)
$(PSP2_EXE_STRIPPED): $(EXECUTABLE)
$(STRIP) --strip-debug $< -o $@
psp2vpk: $(PSP2_EXE_STRIPPED) $(PLUGINS)
rm -rf psp2pkg
rm -f $(EXECUTABLE).vpk
mkdir -p psp2pkg/sce_sys/livearea/contents
mkdir -p psp2pkg/data/
mkdir -p psp2pkg/doc/
vita-elf-create $(PSP2_EXE_STRIPPED) $(EXECUTABLE).velf
# Disable ASLR with -na to support profiling, also it can slow things down
vita-make-fself -na -s -c $(EXECUTABLE).velf psp2pkg/eboot.bin
ifdef DYNAMIC_MODULES
# Use psp2rela to convert the main binary to static, this allows plugins to use functions from it without any relocation
psp2rela -src=psp2pkg/eboot.bin -dst=psp2pkg/eboot.bin -static_mode -fetch_base
endif
vita-mksfoex -s TITLE_ID=VSCU00001 -d ATTRIBUTE2=12 "$(EXECUTABLE)" psp2pkg/sce_sys/param.sfo
cp $(srcdir)/dists/psp2/icon0.png psp2pkg/sce_sys/
cp $(srcdir)/dists/psp2/template.xml psp2pkg/sce_sys/livearea/contents/
cp $(srcdir)/dists/psp2/bg.png psp2pkg/sce_sys/livearea/contents/
cp $(srcdir)/dists/psp2/startup.png psp2pkg/sce_sys/livearea/contents/
cp $(DIST_FILES_THEMES) psp2pkg/data/
ifdef DIST_FILES_ENGINEDATA
cp $(DIST_FILES_ENGINEDATA) psp2pkg/data/
endif
ifdef DIST_FILES_NETWORKING
cp $(DIST_FILES_NETWORKING) psp2pkg/data/
endif
ifdef DIST_FILES_VKEYBD
cp $(DIST_FILES_VKEYBD) psp2pkg/data/
endif
ifdef DYNAMIC_MODULES
mkdir -p psp2pkg/plugins
# Each plugin is built as ELF with .suprx extension in main directory because of PLUGIN_SUFFIX variable
# Then it's stripped and converted here to Vita ELF and SELF inside the package directory
set -e ;\
for p in $(PLUGINS); do \
p=$${p%.suprx} ;\
$(STRIP) --strip-debug $$p.suprx -o $$p.stripped.elf ;\
vita-elf-create -n -e $(srcdir)/backends/plugins/psp2/plugin.yml $$p.stripped.elf $$p.velf ;\
vita-make-fself -na -s $$p.velf psp2pkg/plugins/$$(basename "$$p").suprx ;\
done
endif
cp $(DIST_FILES_DOCS) psp2pkg/doc/
cp $(srcdir)/dists/psp2/readme-psp2.md psp2pkg/doc/
cd psp2pkg && zip -r ../$(EXECUTABLE).vpk . && cd ..
.PHONY: psp2vpk

View File

@@ -0,0 +1,62 @@
/* 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/scummsys.h"
#if defined(RISCOS)
#include "backends/platform/sdl/riscos/riscos.h"
#include "backends/plugins/riscos/riscos-provider.h"
#include "base/main.h"
#include <unixlib/local.h>
#include <signal.h>
#include <string.h>
static void signal_handler(int signum) {
__write_backtrace(signum);
error("Received unexpected signal: %s, exiting", strsignal(signum));
}
int main(int argc, char *argv[]) {
signal(SIGSEGV, signal_handler);
// Create our OSystem instance
g_system = new OSystem_RISCOS();
assert(g_system);
// Pre initialize the backend
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new RiscOSPluginProvider());
#endif
// Invoke the actual ScummVM main entry point
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
return res;
}
#endif

View File

@@ -0,0 +1,68 @@
/* 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/scummsys.h"
#include "backends/platform/sdl/riscos/riscos-utils.h"
#include <unixlib/local.h>
namespace RISCOS_Utils {
Common::String toRISCOS(Common::String path) {
char start[PATH_MAX];
char *end = __riscosify_std(path.c_str(), 0, start, PATH_MAX, 0);
return Common::String(start, end);
}
Common::String toUnix(Common::String path) {
Common::String out = Common::String(path);
uint32 start = 0;
if (out.contains("$")) {
char *x = strstr(out.c_str(), "$");
start = x ? x - out.c_str() : -1;
} else if (out.contains(":")) {
char *x = strstr(out.c_str(), ":");
start = x ? x - out.c_str() : -1;
}
for (uint32 ptr = start; ptr < out.size(); ptr += 1) {
switch (out.c_str()[ptr]) {
case '.':
out.setChar('/', ptr);
break;
case '/':
out.setChar('.', ptr);
break;
case '\xA0':
out.setChar(' ', ptr);
break;
default:
break;
}
}
if (out.contains("$") || out.contains(":"))
out = "/" + out;
return out;
}
}

View File

@@ -0,0 +1,48 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_RISCOS_UTILS_H
#define PLATFORM_SDL_RISCOS_UTILS_H
#include "common/str.h"
// Helper functions
namespace RISCOS_Utils {
/**
* Converts a Unix style path to a RISC OS style path.
*
* @param str Unix style path to convert.
* @return RISC OS style path.
*/
Common::String toRISCOS(Common::String path);
/**
* Converts a RISC OS style path to a Unix style path.
*
* @param str RISC OS style path to convert.
* @return Unix style path.
*/
Common::String toUnix(Common::String path);
}
#endif

View File

@@ -0,0 +1,171 @@
/* 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/scummsys.h"
#ifdef RISCOS
#include "backends/platform/sdl/riscos/riscos.h"
#include "backends/saves/default/default-saves.h"
#include "backends/events/riscossdl/riscossdl-events.h"
#include "backends/graphics/riscossdl/riscossdl-graphics.h"
#include "backends/fs/riscos/riscos-fs-factory.h"
#include "backends/fs/riscos/riscos-fs.h"
#include "common/config-manager.h"
#include <kernel.h>
#include <swis.h>
#ifndef URI_Dispatch
#define URI_Dispatch 0x4e381
#endif
#ifndef Report_Text0
#define Report_Text0 0x54c80
#endif
void OSystem_RISCOS::init() {
// Initialze File System Factory
_fsFactory = new RISCOSFilesystemFactory();
// Invoke parent implementation of this method
OSystem_SDL::init();
}
void OSystem_RISCOS::initBackend() {
ConfMan.registerDefault("enable_reporter", false);
// Create the events manager
if (_eventSource == 0)
_eventSource = new RISCOSSdlEventSource();
// Create the graphics manager
if (!_graphicsManager)
_graphicsManager = new RISCOSSdlGraphicsManager(_eventSource, _window);
// Create the savefile manager
if (_savefileManager == 0) {
Common::String savePath = "/<Choices$Write>/ScummVM/Saves";
if (Riscos::assureDirectoryExists(savePath))
_savefileManager = new DefaultSaveFileManager(Common::Path(savePath));
}
// Invoke parent implementation of this method
OSystem_SDL::initBackend();
}
bool OSystem_RISCOS::hasFeature(Feature f) {
if (f == kFeatureOpenUrl)
return true;
return OSystem_SDL::hasFeature(f);
}
bool OSystem_RISCOS::openUrl(const Common::String &url) {
int flags;
if (_swix(URI_Dispatch, _INR(0,2)|_OUT(0), 0, url.c_str(), 0, &flags) != NULL) {
warning("openUrl() (RISCOS) failed to open URL");
return false;
}
if ((flags & 1) == 1) {
warning("openUrl() (RISCOS) failed to open URL");
return false;
}
return true;
}
void OSystem_RISCOS::logMessage(LogMessageType::Type type, const char *message) {
OSystem_SDL::logMessage(type, message);
// Log messages using !Reporter, available from http://www.avisoft.force9.co.uk/Reporter.htm
if (!(ConfMan.hasKey("enable_reporter") && ConfMan.getBool("enable_reporter")))
return;
char colour;
switch (type) {
case LogMessageType::kError:
colour = 'r';
break;
case LogMessageType::kWarning:
colour = 'o';
break;
case LogMessageType::kInfo:
colour = 'l';
break;
case LogMessageType::kDebug:
default:
colour = 'f';
break;
}
Common::String report = Common::String::format("\\%c %s", colour, message);
_swix(Report_Text0, _IN(0), report.c_str());
}
void OSystem_RISCOS::messageBox(LogMessageType::Type type, const char *message) {
_kernel_swi_regs regs;
_kernel_oserror error;
error.errnum = 0;
Common::strlcpy(error.errmess, message, 252);
regs.r[0] = (int)&error;
regs.r[1] = 0;
regs.r[2] = (int)"ScummVM";
regs.r[3] = 0;
regs.r[4] = 0;
regs.r[5] = 0;
switch (type) {
case LogMessageType::kError:
regs.r[1] |= (1 << 8);
break;
case LogMessageType::kWarning:
regs.r[1] |= (1 << 8) | (2 << 9);
break;
case LogMessageType::kInfo:
case LogMessageType::kDebug:
default:
regs.r[1] |= (1 << 8) | (1 << 9);
break;
}
_kernel_swi(Wimp_ReportError, &regs, &regs);
}
Common::Path OSystem_RISCOS::getDefaultConfigFileName() {
return "/<Choices$Write>/ScummVM/scummvmrc";
}
Common::Path OSystem_RISCOS::getDefaultLogFileName() {
Common::String logFile = "/<Choices$Write>/ScummVM/Logs";
if (!Riscos::assureDirectoryExists(logFile)) {
return Common::Path();
}
Common::Path logPath(logFile);
logPath.joinInPlace("scummvm");
return logPath;
}
#endif

View File

@@ -0,0 +1,44 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_RISCOS_H
#define PLATFORM_SDL_RISCOS_H
#include "backends/platform/sdl/sdl.h"
class OSystem_RISCOS : public OSystem_SDL {
public:
virtual void init();
virtual void initBackend();
virtual bool hasFeature(Feature f);
virtual bool openUrl(const Common::String &url);
virtual void logMessage(LogMessageType::Type type, const char *message);
virtual void messageBox(LogMessageType::Type type, const char *message);
protected:
virtual Common::Path getDefaultConfigFileName();
virtual Common::Path getDefaultLogFileName();
};
#endif

View File

@@ -0,0 +1,69 @@
ifeq ($(shell echo a | iconv --to-code=RISCOS-LATIN1//IGNORE//TRANSLIT >/dev/null 2>&1; echo $$?),0)
ENCODING=RISCOS-LATIN1//IGNORE//TRANSLIT
else
ENCODING=ISO-8859-1//IGNORE//TRANSLIT
endif
BASE_APP_NAME ?= !ScummVM
APP_NAME ?= $(BASE_APP_NAME)
DIST_FILES_DOCS_plaintext := $(filter-out $(DIST_FILES_MANUAL),$(DIST_FILES_DOCS))
# Special target to create an RISC OS snapshot installation
riscosdist: all
mkdir -p $(APP_NAME)
elf2aif $(EXECUTABLE) $(APP_NAME)/scummvm,ff8
cp ${srcdir}/dists/riscos/!Help,feb $(APP_NAME)/!Help,feb
ifdef MAKERUN
$(MAKERUN) $(APP_NAME)/scummvm,ff8 ${srcdir}/dists/riscos/!Run,feb $(APP_NAME)/!Run,feb
else
cp ${srcdir}/dists/riscos/!Run,feb $(APP_NAME)/!Run,feb
sed -i -e "s/WIMPSLOT/WimpSlot -min $$(($$(du -k $(EXECUTABLE) | cut -f1) + 32))K/g" $(APP_NAME)/!Run,feb
endif
ifeq ($(APP_NAME),$(BASE_APP_NAME))
cp ${srcdir}/dists/riscos/!Boot,feb $(APP_NAME)/!Boot,feb
cp ${srcdir}/dists/riscos/!Sprites,ff9 $(APP_NAME)/!Sprites,ff9
cp ${srcdir}/dists/riscos/!Sprites11,ff9 $(APP_NAME)/!Sprites11,ff9
cp ${srcdir}/dists/riscos/!SpritesA1,ff9 $(APP_NAME)/!SpritesA1,ff9
cp ${srcdir}/dists/riscos/!SpritesA2,ff9 $(APP_NAME)/!SpritesA2,ff9
else
cp ${srcdir}/dists/riscos/$(APP_NAME)/!Boot,feb $(APP_NAME)/!Boot,feb
cp ${srcdir}/dists/riscos/$(APP_NAME)/!Sprites,ff9 $(APP_NAME)/!Sprites,ff9
cp ${srcdir}/dists/riscos/$(APP_NAME)/!Sprites11,ff9 $(APP_NAME)/!Sprites11,ff9
endif
mkdir -p $(BASE_APP_NAME)/data
cp $(DIST_FILES_THEMES) $(BASE_APP_NAME)/data/
ifdef DIST_FILES_NETWORKING
cp $(DIST_FILES_NETWORKING) $(BASE_APP_NAME)/data/
endif
ifdef DIST_FILES_ENGINEDATA
cp $(DIST_FILES_ENGINEDATA) $(BASE_APP_NAME)/data/
endif
ifdef DIST_FILES_VKEYBD
cp $(DIST_FILES_VKEYBD) $(BASE_APP_NAME)/data/
endif
ifdef DYNAMIC_MODULES
mkdir -p $(APP_NAME)/plugins
cp $(PLUGINS) $(APP_NAME)/plugins/
endif
ifeq ($(APP_NAME),$(BASE_APP_NAME))
mkdir -p $(APP_NAME)/docs
ifdef TOKENIZE
$(TOKENIZE) ${srcdir}/dists/riscos/FindHelp,fd1 -out $(APP_NAME)/FindHelp,ffb
endif
ifdef DIST_FILES_MANUAL
ifneq ("$(wildcard $(DIST_FILES_MANUAL))","")
cp $(DIST_FILES_MANUAL) $(APP_NAME)/docs/ScummVM,adf
endif
endif
@$(foreach file, $(DIST_FILES_DOCS_plaintext) $(srcdir)/doc/QuickStart, echo ' ' ICONV ' ' $(APP_NAME)/docs/$(notdir $(file)),fff;iconv --to-code=$(ENCODING) $(file) > $(APP_NAME)/docs/$(notdir $(file)),fff;)
@$(foreach lang, $(DIST_FILES_DOCS_languages), mkdir -p $(APP_NAME)/docs/$(lang); $(foreach file, $(DIST_FILES_DOCS_$(lang)), echo ' ' ICONV ' ' $(APP_NAME)/docs/$(lang)/$(notdir $(file)),fff;iconv --from-code=UTF-8 --to-code=$(ENCODING) $(file) > $(APP_NAME)/docs/$(lang)/$(notdir $(file)),fff;))
endif
clean: riscosclean
riscosclean:
$(RM_REC) $(APP_NAME)
$(RM_REC) $(BASE_APP_NAME)
.PHONY: riscosdist riscosclean

View File

@@ -0,0 +1,48 @@
Welcome to Sailfish port of ScummVM.
# Building
First you need to download dependencies as we link statically with them:
``` shell
./sailfish-download.sh
```
You have to do this only once
Suppose that your SDK is in `$SDK_ROOT`
First you need to figure out your target config
``` shell
$SDK_ROOT/bin/sfdk engine exec sb2-config -l
```
``` text
SailfishOS-armv7hl
SailfishOS-i486-x86
```
Then run:
``` shell
$SDK_ROOT/bin/sfdk config --push target $TARGET
$SDK_ROOT/bin/sfdk build
```
And finally you need to sign them with your developer key:
``` shell
$SDK_ROOT/bin/sfdk engine exec -tt sb2 -t $TARGET rpmsign-external sign -k $KEY_PATH/regular_key.pem -c $KEY_PATH/regular_cert.pem RPMS/*.rpm
```
# Known issues
* Screen dimming and sleep aren't inhibited in game
* If you close ScummVM window on the panel ScummVM isn't closed and you
can't open it again
* When switching From Surface SDL to OpenGL renderer touchscreen coordinates
are garbled until restart
* make install doesn't install Sailfish-specific file. It's done in RPM spec

View File

@@ -0,0 +1,11 @@
--- a/libfaad/common.h 2024-10-06 01:41:33.334820363 +0300
+++ b/libfaad/common.h 2024-10-06 01:42:58.196852018 +0300
@@ -327,7 +327,7 @@
return i;
}
#endif /* HAVE_LRINTF */
- #elif (defined(__i386__) && defined(__GNUC__) && \
+ #elif (defined(__i386__) && 0 && defined(__GNUC__) && \
!defined(__CYGWIN__) && !defined(__MINGW32__))
#ifndef HAVE_LRINTF
#define HAS_LRINTF

View File

@@ -0,0 +1,233 @@
%if %{undefined outdir}
%define outdir out-sailfish.%{_arch}
%endif
%define freetype_version 2.13.3
%define flac_version 1.4.3
%define theora_version 1.1.1
%define jpeg_turbo_version 3.0.4
%define libmad_version 0.15.1b
%define libmpeg2_version 0.5.1
%define libfaad_version 2.8.8
%define giflib_version 5.2.2
%define fribidi_version 1.0.16
%define sdl2_version 2.30.7
%define vpx_version 1.14.1
#define engine_config --disable-all-engines --enable-engines=scumm --disable-tinygl
%define engine_config %{nil}
%define _rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
Name: org.scummvm.scummvm
Summary: ScummVM: Multi-game engine
Version: 0
Release: 1
Group: Qt/Qt
License: GPLv3
URL: https://scummvm.org
Source0: %{name}-%{version}.tar.bz2
BuildRequires: pkgconfig(sdl2)
BuildRequires: SDL2_net-devel
BuildRequires: pkgconfig(ogg)
BuildRequires: pkgconfig(vorbis)
BuildRequires: pkgconfig(libpng)
BuildRequires: pkgconfig(egl)
BuildRequires: pkgconfig(glesv2)
BuildRequires: cmake
BuildRequires: git
# libSDL deps
BuildRequires: pkgconfig(wayland-egl)
BuildRequires: pkgconfig(wayland-client)
BuildRequires: pkgconfig(wayland-cursor)
BuildRequires: pkgconfig(wayland-protocols)
BuildRequires: pkgconfig(wayland-scanner)
BuildRequires: pkgconfig(glesv1_cm)
BuildRequires: pkgconfig(xkbcommon)
BuildRequires: pkgconfig(libpulse-simple)
%description
ScummVM: Multi-game engine
%build
mkdir -p %{outdir}
mkdir -p %{outdir}/scummvm
mkdir -p %{outdir}/pkgconfig
if ! [ -d %{outdir}/freetype-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/freetype-%{freetype_version}.tar.xz
cd freetype-%{freetype_version}
./configure --prefix=$PWD/../freetype-install --disable-shared --enable-static
make %{?_smp_mflags}
make install
cd ../..
fi
if ! [ -d %{outdir}/flac-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/flac-%{flac_version}.tar.xz
cd flac-%{flac_version}
./configure --disable-shared --enable-static --disable-examples --disable-programs
make %{?_smp_mflags}
make DESTDIR=$PWD/../flac-install INSTALL_ROOT=$PWD/../flac-install install
cd ../..
fi
if ! [ -d %{outdir}/theora-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/libtheora-%{theora_version}.tar.xz
cd libtheora-%{theora_version}
./configure --disable-shared --enable-static --disable-examples --disable-programs
make %{?_smp_mflags}
make DESTDIR=$PWD/../theora-install INSTALL_ROOT=$PWD/../theora-install install
cd ../..
fi
if ! [ -d %{outdir}/jpeg-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/libjpeg-turbo-%{jpeg_turbo_version}.tar.gz
cd libjpeg-turbo-%{jpeg_turbo_version}
%cmake -DENABLE_SHARED=FALSE
make %{?_smp_mflags}
make DESTDIR=$PWD/../jpeg-install INSTALL_ROOT=$PWD/../jpeg-install install
cd ../..
fi
if ! [ -d %{outdir}/libmad-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/libmad-%{libmad_version}.tar.gz
cd libmad-%{libmad_version}
%if "%{_arch}" == "arm"
ASFLAGS=-marm CFLAGS="-O2 -marm" ./configure --disable-shared --enable-static --disable-examples --disable-programs CFLAGS="-O2 -marm" ASFLAGS=-marm
make CFLAGS="-O2 -marm" ASFLAGS=-marm %{?_smp_mflags}
%else
CFLAGS="-O2" ./configure --disable-shared --enable-static --disable-examples --disable-programs CFLAGS="-O2"
make CFLAGS="-O2" %{?_smp_mflags}
%endif
make DESTDIR=$PWD/../libmad-install INSTALL_ROOT=$PWD/../libmad-install install
cd ../..
fi
if ! [ -d %{outdir}/mpeg2-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/libmpeg2-%{libmpeg2_version}.tar.gz
cd libmpeg2-%{libmpeg2_version}
./configure --disable-shared --enable-static --disable-examples --disable-programs
make %{?_smp_mflags}
make DESTDIR=$PWD/../mpeg2-install INSTALL_ROOT=$PWD/../mpeg2-install install
cd ../..
fi
if ! [ -d %{outdir}/faad-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/faad2-%{libfaad_version}.tar.gz
cd faad2-%{libfaad_version}
echo "Applying patch faad-lrint.patch"
patch -p1 -i "../../faad-lrint.patch"
./configure --disable-shared --enable-static --disable-examples --disable-programs
make %{?_smp_mflags}
make DESTDIR=$PWD/../faad-install INSTALL_ROOT=$PWD/../faad-install install
cd ../..
fi
if ! [ -d %{outdir}/giflib-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/giflib-%{giflib_version}.tar.gz
cd giflib-%{giflib_version}
make %{?_smp_mflags} libgif.a
make DESTDIR=$PWD/../giflib-install INSTALL_ROOT=$PWD/../giflib-install install-include
install -d "$PWD/../giflib-install/usr/local/lib"
install -m 644 libgif.a "$PWD/../giflib-install/usr/local/lib/libgif.a"
cd ../..
fi
if ! [ -d %{outdir}/vpx-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/libvpx-%{vpx_version}.tar.gz
cd libvpx-%{vpx_version}
echo "Applying patch vpx-busybox.patch"
patch -p1 -i "../../vpx-busybox.patch"
./configure --disable-shared --enable-static --disable-examples --target=generic-gnu
make %{?_smp_mflags}
make DESTDIR=$PWD/../vpx-install INSTALL_ROOT=$PWD/../vpx-install install
cd ../..
fi
if ! [ -d %{outdir}/fribidi-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/fribidi-%{fribidi_version}.tar.xz
cd fribidi-%{fribidi_version}
./configure --disable-shared --enable-static --prefix=$PWD/../fribidi-install
make %{?_smp_mflags}
make install
cd ../..
fi
if ! [ -d %{outdir}/sdl-install ]; then
cd %{outdir}
tar xvf ../rpmdeps/SDL2-%{sdl2_version}.tar.gz
cd SDL2-%{sdl2_version}
for x in ../../sdl-patches/*.patch; do
echo "Applying patch $x"
patch -p1 -i "$x"
done
cd ..
cmake \
-Bsdl-build \
-DSDL_PULSEAUDIO=ON \
-DSDL_RPATH=OFF \
-DSDL_STATIC=ON \
-DSDL_SHARED=OFF \
-DSDL_WAYLAND=ON \
-DSDL_X11=OFF \
-DSDL_DBUS=ON \
-DSDL_WAYLAND_LIBDECOR=OFF \
-DSDL_WAYLAND_QT_TOUCH=OFF \
SDL2-%{sdl2_version}
make -C sdl-build %{?_smp_mflags}
make -C sdl-build install DESTDIR=$PWD/sdl-install INSTALL_ROOT=$PWD/sdl-install
cd ..
fi
sed "s@Libs: .*@Libs: $PWD/%{outdir}/freetype-install/lib/libfreetype.a@g" < %{outdir}/freetype-install/lib/pkgconfig/freetype2.pc > %{outdir}/pkgconfig/freetype2.pc
sed "s@Libs: .*@Libs: $PWD/%{outdir}/fribidi-install/lib/libfribidi.a@g" < %{outdir}/fribidi-install/lib/pkgconfig/fribidi.pc > %{outdir}/pkgconfig/fribidi.pc
export PKG_CONFIG_PATH=$PWD/%{outdir}/pkgconfig:$PKG_CONFIG_PATH
export PKG_CONFIG_LIBDIR=$PWD/%{outdir}/pkgconfig:$PKG_CONFIG_LIBDIR
cd %{outdir}/scummvm;
../../../../../../configure --host=sailfish \
--with-jpeg-prefix=../jpeg-install/usr \
--with-mad-prefix=../libmad-install/usr/local \
--with-flac-prefix=../flac-install/usr/local \
--with-theoradec-prefix=../theora-install/usr/local \
--with-mpeg2-prefix=../mpeg2-install/usr/local \
--with-faad-prefix=../faad-install/usr/local \
--with-gif-prefix=../giflib-install/usr/local \
--enable-fribidi --with-fribidi-prefix=../fribidi-install \
--enable-vpx --with-vpx-prefix=../vpx-install/usr/local \
--with-sdl-prefix=../sdl-install/usr/local --enable-static \
%{engine_config}
cd ../..
%{__make} -C %{outdir}/scummvm %{_make_output_sync} %{?_smp_mflags}
%install
rm -rf %{buildroot}/*
%{__make} -C %{outdir}/scummvm DESTDIR=%{buildroot} INSTALL_ROOT=%{buildroot} install
# TODO: Move this stuff into make
mkdir -p %{buildroot}/usr/share/applications
mkdir -p %{buildroot}/usr/share/icons/hicolor/86x86/apps
mkdir -p %{buildroot}/usr/share/icons/hicolor/108x108/apps
mkdir -p %{buildroot}/usr/share/icons/hicolor/128x128/apps
mkdir -p %{buildroot}/usr/share/icons/hicolor/172x172/apps
cp ../../../../dists/sailfish/org.scummvm.scummvm.desktop %{buildroot}/usr/share/applications/org.scummvm.scummvm.desktop
cp ../../../../dists/sailfish/86x86.png %{buildroot}/usr/share/icons/hicolor/86x86/apps/org.scummvm.scummvm.png
cp ../../../../dists/sailfish/108x108.png %{buildroot}/usr/share/icons/hicolor/108x108/apps/org.scummvm.scummvm.png
cp ../../../../dists/sailfish/128x128.png %{buildroot}/usr/share/icons/hicolor/128x128/apps/org.scummvm.scummvm.png
cp ../../../../dists/sailfish/172x172.png %{buildroot}/usr/share/icons/hicolor/172x172/apps/org.scummvm.scummvm.png
%files
%defattr(755,root,root,-)
%{_bindir}/org.scummvm.scummvm
%defattr(644,root,root,-)
%{_datadir}/org.scummvm.scummvm/applications/%{name}.desktop
%{_datadir}/org.scummvm.scummvm/doc/scummvm/*
%{_datadir}/org.scummvm.scummvm/icons/hicolor/scalable/apps/org.scummvm.scummvm.svg
%{_datadir}/org.scummvm.scummvm/man/man6/scummvm.6
%{_datadir}/org.scummvm.scummvm/metainfo/org.scummvm.scummvm.metainfo.xml
%{_datadir}/org.scummvm.scummvm/pixmaps/org.scummvm.scummvm.xpm
%{_datadir}/org.scummvm.scummvm/scummvm/*
%{_datadir}/applications/org.scummvm.scummvm.desktop
%{_datadir}/icons/hicolor/108x108/apps/org.scummvm.scummvm.png
%{_datadir}/icons/hicolor/128x128/apps/org.scummvm.scummvm.png
%{_datadir}/icons/hicolor/172x172/apps/org.scummvm.scummvm.png
%{_datadir}/icons/hicolor/86x86/apps/org.scummvm.scummvm.png

View File

@@ -0,0 +1,11 @@
wget -O rpmdeps/freetype-2.13.3.tar.xz https://download.savannah.gnu.org/releases/freetype/freetype-2.13.3.tar.xz
wget -O rpmdeps/flac-1.4.3.tar.xz https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.4.3.tar.xz
wget -O rpmdeps/libjpeg-turbo-3.0.4.tar.gz https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.0.4/libjpeg-turbo-3.0.4.tar.gz
wget -O rpmdeps/libmad-0.15.1b.tar.gz https://downloads.sourceforge.net/mad/libmad-0.15.1b.tar.gz
wget -O rpmdeps/libmpeg2-0.5.1.tar.gz https://libmpeg2.sourceforge.net/files/libmpeg2-0.5.1.tar.gz
wget -O rpmdeps/faad2-2.8.8.tar.gz https://sourceforge.net/projects/faac/files/faad2-src/faad2-2.8.0/faad2-2.8.8.tar.gz
wget -O rpmdeps/giflib-5.2.2.tar.gz https://sourceforge.net/projects/giflib/files/giflib-5.2.2.tar.gz
wget -O rpmdeps/fribidi-1.0.16.tar.xz https://github.com/fribidi/fribidi/releases/download/v1.0.16/fribidi-1.0.16.tar.xz
wget -O rpmdeps/libtheora-1.1.1.tar.xz https://ftp.osuosl.org/pub/xiph/releases/theora/libtheora-1.1.1.tar.xz
wget -O rpmdeps/SDL2-2.30.7.tar.gz https://github.com/libsdl-org/SDL/releases/download/release-2.30.7/SDL2-2.30.7.tar.gz
wget -O rpmdeps/libvpx-1.14.1.tar.gz https://github.com/webmproject/libvpx/archive/refs/tags/v1.14.1.tar.gz

View File

@@ -0,0 +1,44 @@
/* 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 "backends/platform/sdl/sailfish/sailfish.h"
#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
int main(int argc, char* argv[]) {
g_system = new OSystem_SDL_Sailfish();
assert(g_system);
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
return res;
}

View File

@@ -0,0 +1,46 @@
/* 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 "backends/graphics/sdl/sdl-graphics.h"
#include "backends/platform/sdl/sailfish/sailfish-window.h"
/* Setting window size at anything other than full screen is unexpected
and results in a rectangle without any decorations. So always create
full screen window.
*/
bool SdlWindow_Sailfish::createOrUpdateWindow(int, int, uint32 flags) {
SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(0,&dm);
int width, height;
/* SDL assumes that composer takes care of rotation and so switches
sides in landscape rotation. But Lipstick doesn't handle rotation.
So put them back in correct order.
*/
if (dm.w < dm.h) {
width = dm.w;
height = dm.h;
} else {
width = dm.h;
height = dm.w;
}
return SdlWindow::createOrUpdateWindow(width, height, flags);
}

View File

@@ -0,0 +1,32 @@
/* 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/>.
*
*/
#ifndef BACKENDS_PLATFORM_SDL_MACOSX_MACOSX_WINDOW_H
#define BACKENDS_PLATFORM_SDL_MACOSX_MACOSX_WINDOW_H
#include "backends/platform/sdl/sdl-window.h"
class SdlWindow_Sailfish final : public SdlWindow {
public:
bool createOrUpdateWindow(int, int, uint32 flags) override;
};
#endif

View File

@@ -0,0 +1,165 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "backends/platform/sdl/sailfish/sailfish.h"
#include "backends/platform/sdl/sailfish/sailfish-window.h"
#include "backends/fs/posix/posix-fs-factory.h"
#include "backends/fs/posix/posix-fs.h"
#include "backends/saves/default/default-saves.h"
#include "backends/keymapper/action.h"
#include "backends/keymapper/keymapper-defaults.h"
#include "backends/keymapper/hardware-input.h"
#include "backends/keymapper/keymap.h"
#include "backends/keymapper/keymapper.h"
#define ORG_NAME "org.scummvm"
#define APP_NAME "scummvm"
void OSystem_SDL_Sailfish::init() {
setenv("SDL_VIDEO_WAYLAND_WMCLASS", "org.scummvm.scummvm", 1);
// Initialze File System Factory
_fsFactory = new POSIXFilesystemFactory();
_window = new SdlWindow_Sailfish();
_isAuroraOS = false;
char *line = nullptr;
size_t n = 0;
FILE *os_release = fopen("/etc/os-release", "r");
if (os_release) {
while (getline(&line, &n, os_release) > 0) {
if (strncmp(line, "ID=auroraos", sizeof("ID=auroraos") - 1) == 0) {
_isAuroraOS = true;
}
}
free(line);
fclose(os_release);
}
// Invoke parent implementation of this method
OSystem_SDL::init();
}
Common::String OSystem_SDL_Sailfish::getAppSuffix() {
if (_isAuroraOS) {
return ORG_NAME "/" APP_NAME;
} else {
return ORG_NAME "." APP_NAME;
}
}
void OSystem_SDL_Sailfish::initBackend() {
if (!ConfMan.hasKey("rotation_mode")) {
ConfMan.setInt("rotation_mode", 90);
}
if (!ConfMan.hasKey("savepath")) {
ConfMan.setPath("savepath", getDefaultSavePath());
}
// Create the savefile manager
if (_savefileManager == nullptr) {
_savefileManager = new DefaultSaveFileManager(getDefaultSavePath());
}
OSystem_SDL::initBackend();
}
Common::Path OSystem_SDL_Sailfish::getDefaultSavePath() {
Common::String saveRelPath;
const char *prefix = getenv("HOME");
if (prefix == nullptr) {
return Common::Path();
}
saveRelPath = ".local/share/" + getAppSuffix() + "/saves";
if (!Posix::assureDirectoryExists(saveRelPath, prefix)) {
return Common::Path();
}
Common::Path savePath(prefix);
savePath.joinInPlace(saveRelPath);
return savePath;
}
Common::Path OSystem_SDL_Sailfish::getDefaultConfigFileName() {
Common::String configPath;
const char *prefix = getenv("HOME");
if (prefix == nullptr) {
return Common::Path();
}
configPath = ".local/share/" + getAppSuffix();
if (!Posix::assureDirectoryExists(configPath, prefix)) {
return Common::Path();
}
Common::Path configFile(prefix);
configFile.joinInPlace(configPath);
configFile.joinInPlace("scummvm.ini");
return configFile;
}
Common::Path OSystem_SDL_Sailfish::getDefaultLogFileName() {
Common::String logFile;
const char *prefix = getenv("HOME");
if (prefix == nullptr) {
return Common::Path();
}
logFile = ".cache/" + getAppSuffix() + "/logs";
if (!Posix::assureDirectoryExists(logFile, prefix)) {
return Common::Path();
}
Common::Path logPath(prefix);
logPath.joinInPlace(logFile);
logPath.joinInPlace("scummvm.log");
return logPath;
}
bool OSystem_SDL_Sailfish::hasFeature(Feature f) {
switch (f) {
case kFeatureFullscreenMode:
return false;
case kFeatureTouchpadMode:
return true;
default:
return OSystem_SDL::hasFeature(f);
}
}

View File

@@ -0,0 +1,44 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_SAILFISH_H
#define PLATFORM_SDL_SAILFISH_H
#include "backends/platform/sdl/sdl.h"
class OSystem_SDL_Sailfish : public OSystem_SDL {
public:
void init() override;
void initBackend() override;
bool hasFeature(Feature f) override;
protected:
Common::Path getDefaultConfigFileName() override;
Common::Path getDefaultLogFileName() override;
private:
Common::Path getDefaultSavePath();
Common::String getAppSuffix();
bool _isAuroraOS = false;
};
#endif

View File

@@ -0,0 +1,288 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matti=20Lehtim=C3=A4ki?= <matti.lehtimaki@jolla.com>
Date: Wed, 20 Apr 2022 18:03:42 +0300
Subject: [PATCH] wayland: Bring back wl_shell support
---
include/SDL_syswm.h | 2 +-
src/video/wayland/SDL_waylanddyn.h | 2 +
src/video/wayland/SDL_waylandevents.c | 8 +++
src/video/wayland/SDL_waylandsym.h | 2 +
src/video/wayland/SDL_waylandvideo.c | 7 ++
src/video/wayland/SDL_waylandvideo.h | 1 +
src/video/wayland/SDL_waylandwindow.c | 95 +++++++++++++++++++++++++++
src/video/wayland/SDL_waylandwindow.h | 1 +
8 files changed, 117 insertions(+), 1 deletion(-)
diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h
index 7b8bd6ef996571bbba2e5f1e139a0c9292c88146..671a26ee945bdac99de9f07b57aef9cc893f4cec 100644
--- a/include/SDL_syswm.h
+++ b/include/SDL_syswm.h
@@ -294,7 +294,7 @@ struct SDL_SysWMinfo
{
struct wl_display *display; /**< Wayland display */
struct wl_surface *surface; /**< Wayland surface */
- void *shell_surface; /**< DEPRECATED Wayland shell_surface (window manager handle) */
+ struct wl_shell_surface *shell_surface; /**< DEPRECATED Wayland shell_surface (window manager handle) */
struct wl_egl_window *egl_window; /**< Wayland EGL window (native window) */
struct xdg_surface *xdg_surface; /**< Wayland xdg surface (window manager handle) */
struct xdg_toplevel *xdg_toplevel; /**< Wayland xdg toplevel role */
diff --git a/src/video/wayland/SDL_waylanddyn.h b/src/video/wayland/SDL_waylanddyn.h
index 6feb343912b15a6a9360a11b66a08c0c4e36f882..2c93149cd2dcbff5a69c20606c028aa13905dced 100644
--- a/src/video/wayland/SDL_waylanddyn.h
+++ b/src/video/wayland/SDL_waylanddyn.h
@@ -111,11 +111,13 @@ void SDL_WAYLAND_UnloadSymbols(void);
#define wl_shm_pool_interface (*WAYLAND_wl_shm_pool_interface)
#define wl_buffer_interface (*WAYLAND_wl_buffer_interface)
#define wl_registry_interface (*WAYLAND_wl_registry_interface)
+#define wl_shell_surface_interface (*WAYLAND_wl_shell_surface_interface)
#define wl_region_interface (*WAYLAND_wl_region_interface)
#define wl_pointer_interface (*WAYLAND_wl_pointer_interface)
#define wl_keyboard_interface (*WAYLAND_wl_keyboard_interface)
#define wl_compositor_interface (*WAYLAND_wl_compositor_interface)
#define wl_output_interface (*WAYLAND_wl_output_interface)
+#define wl_shell_interface (*WAYLAND_wl_shell_interface)
#define wl_shm_interface (*WAYLAND_wl_shm_interface)
#define wl_data_device_interface (*WAYLAND_wl_data_device_interface)
#define wl_data_offer_interface (*WAYLAND_wl_data_offer_interface)
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index a8382812ab149c4377441d46a693f736f5430cad..45d679abdafb94708e478745d4f1db57922c37b7 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -518,6 +518,10 @@ static SDL_bool ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
input->seat,
serial);
}
+ } else {
+ if (window_data->shell_surface.wl) {
+ wl_shell_surface_move(window_data->shell_surface.wl, input->seat, serial);
+ }
}
return SDL_TRUE;
@@ -543,6 +547,10 @@ static SDL_bool ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
serial,
directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
}
+ } else {
+ if (window_data->shell_surface.wl) {
+ wl_shell_surface_resize(window_data->shell_surface.wl, input->seat, serial, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+ }
}
return SDL_TRUE;
diff --git a/src/video/wayland/SDL_waylandsym.h b/src/video/wayland/SDL_waylandsym.h
index 1b02b01c6691bd2df30508ab88bbd990586594d0..27ff34a31a77c970300790697204594d24e11a1f 100644
--- a/src/video/wayland/SDL_waylandsym.h
+++ b/src/video/wayland/SDL_waylandsym.h
@@ -101,11 +101,13 @@ SDL_WAYLAND_INTERFACE(wl_surface_interface)
SDL_WAYLAND_INTERFACE(wl_shm_pool_interface)
SDL_WAYLAND_INTERFACE(wl_buffer_interface)
SDL_WAYLAND_INTERFACE(wl_registry_interface)
+SDL_WAYLAND_INTERFACE(wl_shell_surface_interface)
SDL_WAYLAND_INTERFACE(wl_region_interface)
SDL_WAYLAND_INTERFACE(wl_pointer_interface)
SDL_WAYLAND_INTERFACE(wl_keyboard_interface)
SDL_WAYLAND_INTERFACE(wl_compositor_interface)
SDL_WAYLAND_INTERFACE(wl_output_interface)
+SDL_WAYLAND_INTERFACE(wl_shell_interface)
SDL_WAYLAND_INTERFACE(wl_shm_interface)
SDL_WAYLAND_INTERFACE(wl_data_device_interface)
SDL_WAYLAND_INTERFACE(wl_data_source_interface)
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 2cae471792cd692129f193fac2100d7d98ab6705..70e9d7306a8fcc60a4b8b1a9289c18f88a8de990 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -846,6 +846,8 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
} else if (SDL_strcmp(interface, "xdg_wm_base") == 0) {
d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, SDL_min(version, 3));
xdg_wm_base_add_listener(d->shell.xdg, &shell_listener_xdg, NULL);
+ } else if (SDL_strcmp(interface, "wl_shell") == 0) {
+ d->shell.wl = wl_registry_bind(d->registry, id, &wl_shell_interface, 1);
} else if (SDL_strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
} else if (SDL_strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) {
@@ -1097,6 +1099,11 @@ static void Wayland_VideoCleanup(_THIS)
data->shm = NULL;
}
+ if (data->shell.wl) {
+ wl_shell_destroy(data->shell.wl);
+ data->shell.wl = NULL;
+ }
+
if (data->shell.xdg) {
xdg_wm_base_destroy(data->shell.xdg);
data->shell.xdg = NULL;
diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h
index b7b3348c6d4d9285971d5a2416f7d123f303c7f8..e57ab2bd21a3064c257d704b4912c22d5c49074e 100644
--- a/src/video/wayland/SDL_waylandvideo.h
+++ b/src/video/wayland/SDL_waylandvideo.h
@@ -64,6 +64,7 @@ typedef struct
struct
{
struct xdg_wm_base *xdg;
+ struct wl_shell *wl;
#ifdef HAVE_LIBDECOR_H
struct libdecor *libdecor;
#endif
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 08df3638c2e795ecdf4cd5f4972bd5d4f866653d..4cb20afbda9aef1edad59b3cf2bd73a7f6e3d289 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -446,6 +446,20 @@ static void SetFullscreen(SDL_Window *window, struct wl_output *output)
} else {
xdg_toplevel_unset_fullscreen(wind->shell_surface.xdg.roleobj.toplevel);
}
+ } else {
+ if (wind->shell_surface.wl == NULL) {
+ return; /* Can't do anything yet, wait for ShowWindow */
+ }
+
+ wl_surface_commit(wind->surface);
+
+ if (output) {
+ wl_shell_surface_set_fullscreen(wind->shell_surface.wl,
+ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
+ 0, output);
+ } else {
+ wl_shell_surface_set_toplevel(wind->shell_surface.wl);
+ }
}
}
@@ -541,6 +555,62 @@ static const struct wl_callback_listener gles_swap_frame_listener = {
static void Wayland_HandleResize(SDL_Window *window, int width, int height, float scale);
+/* On modern desktops, we probably will use the xdg-shell protocol instead
+ of wl_shell, but wl_shell might be useful on older Wayland installs that
+ don't have the newer protocol, or embedded things that don't have a full
+ window manager. */
+
+static void
+handle_ping_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface,
+ uint32_t serial)
+{
+ wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void
+handle_configure_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface,
+ uint32_t edges, int32_t width, int32_t height)
+{
+ SDL_WindowData *wind = (SDL_WindowData *)data;
+ SDL_Window *window = wind->sdlwindow;
+
+ /* wl_shell_surface spec states that this is a suggestion.
+ Ignore if less than or greater than max/min size. */
+
+ if (width == 0 || height == 0) {
+ return;
+ }
+
+ if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
+ if ((window->flags & SDL_WINDOW_RESIZABLE)) {
+ if (window->max_w > 0) {
+ width = SDL_min(width, window->max_w);
+ }
+ width = SDL_max(width, window->min_w);
+
+ if (window->max_h > 0) {
+ height = SDL_min(height, window->max_h);
+ }
+ height = SDL_max(height, window->min_h);
+ } else {
+ return;
+ }
+ }
+
+ Wayland_HandleResize(window, width, height, wind->scale_factor);
+}
+
+static void
+handle_popup_done_wl_shell_surface(void *data, struct wl_shell_surface *shell_surface)
+{
+}
+
+static const struct wl_shell_surface_listener shell_surface_listener_wl = {
+ handle_ping_wl_shell_surface,
+ handle_configure_wl_shell_surface,
+ handle_popup_done_wl_shell_surface
+};
+
static void handle_configure_xdg_shell_surface(void *data, struct xdg_surface *xdg, uint32_t serial)
{
SDL_WindowData *wind = (SDL_WindowData *)data;
@@ -1374,6 +1444,11 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
}
+ } else {
+ data->shell_surface.wl = wl_shell_get_shell_surface(c->shell.wl, data->surface);
+ wl_shell_surface_set_class(data->shell_surface.wl, c->classname);
+ wl_shell_surface_set_user_data(data->shell_surface.wl, data);
+ wl_shell_surface_add_listener(data->shell_surface.wl, &shell_surface_listener_wl, data);
}
/* Restore state that was set prior to this call */
@@ -1549,6 +1624,11 @@ void Wayland_HideWindow(_THIS, SDL_Window *window)
xdg_surface_destroy(wind->shell_surface.xdg.surface);
wind->shell_surface.xdg.surface = NULL;
}
+ } else {
+ if (wind->shell_surface.wl) {
+ wl_shell_surface_destroy(wind->shell_surface.wl);
+ wind->shell_surface.wl = NULL;
+ }
}
/*
@@ -1829,6 +1909,11 @@ void Wayland_RestoreWindow(_THIS, SDL_Window *window)
return; /* Can't do anything yet, wait for ShowWindow */
}
xdg_toplevel_unset_maximized(wind->shell_surface.xdg.roleobj.toplevel);
+ } else {
+ if (wind->shell_surface.wl == NULL) {
+ return; /* Can't do anything yet, wait for ShowWindow */
+ }
+ wl_shell_surface_set_toplevel(wind->shell_surface.wl);
}
WAYLAND_wl_display_roundtrip(viddata->display);
@@ -1908,6 +1993,11 @@ void Wayland_MaximizeWindow(_THIS, SDL_Window *window)
return; /* Can't do anything yet, wait for ShowWindow */
}
xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel);
+ } else {
+ if (wind->shell_surface.wl == NULL) {
+ return; /* Can't do anything yet, wait for ShowWindow */
+ }
+ wl_shell_surface_set_maximized(wind->shell_surface.wl, NULL);
}
WAYLAND_wl_display_roundtrip(viddata->display);
@@ -2209,6 +2299,11 @@ void Wayland_SetWindowTitle(_THIS, SDL_Window *window)
return; /* Can't do anything yet, wait for ShowWindow */
}
xdg_toplevel_set_title(wind->shell_surface.xdg.roleobj.toplevel, title);
+ } else {
+ if (wind->shell_surface.wl == NULL) {
+ return; /* Can'd do anything yet, wait for ShowWindow */
+ }
+ wl_shell_surface_set_title(wind->shell_surface.wl, title);
}
WAYLAND_wl_display_flush(viddata->display);
diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h
index 36600a4d2783e5205d0e1d2faf8422b54e1f7848..0951126949879d863cde175684a3605367428824 100644
--- a/src/video/wayland/SDL_waylandwindow.h
+++ b/src/video/wayland/SDL_waylandwindow.h
@@ -67,6 +67,7 @@ typedef struct
} roleobj;
SDL_bool initial_configure_seen;
} xdg;
+ struct wl_shell_surface *wl;
} shell_surface;
enum
{

View File

@@ -0,0 +1,49 @@
commit 7dd1cdd4656e0bdbf0f851392f644b2a05c32d64
Author: Vladimir Serbinenko <phcoder@gmail.com>
Date: Thu Sep 26 17:19:14 2024 +0300
Handle wayland touch cancel message
Suppose host has some three-finger gesture. Then we get the following sequence
of events:
DOWN-DOWN-DOWN-MOTION-CANCEL
Note that there is no UP in this sequence. So if we don't handle CANCEL then
we end up thinking that fingers are still touching the screen. Ideally we
should inform the application that cancel has happened as not to trigger
spurious taps but still this is way better than being stuck with phantom
finger touch.
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 65838f480..236dc3232 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -932,6 +932,28 @@ static void touch_handler_frame(void *data, struct wl_touch *touch)
static void touch_handler_cancel(void *data, struct wl_touch *touch)
{
+ struct SDL_WaylandTouchPoint *tp;
+ while ((tp = touch_points.head)) {
+ wl_fixed_t fx = 0, fy = 0;
+ struct wl_surface *surface = NULL;
+ int id = tp->id;
+
+ touch_del(id, &fx, &fy, &surface);
+
+ if (surface) {
+ SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(surface);
+
+ if (window_data) {
+ const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
+ const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
+ const float x = dblx / window_data->sdlwindow->w;
+ const float y = dbly / window_data->sdlwindow->h;
+
+ SDL_SendTouch((SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id,
+ window_data->sdlwindow, SDL_FALSE, x, y, 1.0f);
+ }
+ }
+ }
}
static const struct wl_touch_listener touch_listener = {

View File

@@ -0,0 +1,12 @@
--- a/sdl2-config.in 2024-10-06 01:45:09.683556034 +0300
+++ b/sdl2-config.in 2024-10-06 01:56:47.497325450 +0300
@@ -53,8 +53,8 @@
@ENABLE_SHARED_TRUE@ ;;
@ENABLE_STATIC_TRUE@@ENABLE_SHARED_TRUE@ --static-libs)
@ENABLE_STATIC_TRUE@@ENABLE_SHARED_FALSE@ --libs|--static-libs)
-@ENABLE_STATIC_TRUE@ sdl_static_libs=$(echo "@SDL_LIBS@ @SDL_STATIC_LIBS@" | sed -E "s#-lSDL2[ $]#$libdir/libSDL2.a #g")
+@ENABLE_STATIC_TRUE@ sdl_static_libs=$(echo "@SDL_LIBS@ @SDL_STATIC_LIBS@" | sed "s#-lSDL2[ $]#$libdir/libSDL2.a #g")
@ENABLE_STATIC_TRUE@ echo -L@libdir@ $sdl_static_libs
@ENABLE_STATIC_TRUE@ ;;
*)
echo "${usage}" 1>&2

View File

@@ -0,0 +1,13 @@
--- a/configure 2024-05-29 23:00:23.000000000 +0300
+++ b/configure 2024-10-07 01:08:17.028334535 +0300
@@ -187,10 +187,6 @@
[ -f "${source_path}/${t}.mk" ] && enable_feature ${t}
done
-if ! diff --version >/dev/null; then
- die "diff missing: Try installing diffutils via your package manager."
-fi
-
if ! perl --version >/dev/null; then
die "Perl is required to build"
fi

View File

@@ -0,0 +1,382 @@
/* 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/>.
*
*/
#ifndef BACKEND_SDL_SYS_H
#define BACKEND_SDL_SYS_H
// The purpose of this header is to include the SDL headers in a uniform
// fashion.
// Moreover, it contains a workaround for the fact that SDL_rwops.h uses
// a FILE pointer in one place, which conflicts with common/forbidden.h.
// The SDL 1.3 headers also include strings.h
#include "common/scummsys.h"
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_FILE)
#undef FILE
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcasecmp)
#undef strcasecmp
#define strcasecmp FAKE_strcasecmp
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strncasecmp)
#undef strncasecmp
#define strncasecmp FAKE_strncasecmp
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_exit)
#undef exit
#define exit FAKE_exit
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_abort)
#undef abort
#define abort FAKE_abort
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_system)
#undef system
#define system FAKE_system
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_mkdir)
#undef mkdir
#define mkdir FAKE_mkdir
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcpy)
#undef strcpy
#define strcpy FAKE_strcpy
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcat)
#undef strcat
#define strcat FAKE_strcat
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_vsprintf)
#undef vsprintf
#define vsprintf FAKE_vsprintf
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_sprintf)
#undef sprintf
#define sprintf FAKE_sprintf
#endif
// Fix compilation with MacPorts SDL 2
// It needs various (usually forbidden) symbols from time.h
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_time_h
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_asctime)
#undef asctime
#define asctime FAKE_asctime
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_clock)
#undef clock
#define clock FAKE_clock
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_ctime)
#undef ctime
#define ctime FAKE_ctime
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_difftime)
#undef difftime
#define difftime FAKE_difftime
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_getdate)
#undef getdate
#define getdate FAKE_getdate
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_gmtime)
#undef gmtime
#define gmtime FAKE_gmtime
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_localtime)
#undef localtime
#define localtime FAKE_localtime
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_mktime)
#undef mktime
#define mktime FAKE_mktime
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_time)
#undef time
#define time FAKE_time
#endif
#endif // FORBIDDEN_SYMBOL_EXCEPTION_time_h
// Fix compilation on non-x86 architectures
// It needs various (usually forbidden) symbols from unistd.h
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_chdir)
#undef chdir
#define chdir FAKE_chdir
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_getcwd)
#undef getcwd
#define getcwd FAKE_getcwd
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_getwd)
#undef getwd
#define getwd FAKE_getwd
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_unlink)
#undef unlink
#define unlink FAKE_unlink
#endif
#endif // FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
// HACK: SDL might include windows.h which defines its own ARRAYSIZE.
// However, we want to use the version from common/util.h. Thus, we make sure
// that we actually have this definition after including the SDL headers.
#if defined(ARRAYSIZE) && defined(COMMON_UTIL_H)
#define HACK_REDEFINE_ARRAYSIZE
#undef ARRAYSIZE
#endif
// HACK to fix compilation with SDL 2.0 in MSVC.
// In SDL 2.0, intrin.h is now included in SDL_cpuinfo.h, which includes
// setjmp.h. SDL_cpuinfo.h is included from SDL.h and SDL_syswm.h.
// Thus, we remove the exceptions for setjmp and longjmp before these two
// includes.
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && defined(_MSC_VER) && defined(USE_SDL2)
// We unset any fake definitions of setjmp/longjmp here
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_setjmp
#undef setjmp
#endif
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_longjmp
#undef longjmp
#endif
#endif
#ifdef USE_SDL3
#include <SDL3/SDL.h>
#else
#include <SDL.h>
#endif
// Ignore warnings from system headers pulled by SDL
#pragma warning(push)
#pragma warning(disable:4121) // alignment of a member was sensitive to packing
#if !SDL_VERSION_ATLEAST(3, 0, 0)
#include <SDL_syswm.h>
#endif
#pragma warning(pop)
// Restore the forbidden exceptions from the hack above
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && defined(_MSC_VER)
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_setjmp
#undef setjmp
#define setjmp(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_longjmp
#undef longjmp
#define longjmp(a,b) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#endif
// SDL_syswm.h will include windows.h on Win32. We need to undefine its
// ARRAYSIZE definition because we supply our own.
#undef ARRAYSIZE
#ifdef HACK_REDEFINE_ARRAYSIZE
#undef HACK_REDEFINE_ARRAYSIZE
#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
#endif
// In a moment of brilliance Xlib.h included by SDL_syswm.h #defines the
// following names. In a moment of mental breakdown, which occurred upon
// gazing at Xlib.h, LordHoto decided to undefine them to prevent havoc.
#ifdef Status
#undef Status
#endif
#ifdef Bool
#undef Bool
#endif
#ifdef True
#undef True
#endif
#ifdef False
#undef False
#endif
#ifdef Complex
#undef Complex
#endif
// Finally forbid FILE again (if it was forbidden to start with)
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_FILE)
#undef FILE
#define FILE FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcasecmp)
#undef strcasecmp
#define strcasecmp FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strncasecmp)
#undef strncasecmp
#define strncasecmp FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_exit)
#undef exit
#define exit(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_abort)
#undef abort
#define abort() FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_system)
#undef system
#define system(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_mkdir)
#undef mkdir
#define mkdir(a,b) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcpy)
#undef strcpy
#define strcpy(a,b) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcat)
#undef strcat
#define strcat(a,b) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_vsprintf)
#undef vsprintf
#define vsprintf(a,b,c) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_sprintf)
#undef sprintf
#define sprintf(a,b,...) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
// re-forbid all those time.h symbols again (if they were forbidden)
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_time_h
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_asctime)
#undef asctime
#define asctime(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_clock)
#undef clock
#define clock() FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_ctime)
#undef ctime
#define ctime(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_difftime)
#undef difftime
#define difftime(a,b) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_getdate)
#undef getdate
#define getdate(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_gmtime)
#undef gmtime
#define gmtime(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_localtime)
#undef localtime
#define localtime(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_mktime)
#undef mktime
#define mktime(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_time)
#undef time
#define time(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#endif // FORBIDDEN_SYMBOL_EXCEPTION_time_h
// re-forbid all those unistd.h symbols again (if they were forbidden)
#ifndef FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_chdir)
#undef chdir
#define chdir(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_getcwd)
#undef getcwd
#define getcwd(a,b) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_getwd)
#undef getwd
#define getwd(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_unlink)
#undef unlink
#define unlink(a) FORBIDDEN_look_at_common_forbidden_h_for_more_info SYMBOL !%*
#endif
#endif // FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
#endif

View File

@@ -0,0 +1,613 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/platform/sdl/sdl-window.h"
#include "backends/platform/sdl/sdl.h"
#include "common/textconsole.h"
#include "common/util.h"
#include "common/config-manager.h"
#include "icons/scummvm.xpm"
#if SDL_VERSION_ATLEAST(3, 0, 0)
static const uint32 fullscreenMask = SDL_WINDOW_FULLSCREEN;
#elif SDL_VERSION_ATLEAST(2, 0, 0)
static const uint32 fullscreenMask = SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN;
#endif
SdlWindow::SdlWindow() :
#if SDL_VERSION_ATLEAST(2, 0, 0)
_window(nullptr), _windowCaption("ScummVM"),
_lastFlags(0), _lastX(SDL_WINDOWPOS_UNDEFINED), _lastY(SDL_WINDOWPOS_UNDEFINED),
#endif
_inputGrabState(false), _inputLockState(false),
_resizable(true)
{
memset(&grabRect, 0, sizeof(grabRect));
#if SDL_VERSION_ATLEAST(2, 0, 0)
#elif SDL_VERSION_ATLEAST(1, 2, 10)
// Query the desktop resolution. We simply hope nothing tried to change
// the resolution so far.
const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
if (videoInfo && videoInfo->current_w > 0 && videoInfo->current_h > 0) {
_desktopRes = Common::Rect(videoInfo->current_w, videoInfo->current_h);
}
#elif defined(MAEMO)
// All supported Maemo devices have a display resolution of 800x480
_desktopRes = Common::Rect(800, 480);
#elif defined(KOLIBRIOS)
// TODO: Use kolibriOS call to determine this.
_desktopRes = Common::Rect(640, 480);
#else
#error Unable to detect screen resolution
#endif
}
SdlWindow::~SdlWindow() {
#if SDL_VERSION_ATLEAST(2, 0, 0)
destroyWindow();
#endif
}
void SdlWindow::setupIcon() {
#ifndef __MORPHOS__
int x, y, w, h, ncols, nbytes, i;
unsigned int rgba[256];
unsigned int *icon;
if (sscanf(scummvm_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes) != 4) {
warning("Wrong format of scummvm_icon[0] (%s)", scummvm_icon[0]);
return;
}
if ((w > 512) || (h > 512) || (ncols > 255) || (nbytes > 1)) {
warning("Could not load the built-in icon (%d %d %d %d)", w, h, ncols, nbytes);
return;
}
icon = (unsigned int*)malloc(w*h*sizeof(unsigned int));
if (!icon) {
warning("Could not allocate temp storage for the built-in icon");
return;
}
for (i = 0; i < ncols; i++) {
unsigned char code;
char color[32];
memset(color, 0, sizeof(color));
unsigned int col;
if (sscanf(scummvm_icon[1 + i], "%c c %s", &code, color) != 2) {
warning("Wrong format of scummvm_icon[%d] (%s)", 1 + i, scummvm_icon[1 + i]);
}
if (!strcmp(color, "None"))
col = 0x00000000;
else if (!strcmp(color, "black"))
col = 0xFF000000;
else if (!strcmp(color, "gray20"))
col = 0xFF333333;
else if (color[0] == '#') {
if (sscanf(color + 1, "%06x", &col) != 1) {
warning("Wrong format of color (%s)", color + 1);
}
col |= 0xFF000000;
} else {
warning("Could not load the built-in icon (%d %s - %s) ", code, color, scummvm_icon[1 + i]);
free(icon);
return;
}
rgba[code] = col;
}
for (y = 0; y < h; y++) {
const char *line = scummvm_icon[1 + ncols + y];
for (x = 0; x < w; x++) {
icon[x + w * y] = rgba[(int)line[x]];
}
}
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_Surface *sdl_surf = SDL_CreateSurfaceFrom(w, h, SDL_GetPixelFormatForMasks(32, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000), icon, w * 4);
#else
SDL_Surface *sdl_surf = SDL_CreateRGBSurfaceFrom(icon, w, h, 32, w * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
#endif
if (!sdl_surf) {
warning("SDL_CreateRGBSurfaceFrom(icon) failed");
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
SDL_SetWindowIcon(_window, sdl_surf);
}
#else
SDL_WM_SetIcon(sdl_surf, NULL);
#endif
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_DestroySurface(sdl_surf);
#else
SDL_FreeSurface(sdl_surf);
#endif
free(icon);
#endif
}
void SdlWindow::setWindowCaption(const Common::String &caption) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
_windowCaption = caption;
if (_window) {
SDL_SetWindowTitle(_window, caption.c_str());
}
#else
SDL_WM_SetCaption(caption.c_str(), caption.c_str());
#endif
}
void SdlWindow::setResizable(bool resizable) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
// Don't allow switching state if the window is not meant to be resized
if ((_lastFlags & SDL_WINDOW_RESIZABLE) == 0) {
return;
}
#endif
#if SDL_VERSION_ATLEAST(3, 0, 0)
if (_window) {
SDL_SetWindowResizable(_window, resizable);
}
#elif SDL_VERSION_ATLEAST(2, 0, 5)
if (_window) {
SDL_SetWindowResizable(_window, resizable ? SDL_TRUE : SDL_FALSE);
}
#endif
_resizable = resizable;
}
void SdlWindow::grabMouse(bool grab) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_SetWindowMouseGrab(_window, grab);
#else
SDL_SetWindowGrab(_window, grab ? SDL_TRUE : SDL_FALSE);
#endif
#if SDL_VERSION_ATLEAST(2, 0, 18)
SDL_SetWindowMouseRect(_window, grab ? &grabRect : NULL);
#endif
}
_inputGrabState = grab;
#else
if (grab) {
_inputGrabState = true;
SDL_WM_GrabInput(SDL_GRAB_ON);
} else {
_inputGrabState = false;
if (!_inputLockState)
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
#endif
}
void SdlWindow::setMouseRect(const Common::Rect &rect) {
float dpiScale = getSdlDpiScalingFactor();
grabRect.x = (int)(rect.left / dpiScale + 0.5f);
grabRect.y = (int)(rect.top / dpiScale + 0.5f);
grabRect.w = (int)(rect.width() / dpiScale + 0.5f);
grabRect.h = (int)(rect.height() / dpiScale + 0.5f);
#if SDL_VERSION_ATLEAST(2, 0, 18)
if (_inputGrabState || _lastFlags & fullscreenMask) {
SDL_SetWindowMouseRect(_window, &grabRect);
}
#endif
}
bool SdlWindow::lockMouse(bool lock) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_SetWindowRelativeMouseMode(_window, lock);
_inputLockState = lock;
#elif SDL_VERSION_ATLEAST(2, 0, 0)
SDL_SetRelativeMouseMode(lock ? SDL_TRUE : SDL_FALSE);
_inputLockState = lock;
#else
if (lock) {
_inputLockState = true;
SDL_WM_GrabInput(SDL_GRAB_ON);
} else {
_inputLockState = false;
if (!_inputGrabState)
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
#endif
return true;
}
bool SdlWindow::hasMouseFocus() const {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
return (SDL_GetWindowFlags(_window) & SDL_WINDOW_MOUSE_FOCUS);
} else {
return false;
}
#else
return (SDL_GetAppState() & SDL_APPMOUSEFOCUS);
#endif
}
bool SdlWindow::warpMouseInWindow(int x, int y) {
if (hasMouseFocus()) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
float dpiScale = getSdlDpiScalingFactor();
x = (int)(x / dpiScale + 0.5f);
y = (int)(y / dpiScale + 0.5f);
SDL_WarpMouseInWindow(_window, x, y);
return true;
}
#else
SDL_WarpMouse(x, y);
return true;
#endif
}
return false;
}
void SdlWindow::iconifyWindow() {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
SDL_MinimizeWindow(_window);
}
#else
SDL_WM_IconifyWindow();
#endif
}
#if !SDL_VERSION_ATLEAST(3, 0, 0)
bool SdlWindow::getSDLWMInformation(SDL_SysWMinfo *info) const {
SDL_VERSION(&info->version);
#if SDL_VERSION_ATLEAST(2, 0, 0)
return _window ? (SDL_GetWindowWMInfo(_window, info) == SDL_TRUE) : false;
#elif !defined(__MORPHOS__)
return SDL_GetWMInfo(info);
#else
return false;
#endif
}
#endif
Common::Rect SdlWindow::getDesktopResolution() {
#if SDL_VERSION_ATLEAST(3, 0, 0)
const SDL_DisplayMode* pDisplayMode = SDL_GetDesktopDisplayMode(getDisplayIndex());
if (pDisplayMode) {
_desktopRes = Common::Rect(pDisplayMode->w, pDisplayMode->h);
} else {
warning("SDL_GetDesktopDisplayMode failed: %s", SDL_GetError());
}
#elif SDL_VERSION_ATLEAST(2, 0, 0)
SDL_DisplayMode displayMode;
if (!SDL_GetDesktopDisplayMode(getDisplayIndex(), &displayMode)) {
_desktopRes = Common::Rect(displayMode.w, displayMode.h);
}
#endif
return _desktopRes;
}
void SdlWindow::getDisplayDpi(float *dpi, float *defaultDpi) const {
const float systemDpi =
#ifdef __APPLE__
72.0f;
#elif defined(_WIN32)
96.0f;
#else
90.0f; // ScummVM default
#endif
if (defaultDpi)
*defaultDpi = systemDpi;
if (dpi) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
*dpi = SDL_GetWindowDisplayScale(_window) * systemDpi;
#elif SDL_VERSION_ATLEAST(2, 0, 4)
if (SDL_GetDisplayDPI(getDisplayIndex(), nullptr, dpi, nullptr) != 0) {
*dpi = systemDpi;
}
#else
*dpi = systemDpi;
#endif
}
}
float SdlWindow::getDpiScalingFactor() const {
if (ConfMan.hasKey("forced_dpi_scaling"))
return ConfMan.getInt("forced_dpi_scaling") / 100.f;
float dpi, defaultDpi;
getDisplayDpi(&dpi, &defaultDpi);
float ratio = dpi / defaultDpi;
debug(4, "Reported DPI: %g default: %g, ratio %g, clipped: %g", dpi, defaultDpi, ratio, CLIP(ratio, 1.0f, 4.0f));
// Getting the DPI can be unreliable, so clamp the scaling factor to make sure
// we do not return unreasonable values.
return CLIP(ratio, 1.0f, 4.0f);
}
float SdlWindow::getSdlDpiScalingFactor() const {
#if SDL_VERSION_ATLEAST(3, 0, 0)
return SDL_GetWindowDisplayScale(getSDLWindow());
#elif SDL_VERSION_ATLEAST(2, 0, 0)
int windowWidth, windowHeight;
SDL_GetWindowSize(getSDLWindow(), &windowWidth, &windowHeight);
int realWidth, realHeight;
SDL_GL_GetDrawableSize(getSDLWindow(), &realWidth, &realHeight);
return (float)realWidth / (float)windowWidth;
#else
return 1.f;
#endif
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Surface *copySDLSurface(SDL_Surface *src) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
const bool locked = SDL_MUSTLOCK(src);
if (locked) {
if (!SDL_LockSurface(src)) {
return nullptr;
}
}
#else
const bool locked = SDL_MUSTLOCK(src) == SDL_TRUE;
if (locked) {
if (SDL_LockSurface(src) != 0) {
return nullptr;
}
}
#endif
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_Surface *res = SDL_CreateSurfaceFrom(src->w, src->h, src->format,
src->pixels, src->pitch);
#else
SDL_Surface *res = SDL_CreateRGBSurfaceFrom(src->pixels,
src->w, src->h, src->format->BitsPerPixel,
src->pitch, src->format->Rmask, src->format->Gmask,
src->format->Bmask, src->format->Amask);
#endif
if (locked) {
SDL_UnlockSurface(src);
}
return res;
}
int SdlWindow::getDisplayIndex() const {
#if SDL_VERSION_ATLEAST(3, 0, 0)
int display = 0;
int num_displays;
SDL_DisplayID *displays = SDL_GetDisplays(&num_displays);
if (num_displays > 0) {
display = static_cast<int>(displays[0]);
}
SDL_free(displays);
return display;
#else
if (_window) {
int displayIndex = SDL_GetWindowDisplayIndex(_window);
if (displayIndex >= 0)
return displayIndex;
}
// Default to primary display
return 0;
#endif
}
bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
if (_inputGrabState) {
flags |= SDL_WINDOW_MOUSE_GRABBED;
}
#else
if (_inputGrabState) {
flags |= SDL_WINDOW_INPUT_GRABBED;
}
#endif
#if SDL_VERSION_ATLEAST(2, 0, 0)
bool allowResize = flags & SDL_WINDOW_RESIZABLE;
if (!_resizable) {
flags &= ~SDL_WINDOW_RESIZABLE;
}
#endif
#if SDL_VERSION_ATLEAST(3, 0, 0)
const uint32 updateableFlagsMask = fullscreenMask | SDL_WINDOW_MOUSE_GRABBED | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED;
#elif SDL_VERSION_ATLEAST(2, 0, 5)
// SDL_WINDOW_RESIZABLE can be updated without recreating the window starting with SDL 2.0.5
// Even though some users may switch the SDL version when it's linked dynamically, 2.0.5 is now getting quite old
const uint32 updateableFlagsMask = fullscreenMask | SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED;
#else
const uint32 updateableFlagsMask = fullscreenMask | SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_MAXIMIZED;
#endif
const uint32 oldNonUpdateableFlags = _lastFlags & ~updateableFlagsMask;
const uint32 newNonUpdateableFlags = flags & ~updateableFlagsMask;
const uint32 fullscreenFlags = flags & fullscreenMask;
// This is terrible, but there is no way in SDL to get information on the
// maximum bounds of a window with decoration, and SDL is too dumb to make
// sure the window's surface doesn't grow beyond the display bounds, which
// can easily happen with 3x scalers. There is a function in SDL to get the
// window decoration size, but it only exists starting in SDL 2.0.5, which
// is a buggy release on some platforms so we can't safely use 2.0.5+
// features since some users replace the SDL dynamic library with 2.0.4, and
// the documentation says it only works on X11 anyway, which means it is
// basically worthless. So we'll just try to keep things closeish to the
// maximum for now.
Common::Rect desktopRes = getDesktopResolution();
if (
!fullscreenFlags
#if defined(MACOSX)
// On macOS a maximized window is borderless
&& !(flags & SDL_WINDOW_MAXIMIZED)
#endif
) {
int top, left, bottom, right;
#if SDL_VERSION_ATLEAST(3, 0, 0)
if (!_window || !SDL_GetWindowBordersSize(_window, &top, &left, &bottom, &right))
#elif SDL_VERSION_ATLEAST(2, 0, 5)
if (!_window || SDL_GetWindowBordersSize(_window, &top, &left, &bottom, &right) < 0)
#endif
{
left = right = 10;
top = bottom = 15;
}
desktopRes.right -= (left + right);
desktopRes.bottom -= (top + bottom);
}
if (width > desktopRes.right) {
width = desktopRes.right;
}
if (height > desktopRes.bottom) {
height = desktopRes.bottom;
}
if (!_window || oldNonUpdateableFlags != newNonUpdateableFlags) {
destroyWindow();
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_PropertiesID props = SDL_CreateProperties();
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, _windowCaption.c_str());
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, _lastX);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, _lastY);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER, flags);
_window = SDL_CreateWindowWithProperties(props);
SDL_DestroyProperties(props);
#else
_window = SDL_CreateWindow(_windowCaption.c_str(), _lastX,
_lastY, width, height, flags);
#endif
if (!_window) {
return false;
}
if (_window) {
setupIcon();
}
} else {
if (fullscreenFlags) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
if (!SDL_SetWindowFullscreenMode(_window, NULL))
warning("SDL_SetWindowFullscreenMode failed: %s", SDL_GetError());
if (!SDL_SyncWindow(_window))
warning("SDL_SyncWindow failed: %s", SDL_GetError());
#else
SDL_DisplayMode fullscreenMode;
fullscreenMode.w = width;
fullscreenMode.h = height;
fullscreenMode.driverdata = nullptr;
fullscreenMode.format = 0;
fullscreenMode.refresh_rate = 0;
SDL_SetWindowDisplayMode(_window, &fullscreenMode);
#endif
} else {
SDL_SetWindowSize(_window, width, height);
if (flags & SDL_WINDOW_MAXIMIZED) {
SDL_MaximizeWindow(_window);
} else {
SDL_RestoreWindow(_window);
}
}
SDL_SetWindowFullscreen(_window, fullscreenFlags);
}
#if SDL_VERSION_ATLEAST(3, 0, 0)
const bool shouldGrab = (flags & SDL_WINDOW_MOUSE_GRABBED) || fullscreenFlags;
SDL_SetWindowMouseGrab(_window, shouldGrab);
#else
const bool shouldGrab = (flags & SDL_WINDOW_INPUT_GRABBED) || fullscreenFlags;
SDL_SetWindowGrab(_window, shouldGrab ? SDL_TRUE : SDL_FALSE);
#endif
#if SDL_VERSION_ATLEAST(2, 0, 18)
SDL_SetWindowMouseRect(_window, shouldGrab ? &grabRect : NULL);
#endif
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_SetWindowResizable(_window, (flags & SDL_WINDOW_RESIZABLE) != 0);
#elif SDL_VERSION_ATLEAST(2, 0, 5)
SDL_SetWindowResizable(_window, (flags & SDL_WINDOW_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
#endif
#if SDL_VERSION_ATLEAST(2, 0, 0)
// Restore the flag to allow switching resize state later
if (allowResize) {
flags |= SDL_WINDOW_RESIZABLE;
}
#endif
#if defined(MACOSX)
// macOS windows with the flag SDL_WINDOW_FULLSCREEN_DESKTOP exiting their fullscreen space
// ignore the size set by SDL_SetWindowSize while they were in fullscreen mode.
// Instead, they revert back to their previous windowed mode size.
// This is a bug in SDL2: https://github.com/libsdl-org/SDL/issues/2518.
// TODO: Remove the call to SDL_SetWindowSize below once the SDL bug is fixed.
// In some cases at this point there may be a pending SDL resize event with the old size.
// This happens for example if we destroyed the window, or when switching between windowed
// and fullscreen modes. If we changed the window size here, this pending event will have the
// old (and incorrect) size. To avoid any issue we call SDL_SetWindowSize() to generate another
// resize event (SDL_WINDOWEVENT_SIZE_CHANGED) so that the last resize event we receive has
// the correct size. This fixes for exmample bug #9971: SDL2: Fullscreen to RTL launcher resolution
SDL_SetWindowSize(_window, width, height);
#endif
_lastFlags = flags;
return true;
}
void SdlWindow::destroyWindow() {
if (_window) {
if (!(_lastFlags & fullscreenMask)) {
SDL_GetWindowPosition(_window, &_lastX, &_lastY);
}
// Notify the graphics manager that we are about to delete its window
OSystem_SDL *system = dynamic_cast<OSystem_SDL *>(g_system);
assert(system);
GraphicsManager *graphics = system->getGraphicsManager();
if (graphics) {
SdlGraphicsManager *sdlGraphics = dynamic_cast<SdlGraphicsManager *>(graphics);
assert(sdlGraphics);
sdlGraphics->destroyingWindow();
}
SDL_DestroyWindow(_window);
_window = nullptr;
}
}
#endif

View File

@@ -0,0 +1,210 @@
/* 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/>.
*
*/
#ifndef BACKENDS_PLATFORM_SDL_WINDOW_H
#define BACKENDS_PLATFORM_SDL_WINDOW_H
#include "backends/platform/sdl/sdl-sys.h"
#include "common/rect.h"
#include "common/str.h"
class SdlWindow {
public:
SdlWindow();
virtual ~SdlWindow();
/**
* Setup the window icon.
*/
virtual void setupIcon();
/**
* Change the caption of the window.
*
* @param caption New window caption in UTF-8 encoding.
*/
void setWindowCaption(const Common::String &caption);
/**
* Allows the window to be resized or not
*
* @param resizable Whether the window can be resizable or not.
*/
void setResizable(bool resizable);
/**
* Grab or ungrab the mouse cursor. This decides whether the cursor can leave
* the window or not.
*/
void grabMouse(bool grab);
/**
* Specify the area of the window to confine the mouse cursor.
*/
void setMouseRect(const Common::Rect &rect);
/**
* Lock or unlock the mouse cursor within the window.
*/
bool lockMouse(bool lock);
/**
* Check whether the application has mouse focus.
*/
bool hasMouseFocus() const;
/**
* Warp the mouse to the specified position in window coordinates. The mouse
* will only be warped if the window is focused in the window manager.
*
* @returns true if the system cursor was warped.
*/
bool warpMouseInWindow(int x, int y);
/**
* Iconifies the window.
*/
void iconifyWindow();
#if !SDL_VERSION_ATLEAST(3, 0, 0)
/**
* Query platform specific SDL window manager information.
*
* Since this is an SDL internal structure clients are responsible
* for accessing it in a version safe manner.
*/
bool getSDLWMInformation(SDL_SysWMinfo *info) const;
#endif
/*
* Retrieve the current desktop resolution.
*/
Common::Rect getDesktopResolution();
/*
* Get the scaling between the SDL Window size and the SDL
* drawable area size. On some system, when HiDPI support is
* enabled, those two sizes are different.
*
* To convert from window coordinate to drawable area coordinate,
* multiple the coordinate by this scaling factor. To convert
* from drawable area coordinate to window coordinate, divide the
* coordinate by this scaling factor.
*/
float getSdlDpiScalingFactor() const;
/**
* Returns the scaling mode based on the display DPI
*/
virtual float getDpiScalingFactor() const;
bool resizable() const {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
return SDL_GetWindowFlags(_window) & SDL_WINDOW_RESIZABLE;
}
#endif
return _resizable;
}
bool mouseIsGrabbed() const {
#if SDL_VERSION_ATLEAST(3, 0, 0)
if (_window) {
return SDL_GetWindowMouseGrab(_window);
}
#elif SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
return SDL_GetWindowGrab(_window) == SDL_TRUE;
}
#endif
return _inputGrabState;
}
bool mouseIsLocked() const {
#if SDL_VERSION_ATLEAST(3, 0, 0)
return SDL_GetWindowRelativeMouseMode(_window);
#elif SDL_VERSION_ATLEAST(2, 0, 0)
return SDL_GetRelativeMouseMode() == SDL_TRUE;
#else
return _inputLockState;
#endif
}
private:
Common::Rect _desktopRes;
bool _resizable;
bool _inputGrabState, _inputLockState;
SDL_Rect grabRect;
protected:
void getDisplayDpi(float *dpi, float *defaultDpi) const;
#if SDL_VERSION_ATLEAST(2, 0, 0)
public:
/**
* @return The window ScummVM has setup with SDL.
*/
SDL_Window *getSDLWindow() const { return _window; }
/**
* @return The display containing the ScummVM window.
*/
int getDisplayIndex() const;
/**
* Creates or updates the SDL window.
*
* @param width Width of the window.
* @param height Height of the window.
* @param flags SDL flags passed to SDL_CreateWindow
* @return true on success, false otherwise
*/
virtual bool createOrUpdateWindow(int width, int height, uint32 flags);
/**
* Destroys the current SDL window.
*/
void destroyWindow();
protected:
SDL_Window *_window;
private:
uint32 _lastFlags;
/**
* Switching between software and OpenGL modes requires the window to be
* destroyed and recreated. These properties store the position of the last
* window so the new window will be created in the same place.
*/
int _lastX, _lastY;
Common::String _windowCaption;
#endif
};
class SdlIconlessWindow : public SdlWindow {
public:
virtual void setupIcon() {}
};
#endif

File diff suppressed because it is too large Load Diff

211
backends/platform/sdl/sdl.h Normal file
View File

@@ -0,0 +1,211 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_H
#define PLATFORM_SDL_H
#include "backends/platform/sdl/sdl-sys.h"
#include "backends/modular-backend.h"
#include "backends/mixer/sdl/sdl-mixer.h"
#include "backends/events/sdl/sdl-events.h"
#include "backends/log/log.h"
#include "backends/platform/sdl/sdl-window.h"
#include "common/array.h"
#ifdef USE_OPENGL
#define USE_MULTIPLE_RENDERERS
#endif
#ifdef USE_DISCORD
class DiscordPresence;
#endif
/**
* Base OSystem class for all SDL ports.
*/
class OSystem_SDL : public ModularMixerBackend, public ModularGraphicsBackend {
public:
OSystem_SDL();
virtual ~OSystem_SDL();
/**
* Pre-initialize backend. It should be called after
* instantiating the backend. Early needed managers are
* created here.
*/
void init() override;
bool hasFeature(Feature f) override;
void setFeatureState(Feature f, bool enable) override;
bool getFeatureState(Feature f) override;
// Override functions from ModularBackend and OSystem
void initBackend() override;
void engineInit() override;
void engineDone() override;
void quit() override;
void fatalError() override;
Common::KeymapArray getGlobalKeymaps() override;
Common::HardwareInputSet *getHardwareInputSet() override;
// Logging
void logMessage(LogMessageType::Type type, const char *message) override;
Common::String getSystemLanguage() const override;
#if SDL_VERSION_ATLEAST(2, 0, 0)
// Clipboard
bool hasTextInClipboard() override;
Common::U32String getTextFromClipboard() override;
bool setTextInClipboard(const Common::U32String &text) override;
void messageBox(LogMessageType::Type type, const char *message) override;
#endif
#if SDL_VERSION_ATLEAST(2, 0, 14)
bool openUrl(const Common::String &url) override;
#endif
void setWindowCaption(const Common::U32String &caption) override;
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0) override;
Common::MutexInternal *createMutex() override;
uint32 getMillis(bool skipRecord = false) override;
void delayMillis(uint msecs) override;
void getTimeAndDate(TimeDate &td, bool skipRecord = false) const override;
MixerManager *getMixerManager() override;
Common::TimerManager *getTimerManager() override;
Common::SaveFileManager *getSavefileManager() override;
uint32 getDoubleClickTime() const override;
// Default paths
virtual Common::Path getDefaultIconsPath();
virtual Common::Path getDefaultDLCsPath();
virtual Common::Path getScreenshotsPath();
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
Common::Array<uint> getSupportedAntiAliasingLevels() const override;
OpenGL::ContextType getOpenGLType() const override { return _oglType; }
#endif
#if defined(USE_OPENGL) && defined(USE_GLAD)
void *getOpenGLProcAddress(const char *name) const override;
#endif
protected:
bool _inited;
bool _initedSDL;
#ifdef USE_SDL_NET
bool _initedSDLnet;
#endif
#ifdef USE_DISCORD
DiscordPresence *_presence;
#endif
/**
* The path of the currently open log file, if any.
*
* @note This is currently a Path and not an FSNode for simplicity;
* e.g. we don't need to include fs.h here, and currently the
* only use of this value is to use it to open the log file in an
* editor; for that, we need it only as a path anyway.
*/
Common::Path _logFilePath;
/**
* The event source we use for obtaining SDL events.
*/
SdlEventSource *_eventSource;
Common::EventSource *_eventSourceWrapper;
/**
* The SDL output window.
*/
SdlWindow *_window;
SdlGraphicsManager::State _gfxManagerState;
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
// Graphics capabilities
void detectOpenGLFeaturesSupport();
void detectAntiAliasingSupport();
OpenGL::ContextType _oglType;
bool _supportsShaders;
Common::Array<uint> _antiAliasLevels;
#endif
/**
* Initialize the SDL library.
*/
virtual void initSDL();
/**
* Create the audio CD manager
*/
virtual AudioCDManager *createAudioCDManager();
// Logging
virtual Common::WriteStream *createLogFile();
Backends::Log::Log *_logger;
#ifdef USE_MULTIPLE_RENDERERS
enum GraphicsManagerType {
GraphicsManagerSurfaceSDL,
#ifdef USE_OPENGL
GraphicsManagerOpenGL,
#endif
GraphicsManagerCount
};
typedef Common::Array<GraphicsMode> GraphicsModeArray;
GraphicsModeArray _graphicsModes;
Common::Array<int> _graphicsModeIds;
int _graphicsMode;
int _firstMode[GraphicsManagerCount];
int _lastMode[GraphicsManagerCount];
int _defaultMode[GraphicsManagerCount];
int _supports3D[GraphicsManagerCount];
/**
* Create the merged graphics modes list.
*/
void setupGraphicsModes();
/**
* Clear the merged graphics modes list.
*/
void clearGraphicsModes();
virtual GraphicsManagerType getDefaultGraphicsManager() const;
SdlGraphicsManager *createGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window, GraphicsManagerType type);
const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
int getDefaultGraphicsMode() const override;
bool setGraphicsMode(int mode, uint flags) override;
int getGraphicsMode() const override;
#endif
virtual uint32 getOSDoubleClickTime() const { return 0; }
virtual const char * const *buildHelpDialogData() override;
};
#endif

View File

@@ -0,0 +1,71 @@
ScummVM-Switch README
==============================================================================
Installation
============
- The latest daily version of ScummVM for Switch is [here](https://buildbot.scummvm.org/snapshots/master/switch-master-latest.zip) (needs to be unzipped).
- Copy the scummvm folder to your SD card into the folder /switch/ so that you have a folder `/switch/scummvm` with `scummvm.nro` and other folders inside.
- Launch ScummVM using your favorite method to launch homebrew on the Switch
Notes
=====
- This README may be outdated, for more up-to-date instructions and notes see
the Switch Port Wiki: https://wiki.scummvm.org/index.php/Nintendo_Switch
Building the source code
========================
This port of ScummVM to the Switch is based on SDL2. It uses the open source SDK provided by devkitPro.
To build ScummVM for Switch:
- Obtain the ScummVM source code (https://github.com/scummvm/scummvm)
- Install the development tools for Switch following the official instructions (https://devkitpro.org/wiki/Getting_Started)
- Install libraries via
```
sudo dkp-pacman -S \
switch-sdl2 \
switch-libmad \
switch-libogg \
switch-libvorbis \
switch-flac \
switch-libtheora \
switch-libpng \
switch-libjpeg-turbo \
switch-zlib \
switch-freetype \
switch-sdl2_net \
switch-curl \
switch-libtimidity \
switch-pkg-config
```
- Optional: To enable fluidsynth support, download and install the unofficial fluidsynth-lite switch port via
```
git clone https://github.com/rsn8887/fluidsynth-lite
cd fluidsynth-lite
make -f Makefile.nx
make -f Makefile.nx install
```
- Create a subdirectory somewhere outside the source folder for your ScummVM build and cd into it
- Execute the command
```
../scummvm/configure --host=switch
```
- Execute the command
```
make scummvm_switch.zip
```
Port Authors
============
cpasjuste
rsn8887
Thanks
======
[devkitPro](https://devkitpro.org devkitPro) and [Switchbrew](https://switchbrew.org/) teams

View File

@@ -0,0 +1,56 @@
/* 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 <switch.h>
#include "common/scummsys.h"
#include "backends/platform/sdl/switch/switch.h"
#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
int main(int argc, char *argv[]) {
socketInitializeDefault();
#ifdef __SWITCH_DEBUG__
nxlinkStdio();
#endif
// Create our OSystem instance
g_system = new OSystem_Switch();
assert(g_system);
// Pre initialize the backend
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
socketExit();
return res;
}

View File

@@ -0,0 +1,171 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
#include <switch.h>
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/translation.h"
#include "backends/platform/sdl/switch/switch.h"
#include "backends/events/switchsdl/switchsdl-events.h"
#include "backends/saves/posix/posix-saves.h"
#include "backends/fs/posix-drives/posix-drives-fs-factory.h"
#include "backends/fs/posix-drives/posix-drives-fs.h"
#include "backends/keymapper/hardware-input.h"
static const Common::HardwareInputTableEntry switchJoystickButtons[] = {
{ "JOY_A", Common::JOYSTICK_BUTTON_A, _s("B") },
{ "JOY_B", Common::JOYSTICK_BUTTON_B, _s("A") },
{ "JOY_X", Common::JOYSTICK_BUTTON_X, _s("Y") },
{ "JOY_Y", Common::JOYSTICK_BUTTON_Y, _s("X") },
{ "JOY_BACK", Common::JOYSTICK_BUTTON_BACK, _s("Minus") },
{ "JOY_START", Common::JOYSTICK_BUTTON_START, _s("Plus") },
{ "JOY_GUIDE", Common::JOYSTICK_BUTTON_START, _s("Plus") },
{ "JOY_LEFT_STICK", Common::JOYSTICK_BUTTON_LEFT_STICK, _s("L3") },
{ "JOY_RIGHT_STICK", Common::JOYSTICK_BUTTON_RIGHT_STICK, _s("R3") },
{ "JOY_LEFT_SHOULDER", Common::JOYSTICK_BUTTON_LEFT_SHOULDER, _s("L") },
{ "JOY_RIGHT_SHOULDER", Common::JOYSTICK_BUTTON_RIGHT_SHOULDER, _s("R") },
{ "JOY_UP", Common::JOYSTICK_BUTTON_DPAD_UP, _s("D-pad Up") },
{ "JOY_DOWN", Common::JOYSTICK_BUTTON_DPAD_DOWN, _s("D-pad Down") },
{ "JOY_LEFT", Common::JOYSTICK_BUTTON_DPAD_LEFT, _s("D-pad Left") },
{ "JOY_RIGHT", Common::JOYSTICK_BUTTON_DPAD_RIGHT, _s("D-pad Right") },
{ nullptr, 0, nullptr }
};
static const Common::AxisTableEntry switchJoystickAxes[] = {
{ "JOY_LEFT_TRIGGER", Common::JOYSTICK_AXIS_LEFT_TRIGGER, Common::kAxisTypeHalf, _s("ZL") },
{ "JOY_RIGHT_TRIGGER", Common::JOYSTICK_AXIS_RIGHT_TRIGGER, Common::kAxisTypeHalf, _s("ZR") },
{ "JOY_LEFT_STICK_X", Common::JOYSTICK_AXIS_LEFT_STICK_X, Common::kAxisTypeFull, _s("Left Stick X") },
{ "JOY_LEFT_STICK_Y", Common::JOYSTICK_AXIS_LEFT_STICK_Y, Common::kAxisTypeFull, _s("Left Stick Y") },
{ "JOY_RIGHT_STICK_X", Common::JOYSTICK_AXIS_RIGHT_STICK_X, Common::kAxisTypeFull, _s("Right Stick X") },
{ "JOY_RIGHT_STICK_Y", Common::JOYSTICK_AXIS_RIGHT_STICK_Y, Common::kAxisTypeFull, _s("Right Stick Y") },
{ nullptr, 0, Common::kAxisTypeFull, nullptr }
};
void OSystem_Switch::init() {
DrivesPOSIXFilesystemFactory *fsFactory = new DrivesPOSIXFilesystemFactory();
fsFactory->addDrive("sdmc:");
fsFactory->configureBuffering(DrivePOSIXFilesystemNode::kBufferingModeScummVM, 2048);
_fsFactory = fsFactory;
// Invoke parent implementation of this method
OSystem_SDL::init();
}
void OSystem_Switch::initBackend() {
ConfMan.registerDefault("fullscreen", true);
ConfMan.registerDefault("aspect_ratio", false);
ConfMan.registerDefault("gfx_mode", "2x");
ConfMan.registerDefault("filtering", true);
ConfMan.registerDefault("output_rate", 48000);
ConfMan.registerDefault("touchpad_mouse_mode", false);
ConfMan.setBool("fullscreen", true);
ConfMan.setInt("joystick_num", 0);
if (!ConfMan.hasKey("aspect_ratio")) {
ConfMan.setBool("aspect_ratio", false);
}
if (!ConfMan.hasKey("gfx_mode")) {
ConfMan.set("gfx_mode", "2x");
}
if (!ConfMan.hasKey("filtering")) {
ConfMan.setBool("filtering", true);
}
if (!ConfMan.hasKey("output_rate")) {
ConfMan.setInt("output_rate", 48000);
}
if (!ConfMan.hasKey("touchpad_mouse_mode")) {
ConfMan.setBool("touchpad_mouse_mode", false);
}
// Create the savefile manager
if (_savefileManager == 0) {
_savefileManager = new DefaultSaveFileManager("./saves");
}
// Event source
if (_eventSource == 0) {
_eventSource = new SwitchEventSource();
}
// Invoke parent implementation of this method
OSystem_SDL::initBackend();
}
bool OSystem_Switch::hasFeature(Feature f) {
if (f == kFeatureFullscreenMode)
return false;
return (f == kFeatureTouchpadMode ||
OSystem_SDL::hasFeature(f));
}
void OSystem_Switch::logMessage(LogMessageType::Type type, const char *message) {
printf("%s\n", message);
}
Common::Path OSystem_Switch::getDefaultLogFileName() {
return "scummvm.log";
}
Common::HardwareInputSet *OSystem_Switch::getHardwareInputSet() {
using namespace Common;
CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
// Users may use USB / bluetooth mice and keyboards
inputSet->addHardwareInputSet(new MouseHardwareInputSet(defaultMouseButtons));
inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
inputSet->addHardwareInputSet(new JoystickHardwareInputSet(switchJoystickButtons, switchJoystickAxes));
return inputSet;
}
Common::String OSystem_Switch::getSystemLanguage() const {
u64 lang;
SetLanguage langcode;
setInitialize();
setGetSystemLanguage(&lang);
setMakeLanguage(lang, &langcode);
switch (langcode) {
case SetLanguage_JA: return "ja_JP";
case SetLanguage_ENUS: return "en_US";
case SetLanguage_FR: return "fr_FR";
case SetLanguage_FRCA: return "fr_FR";
case SetLanguage_DE: return "de_DE";
case SetLanguage_IT: return "it_IT";
case SetLanguage_ES: return "es_ES";
case SetLanguage_ZHCN: return "zh_CN";
case SetLanguage_KO: return "ko_KR";
case SetLanguage_NL: return "nl_NL";
case SetLanguage_PT: return "pt_PT";
case SetLanguage_RU: return "ru_RU";
case SetLanguage_ZHTW: return "zh_HK";
default: return "en_US";
}
}

View File

@@ -0,0 +1,41 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_SWITCH_H
#define PLATFORM_SDL_SWITCH_H
#include "backends/platform/sdl/sdl.h"
class OSystem_Switch : public OSystem_SDL {
public:
void init() override;
void initBackend() override;
bool hasFeature(Feature f) override;
void logMessage(LogMessageType::Type type, const char *message) override;
Common::HardwareInputSet *getHardwareInputSet() override;
virtual Common::String getSystemLanguage() const;
protected:
Common::Path getDefaultLogFileName() override;
};
#endif

View File

@@ -0,0 +1,35 @@
scummvm.nro: $(EXECUTABLE)
mkdir -p ./switch_release/scummvm/data
mkdir -p ./switch_release/scummvm/doc
nacptool --create "ScummVM" "ScummVM Team" "$(VERSION)" ./switch_release/scummvm.nacp
elf2nro $(EXECUTABLE) ./switch_release/scummvm/scummvm.nro --icon=$(srcdir)/dists/switch/icon.jpg --nacp=./switch_release/scummvm.nacp
switch_release: scummvm.nro
rm -f ./switch_release/scummvm.nacp
cp $(DIST_FILES_THEMES) ./switch_release/scummvm/data
ifdef DIST_FILES_ENGINEDATA
cp $(DIST_FILES_ENGINEDATA) ./switch_release/scummvm/data
endif
ifdef DIST_FILES_ENGINEDATA_BIG
cp $(DIST_FILES_ENGINEDATA_BIG) ./switch_release/scummvm/data
endif
ifdef DIST_FILES_SOUNDFONTS
cp $(DIST_FILES_SOUNDFONTS) ./switch_release/scummvm/data
endif
ifdef DIST_FILES_NETWORKING
cp $(DIST_FILES_NETWORKING) ./switch_release/scummvm/data
endif
ifdef DIST_FILES_VKEYBD
cp $(DIST_FILES_VKEYBD) ./switch_release/scummvm/data
endif
ifdef DIST_FILES_SHADERS
mkdir -p ./switch_release/scummvm/data/shaders
cp $(DIST_FILES_SHADERS) ./switch_release/scummvm/data/shaders
endif
cp $(DIST_FILES_DOCS) ./switch_release/scummvm/doc/
cp $(srcdir)/backends/platform/sdl/switch/README.SWITCH ./switch_release/scummvm/doc/
scummvm_switch.zip: switch_release
cd ./switch_release && zip -r ../scummvm_switch.zip . && cd ..
.PHONY: scummvm.nro switch_release scummvm_switch.zip

View File

@@ -0,0 +1,87 @@
/* 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/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/scummsys.h"
#ifdef WIN32
// Fix for bug #4700 "MSVC compilation broken with r47595":
// We need to keep this on top of the "common/scummsys.h"(base/main.h) include,
// otherwise we will get errors about the windows headers redefining
// "ARRAYSIZE" for example.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "backends/platform/sdl/win32/win32.h"
#include "backends/platform/sdl/win32/win32_wrapper.h"
#include "backends/plugins/win32/win32-provider.h"
#include "base/main.h"
int __stdcall WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/, LPSTR /*lpCmdLine*/, int /*iShowCmd*/) {
#if !SDL_VERSION_ATLEAST(2, 0, 0)
SDL_SetModuleHandle(GetModuleHandle(NULL));
#endif
// HACK: __argc, __argv are broken and return zero when using mingwrt 4.0+ on MinGW
// HACK: MinGW-w64 based toolchains neither feature _argc nor _argv. The 32 bit
// incarnation only defines __MINGW32__. This leads to build breakage due to
// missing declarations. Luckily MinGW-w64 based toolchains define
// __MINGW64_VERSION_foo macros inside _mingw.h, which is included from all
// system headers. Thus we abuse that to detect them.
#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
return main(_argc, _argv);
#else
return main(__argc, __argv);
#endif
}
int main(int argc, char *argv[]) {
#ifdef UNICODE
argv = Win32::getArgvUtf8(&argc);
#endif
// Create our OSystem instance
g_system = new OSystem_Win32();
assert(g_system);
// Pre initialize the backend
g_system->init();
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new Win32PluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
// Free OSystem
g_system->destroy();
#ifdef UNICODE
Win32::freeArgvUtf8(argc, argv);
#endif
return res;
}
#endif

View File

@@ -0,0 +1,65 @@
/* 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/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#ifdef WIN32
#include "backends/platform/sdl/win32/win32-window.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
void SdlWindow_Win32::setupIcon() {
HMODULE handle = GetModuleHandle(nullptr);
HICON ico = LoadIcon(handle, MAKEINTRESOURCE(1001 /* IDI_ICON */));
if (ico) {
HWND hwnd = getHwnd();
if (hwnd) {
// Replace the handle to the icon associated with the window class by our custom icon
SetClassLongPtr(hwnd, GCLP_HICON, (ULONG_PTR)ico);
// Since there wasn't any default icon, we can't use the return value from SetClassLong
// to check for errors (it would be 0 in both cases: error or no previous value for the
// icon handle). Instead we check for the last-error code value.
if (GetLastError() == ERROR_SUCCESS)
return;
}
}
// If no icon has been set, fallback to default path
SdlWindow::setupIcon();
}
HWND SdlWindow_Win32::getHwnd() {
SDL_SysWMinfo wminfo;
if (getSDLWMInformation(&wminfo)) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
return wminfo.info.win.window;
#else
return wminfo.window;
#endif
}
return nullptr;
}
#endif

View File

@@ -0,0 +1,37 @@
/* 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/>.
*
*/
#ifndef BACKENDS_PLATFORM_SDL_WIN32_WIN32_WINDOW_H
#define BACKENDS_PLATFORM_SDL_WIN32_WIN32_WINDOW_H
#ifdef WIN32
#include "backends/platform/sdl/sdl-window.h"
class SdlWindow_Win32 final : public SdlWindow {
public:
void setupIcon() override;
HWND getHwnd();
};
#endif
#endif

View File

@@ -0,0 +1,545 @@
/* 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/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>
#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
// required for SHGFP_TYPE_CURRENT in shlobj.h
#define _WIN32_IE 0x500
#endif
#include <shlobj.h>
#include <tchar.h>
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/error.h"
#include "common/textconsole.h"
#include "backends/audiocd/win32/win32-audiocd.h"
#include "backends/platform/sdl/win32/win32.h"
#include "backends/platform/sdl/win32/win32-window.h"
#include "backends/platform/sdl/win32/win32_wrapper.h"
#include "backends/saves/windows/windows-saves.h"
#include "backends/fs/windows/windows-fs-factory.h"
#include "backends/taskbar/win32/win32-taskbar.h"
#include "backends/updates/win32/win32-updates.h"
#include "backends/dialogs/win32/win32-dialogs.h"
#include "common/memstream.h"
#include "common/ustr.h"
#if defined(USE_TTS)
#include "backends/text-to-speech/windows/windows-text-to-speech.h"
#endif
#define DEFAULT_CONFIG_FILE "scummvm.ini"
OSystem_Win32::OSystem_Win32() :
_isPortable(false) {
}
void OSystem_Win32::init() {
// Initialize File System Factory
_fsFactory = new WindowsFilesystemFactory();
// Create Win32 specific window
initSDL();
_window = new SdlWindow_Win32();
#if defined(USE_TASKBAR)
// Initialize taskbar manager
_taskbarManager = new Win32TaskbarManager((SdlWindow_Win32*)_window);
#endif
#if defined(USE_SYSDIALOGS)
// Initialize dialog manager
_dialogManager = new Win32DialogManager((SdlWindow_Win32*)_window);
#endif
#if defined(USE_JPEG)
initializeJpegLibraryForWin95();
#endif
// Invoke parent implementation of this method
OSystem_SDL::init();
}
WORD GetCurrentSubsystem() {
// HMODULE is the module base address. And the PIMAGE_DOS_HEADER is located at the beginning.
PIMAGE_DOS_HEADER EXEHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(nullptr);
assert(EXEHeader->e_magic == IMAGE_DOS_SIGNATURE);
// PIMAGE_NT_HEADERS is bitness dependant.
// Conveniently, since it's for our own process, it's always the correct bitness.
// IMAGE_NT_HEADERS has to be found using a byte offset from the EXEHeader,
// which requires the ugly cast.
PIMAGE_NT_HEADERS PEHeader = (PIMAGE_NT_HEADERS)(((char*)EXEHeader) + EXEHeader->e_lfanew);
assert(PEHeader->Signature == IMAGE_NT_SIGNATURE);
return PEHeader->OptionalHeader.Subsystem;
}
void OSystem_Win32::initBackend() {
// The console window is enabled for the console subsystem,
// since Windows already creates the console window for us
ConfMan.registerDefault("console", GetCurrentSubsystem() == IMAGE_SUBSYSTEM_WINDOWS_CUI);
// Enable or disable the window console window
if (ConfMan.getBool("console")) {
if (AllocConsole()) {
freopen("CONIN$","r",stdin);
freopen("CONOUT$","w",stdout);
freopen("CONOUT$","w",stderr);
}
SetConsoleTitle(TEXT("ScummVM Status Window"));
} else {
FreeConsole();
}
// Create the savefile manager
if (_savefileManager == nullptr)
_savefileManager = new WindowsSaveFileManager(_isPortable);
#if defined(USE_SPARKLE)
// Initialize updates manager
if (!_isPortable) {
_updateManager = new Win32UpdateManager((SdlWindow_Win32*)_window);
}
#endif
// Initialize text to speech
#ifdef USE_TTS
_textToSpeechManager = new WindowsTextToSpeechManager();
#endif
// Invoke parent implementation of this method
OSystem_SDL::initBackend();
}
#ifdef USE_OPENGL
OSystem_SDL::GraphicsManagerType OSystem_Win32::getDefaultGraphicsManager() const {
return GraphicsManagerOpenGL;
}
#endif
bool OSystem_Win32::hasFeature(Feature f) {
if (f == kFeatureDisplayLogFile || f == kFeatureOpenUrl)
return true;
#ifdef USE_SYSDIALOGS
if (f == kFeatureSystemBrowserDialog)
return true;
#endif
return OSystem_SDL::hasFeature(f);
}
bool OSystem_Win32::displayLogFile() {
if (_logFilePath.empty())
return false;
// Try opening the log file with the default text editor
// log files should be registered as "txtfile" by default and thus open in the default text editor
TCHAR *tLogFilePath = Win32::stringToTchar(_logFilePath.toString(Common::Path::kNativeSeparator));
SHELLEXECUTEINFO sei;
memset(&sei, 0, sizeof(sei));
sei.fMask = SEE_MASK_FLAG_NO_UI;
sei.hwnd = getHwnd();
sei.lpFile = tLogFilePath;
sei.nShow = SW_SHOWNORMAL;
if (ShellExecuteEx(&sei)) {
free(tLogFilePath);
return true;
}
// ShellExecute with the default verb failed, try the "Open with..." dialog
PROCESS_INFORMATION processInformation;
STARTUPINFO startupInfo;
memset(&processInformation, 0, sizeof(processInformation));
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
TCHAR cmdLine[MAX_PATH * 2]; // CreateProcess may change the contents of cmdLine
_stprintf(cmdLine, TEXT("rundll32 shell32.dll,OpenAs_RunDLL %s"), tLogFilePath);
BOOL result = CreateProcess(nullptr,
cmdLine,
nullptr,
nullptr,
FALSE,
NORMAL_PRIORITY_CLASS,
nullptr,
nullptr,
&startupInfo,
&processInformation);
free(tLogFilePath);
if (result) {
CloseHandle(processInformation.hProcess);
CloseHandle(processInformation.hThread);
return true;
}
return false;
}
bool OSystem_Win32::openUrl(const Common::String &url) {
TCHAR *tUrl = Win32::stringToTchar(url);
SHELLEXECUTEINFO sei;
memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_FLAG_NO_UI;
sei.hwnd = getHwnd();
sei.lpFile = tUrl;
sei.nShow = SW_SHOWNORMAL;
BOOL success = ShellExecuteEx(&sei);
free(tUrl);
if (!success) {
warning("ShellExecuteEx failed: error = %08lX", GetLastError());
return false;
}
return true;
}
void OSystem_Win32::logMessage(LogMessageType::Type type, const char *message) {
OSystem_SDL::logMessage(type, message);
#if defined( USE_WINDBG )
TCHAR *tMessage = Win32::stringToTchar(message);
OutputDebugString(tMessage);
free(tMessage);
#endif
}
Common::String OSystem_Win32::getSystemLanguage() const {
#if defined(USE_DETECTLANG) && defined(USE_TRANSLATION)
// We can not use "setlocale" (at least not for MSVC builds), since it
// will return locales like: "English_USA.1252", thus we need a special
// way to determine the locale string for Win32.
TCHAR langName[9];
TCHAR ctryName[9];
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, langName, ARRAYSIZE(langName)) != 0 &&
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, ctryName, ARRAYSIZE(ctryName)) != 0) {
Common::String localeName = Win32::tcharToString(langName);
localeName += "_";
localeName += Win32::tcharToString(ctryName);
return localeName;
}
#endif // USE_DETECTLANG
// Falback to SDL implementation
return OSystem_SDL::getSystemLanguage();
}
Common::Path OSystem_Win32::getDefaultIconsPath() {
TCHAR iconsPath[MAX_PATH];
if (_isPortable) {
Win32::getProcessDirectory(iconsPath, MAX_PATH);
_tcscat(iconsPath, TEXT("\\Icons\\"));
} else {
// Use the Application Data directory of the user profile
if (!Win32::getApplicationDataDirectory(iconsPath)) {
return Common::Path();
}
_tcscat(iconsPath, TEXT("\\Icons\\"));
CreateDirectory(iconsPath, nullptr);
}
return Common::Path(Win32::tcharToString(iconsPath), Common::Path::kNativeSeparator);
}
Common::Path OSystem_Win32::getDefaultDLCsPath() {
TCHAR dlcsPath[MAX_PATH];
if (_isPortable) {
Win32::getProcessDirectory(dlcsPath, MAX_PATH);
_tcscat(dlcsPath, TEXT("\\DLCs\\"));
} else {
// Use the Application Data directory of the user profile
if (!Win32::getApplicationDataDirectory(dlcsPath)) {
return Common::Path();
}
_tcscat(dlcsPath, TEXT("\\DLCs\\"));
CreateDirectory(dlcsPath, nullptr);
}
return Common::Path(Win32::tcharToString(dlcsPath), Common::Path::kNativeSeparator);
}
Common::Path OSystem_Win32::getScreenshotsPath() {
// If the user has configured a screenshots path, use it
Common::Path screenshotsPath = ConfMan.getPath("screenshotpath");
if (!screenshotsPath.empty()) {
return screenshotsPath;
}
TCHAR picturesPath[MAX_PATH];
if (_isPortable) {
Win32::getProcessDirectory(picturesPath, MAX_PATH);
_tcscat(picturesPath, TEXT("\\Screenshots\\"));
} else {
// Use the My Pictures folder
HRESULT hr = SHGetFolderPathFunc(nullptr, CSIDL_MYPICTURES, nullptr, SHGFP_TYPE_CURRENT, picturesPath);
if (hr != S_OK) {
if (hr != E_NOTIMPL) {
warning("Unable to locate My Pictures directory");
}
return Common::Path();
}
_tcscat(picturesPath, TEXT("\\ScummVM Screenshots\\"));
}
// If the directory already exists (as it should in most cases),
// we don't want to fail, but we need to stop on other errors (such as ERROR_PATH_NOT_FOUND)
if (!CreateDirectory(picturesPath, nullptr)) {
if (GetLastError() != ERROR_ALREADY_EXISTS)
error("Cannot create ScummVM Screenshots folder");
}
return Common::Path(Win32::tcharToString(picturesPath), Common::Path::kNativeSeparator);
}
Common::Path OSystem_Win32::getDefaultConfigFileName() {
TCHAR configFile[MAX_PATH];
// if this is the first time the default config file name is requested
// then we need detect if we should run in portable mode. (and if it's
// never requested before the backend is initialized then a config file
// was provided on the command line and portable mode doesn't apply.)
if (!backendInitialized()) {
_isPortable = detectPortableConfigFile();
}
if (_isPortable) {
// Use the current process directory in portable mode
Win32::getProcessDirectory(configFile, MAX_PATH);
_tcscat(configFile, TEXT("\\" DEFAULT_CONFIG_FILE));
} else {
// Use the Application Data directory of the user profile
if (Win32::getApplicationDataDirectory(configFile)) {
_tcscat(configFile, TEXT("\\" DEFAULT_CONFIG_FILE));
FILE *tmp = nullptr;
if ((tmp = _tfopen(configFile, TEXT("r"))) == nullptr) {
// Check windows directory
TCHAR oldConfigFile[MAX_PATH];
uint ret = GetWindowsDirectory(oldConfigFile, MAX_PATH);
if (ret == 0 || ret > MAX_PATH)
error("Cannot retrieve the path of the Windows directory");
_tcscat(oldConfigFile, TEXT("\\" DEFAULT_CONFIG_FILE));
if ((tmp = _tfopen(oldConfigFile, TEXT("r")))) {
_tcscpy(configFile, oldConfigFile);
fclose(tmp);
}
} else {
fclose(tmp);
}
} else {
// Check windows directory
uint ret = GetWindowsDirectory(configFile, MAX_PATH);
if (ret == 0 || ret > MAX_PATH)
error("Cannot retrieve the path of the Windows directory");
_tcscat(configFile, TEXT("\\" DEFAULT_CONFIG_FILE));
}
}
return Common::Path(Win32::tcharToString(configFile), Common::Path::kNativeSeparator);
}
Common::Path OSystem_Win32::getDefaultLogFileName() {
TCHAR logFile[MAX_PATH];
if (_isPortable) {
Win32::getProcessDirectory(logFile, MAX_PATH);
} else {
// Use the Application Data directory of the user profile
if (!Win32::getApplicationDataDirectory(logFile)) {
return Common::Path();
}
_tcscat(logFile, TEXT("\\Logs"));
CreateDirectory(logFile, nullptr);
}
_tcscat(logFile, TEXT("\\scummvm.log"));
return Common::Path(Win32::tcharToString(logFile), Common::Path::kNativeSeparator);
}
bool OSystem_Win32::detectPortableConfigFile() {
// ScummVM operates in a "portable mode" if there is a config file in the
// same directory as the executable. In this mode, the executable's
// directory is used instead of the user's profile for application files.
// This approach is modeled off of the portable mode in Notepad++.
// Check if there is a config file in the same directory as the executable.
TCHAR portableConfigFile[MAX_PATH];
Win32::getProcessDirectory(portableConfigFile, MAX_PATH);
_tcscat(portableConfigFile, TEXT("\\" DEFAULT_CONFIG_FILE));
FILE *file = _tfopen(portableConfigFile, TEXT("r"));
if (file == nullptr) {
return false;
}
fclose(file);
// Check if we're running from Program Files on Vista+.
// If so then don't attempt to use local files due to UAC.
// (Notepad++ does this too.)
if (Win32::confirmWindowsVersion(6, 0)) {
TCHAR programFiles[MAX_PATH];
if (SHGetFolderPathFunc(nullptr, CSIDL_PROGRAM_FILES, nullptr, SHGFP_TYPE_CURRENT, programFiles) == S_OK) {
_tcscat(portableConfigFile, TEXT("\\"));
if (_tcsstr(portableConfigFile, programFiles) == portableConfigFile) {
return false;
}
}
}
return true;
}
namespace {
class Win32ResourceArchive final : public Common::Archive {
friend BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam);
public:
Win32ResourceArchive();
bool hasFile(const Common::Path &path) const override;
int listMembers(Common::ArchiveMemberList &list) const override;
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
private:
typedef Common::List<Common::Path> FilenameList;
FilenameList _files;
};
BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam) {
if (IS_INTRESOURCE(lpszName))
return TRUE;
Win32ResourceArchive *arch = (Win32ResourceArchive *)lParam;
Common::String filename = Win32::tcharToString(lpszName);
// We use / as path separator in resources
arch->_files.push_back(Common::Path(filename, '/'));
return TRUE;
}
Win32ResourceArchive::Win32ResourceArchive() {
EnumResourceNames(nullptr, MAKEINTRESOURCE(256), &EnumResNameProc, (LONG_PTR)this);
}
bool Win32ResourceArchive::hasFile(const Common::Path &path) const {
for (const auto &curPath : _files) {
if (curPath.equalsIgnoreCase(path))
return true;
}
return false;
}
int Win32ResourceArchive::listMembers(Common::ArchiveMemberList &list) const {
int count = 0;
for (FilenameList::const_iterator i = _files.begin(); i != _files.end(); ++i, ++count)
list.push_back(Common::ArchiveMemberPtr(new Common::GenericArchiveMember(*i, *this)));
return count;
}
const Common::ArchiveMemberPtr Win32ResourceArchive::getMember(const Common::Path &path) const {
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
}
Common::SeekableReadStream *Win32ResourceArchive::createReadStreamForMember(const Common::Path &path) const {
// We store paths in resources using / separator
Common::String name = path.toString('/');
TCHAR *tName = Win32::stringToTchar(name);
HRSRC resource = FindResource(nullptr, tName, MAKEINTRESOURCE(256));
free(tName);
if (resource == nullptr)
return nullptr;
HGLOBAL handle = LoadResource(nullptr, resource);
if (handle == nullptr)
return nullptr;
const byte *data = (const byte *)LockResource(handle);
if (data == nullptr)
return nullptr;
uint32 size = SizeofResource(nullptr, resource);
if (size == 0)
return nullptr;
return new Common::MemoryReadStream(data, size);
}
} // End of anonymous namespace
void OSystem_Win32::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
s.add("Win32Res", new Win32ResourceArchive(), priority);
OSystem_SDL::addSysArchivesToSearchSet(s, priority);
}
AudioCDManager *OSystem_Win32::createAudioCDManager() {
return createWin32AudioCDManager();
}
uint32 OSystem_Win32::getOSDoubleClickTime() const {
return GetDoubleClickTime();
}
// libjpeg-turbo uses SSE instructions that error on at least some Win95 machines.
// These can be disabled with an environment variable. Fixes bug #13643
#if defined(USE_JPEG)
void OSystem_Win32::initializeJpegLibraryForWin95() {
OSVERSIONINFO versionInfo;
ZeroMemory(&versionInfo, sizeof(versionInfo));
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
GetVersionEx(&versionInfo);
// Is Win95?
if (versionInfo.dwMajorVersion == 4 && versionInfo.dwMinorVersion == 0) {
// Disable SSE instructions in libjpeg-turbo.
// This limits detected extensions to 3DNOW and MMX.
_tputenv(TEXT("JSIMD_FORCE3DNOW=1"));
}
}
#endif
#endif

View File

@@ -0,0 +1,77 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_WIN32_H
#define PLATFORM_SDL_WIN32_H
#include "backends/platform/sdl/sdl.h"
#include "backends/platform/sdl/win32/win32-window.h"
class OSystem_Win32 final : public OSystem_SDL {
public:
OSystem_Win32();
void init() override;
void initBackend() override;
#ifdef USE_OPENGL
GraphicsManagerType getDefaultGraphicsManager() const override;
#endif
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0) override;
bool hasFeature(Feature f) override;
bool displayLogFile() override;
bool openUrl(const Common::String &url) override;
void logMessage(LogMessageType::Type type, const char *message) override;
Common::String getSystemLanguage() const override;
// Default paths
Common::Path getDefaultIconsPath() override;
Common::Path getDefaultDLCsPath() override;
Common::Path getScreenshotsPath() override;
protected:
Common::Path getDefaultConfigFileName() override;
Common::Path getDefaultLogFileName() override;
// Override createAudioCDManager() to get our Windows-specific
// version.
AudioCDManager *createAudioCDManager() override;
HWND getHwnd() { return ((SdlWindow_Win32*)_window)->getHwnd(); }
uint32 getOSDoubleClickTime() const override;
private:
bool _isPortable;
bool detectPortableConfigFile();
#if defined(USE_JPEG)
void initializeJpegLibraryForWin95();
#endif
};
#endif

View File

@@ -0,0 +1,129 @@
#
# Windows specific
#
WIN32PATH ?= $(DESTDIR)
clean-win32-resource-embed:
clean: clean-win32-resource-embed
.PHONY: clean-win32-resource-embed
define win32-resource-embed-macro
$(1): configure.stamp $(foreach filename,$($(2)), $(srcdir)/$(filename)) $($(2)_SOURCE)
$(QUIET)echo ' GENERATE' $$@
$(QUIET)mkdir -p $$(dir $$@)
$(QUIET)echo -n '' > $$@
$(QUIET)echo $$(foreach filename,$$($(2)),$$(filename)) | sed -e 's/ /\n/g' | sed -E 's/(.*\/)(.+)/\2 FILE "\1\2"/g' >> $$@
dists/scummvm.o: $(1)
clean-win32-resource-embed-$(1):
$(RM) $(1)
clean-win32-resource-embed: clean-win32-resource-embed-$(1)
.PHONY: clean-win32-resource-embed-$(1)
endef
$(eval $(call win32-resource-embed-macro,dists/scummvm_rc_engine_data_core.rh,DIST_FILES_ENGINEDATA_BASE_CORE))
$(eval $(call win32-resource-embed-macro,dists/scummvm_rc_engine_data.rh,DIST_FILES_ENGINEDATA_BASE))
$(eval $(call win32-resource-embed-macro,dists/scummvm_rc_engine_data_big.rh,DIST_FILES_ENGINEDATA_BASE_BIG))
# Special target to create a win32 snapshot binary (for Inno Setup)
win32-data: all
mkdir -p $(WIN32PATH)
mkdir -p $(WIN32PATH)/doc
mkdir -p $(WIN32PATH)/doc/cz
mkdir -p $(WIN32PATH)/doc/da
mkdir -p $(WIN32PATH)/doc/de
mkdir -p $(WIN32PATH)/doc/es
mkdir -p $(WIN32PATH)/doc/fr
mkdir -p $(WIN32PATH)/doc/it
mkdir -p $(WIN32PATH)/doc/ko
mkdir -p $(WIN32PATH)/doc/no-nb
mkdir -p $(WIN32PATH)/doc/sv
$(STRIP) $(EXECUTABLE) -o $(WIN32PATH)/$(EXECUTABLE)
cp $(srcdir)/AUTHORS $(WIN32PATH)/AUTHORS.txt
cp $(srcdir)/COPYING $(WIN32PATH)/COPYING.txt
cp $(srcdir)/LICENSES/COPYING.Apache $(WIN32PATH)/COPYING.Apache.txt
cp $(srcdir)/LICENSES/COPYING.BSD $(WIN32PATH)/COPYING.BSD.txt
cp $(srcdir)/LICENSES/COPYING.BSL $(WIN32PATH)/COPYING.BSL.txt
cp $(srcdir)/LICENSES/COPYING.GLAD $(WIN32PATH)/COPYING.GLAD.txt
cp $(srcdir)/LICENSES/COPYING.LGPL $(WIN32PATH)/COPYING.LGPL.txt
cp $(srcdir)/LICENSES/COPYING.LUA $(WIN32PATH)/COPYING.LUA.txt
cp $(srcdir)/LICENSES/COPYING.MIT $(WIN32PATH)/COPYING.MIT.txt
cp $(srcdir)/LICENSES/COPYING.MKV $(WIN32PATH)/COPYING.MKV.txt
cp $(srcdir)/LICENSES/COPYING.MPL $(WIN32PATH)/COPYING.MPL.txt
cp $(srcdir)/LICENSES/COPYING.OFL $(WIN32PATH)/COPYING.OFL.txt
cp $(srcdir)/LICENSES/COPYING.ISC $(WIN32PATH)/COPYING.ISC.txt
cp $(srcdir)/LICENSES/COPYING.TINYGL $(WIN32PATH)/COPYING.TINYGL.txt
cp $(srcdir)/LICENSES/CatharonLicense.txt $(WIN32PATH)/CatharonLicense.txt
cp $(srcdir)/COPYRIGHT $(WIN32PATH)/COPYRIGHT.txt
cp $(srcdir)/doc/cz/PrectiMe $(WIN32PATH)/doc/cz/PrectiMe.txt
cp $(srcdir)/doc/QuickStart $(WIN32PATH)/doc/QuickStart.txt
cp $(srcdir)/doc/es/InicioRapido $(WIN32PATH)/doc/es/InicioRapido.txt
cp $(srcdir)/doc/fr/DemarrageRapide $(WIN32PATH)/doc/fr/DemarrageRapide.txt
cp $(srcdir)/doc/it/GuidaRapida $(WIN32PATH)/doc/it/GuidaRapida.txt
cp $(srcdir)/doc/ko/QuickStart $(WIN32PATH)/doc/ko/QuickStart.txt
cp $(srcdir)/doc/no-nb/HurtigStart $(WIN32PATH)/doc/no-nb/HurtigStart.txt
cp $(srcdir)/doc/da/HurtigStart $(WIN32PATH)/doc/da/HurtigStart.txt
cp $(srcdir)/doc/de/Schnellstart $(WIN32PATH)/doc/de/Schnellstart.txt
cp $(srcdir)/doc/sv/Snabbstart $(WIN32PATH)/doc/sv/Snabbstart.txt
ifdef USE_PANDOC
cp NEWS$(PANDOCEXT) $(WIN32PATH)/NEWS.txt
cp README$(PANDOCEXT) $(WIN32PATH)/README.txt
cp doc/de/NEUES$(PANDOCEXT) $(WIN32PATH)/doc/de/NEUES.txt
else
cp $(srcdir)/NEWS.md $(WIN32PATH)/NEWS.txt
cp $(srcdir)/README.md $(WIN32PATH)/README.txt
cp $(srcdir)/doc/de/NEUES.md $(WIN32PATH)/doc/de/NEUES.txt
endif
cp $(srcdir)/doc/de/LIESMICH $(WIN32PATH)/doc/de/LIESMICH.txt
cp $(srcdir)/doc/sv/LasMig $(WIN32PATH)/doc/sv/LasMig.txt
unix2dos $(WIN32PATH)/*.txt
unix2dos $(WIN32PATH)/doc/*.txt
unix2dos $(WIN32PATH)/doc/cz/*.txt
unix2dos $(WIN32PATH)/doc/da/*.txt
unix2dos $(WIN32PATH)/doc/de/*.txt
unix2dos $(WIN32PATH)/doc/es/*.txt
unix2dos $(WIN32PATH)/doc/fr/*.txt
unix2dos $(WIN32PATH)/doc/it/*.txt
unix2dos $(WIN32PATH)/doc/no-nb/*.txt
unix2dos $(WIN32PATH)/doc/sv/*.txt
win32dist: win32-data
mkdir -p $(WIN32PATH)/graphics
cp $(srcdir)/dists/win32/graphics/left.bmp $(WIN32PATH)/graphics
cp $(srcdir)/dists/win32/graphics/scummvm-install.ico $(WIN32PATH)/graphics
cp $(srcdir)/dists/win32/graphics/scummvm-install.bmp $(WIN32PATH)/graphics
cp $(srcdir)/dists/win32/ScummVM.iss $(WIN32PATH)
ifdef WIN32SDLDOCPATH
cp $(WIN32SDLDOCPATH)/README-SDL.txt $(WIN32PATH)/README-SDL.txt
endif
ifdef WIN32SDLPATH
cp $(WIN32SDLPATH)/SDL2.dll $(WIN32PATH)
ifdef USE_SDL_NET
cp $(WIN32SDLPATH)/SDL2_net.dll $(WIN32PATH)
sed -e '/SDL2_net\.dll/ s/^;//' -i $(WIN32PATH)/ScummVM.iss
endif
endif
ifdef WIN32SPARKLEPATH
ifdef USE_SPARKLE
cp $(WIN32SPARKLEPATH)/WinSparkle.dll $(WIN32PATH)
sed -e '/WinSparkle\.dll/ s/^;//' -i $(WIN32PATH)/ScummVM.iss
endif
endif
win32dist-mingw: win32-data
ifneq (,$(findstring peldd,$(LDD)))
$(LDD) $(WIN32PATH)/$(EXECUTABLE) | xargs -I files cp -vu files $(WIN32PATH)
else
ldd $(WIN32PATH)/$(EXECUTABLE) | grep -i mingw | cut -d">" -f2 | cut -d" " -f2 | sort -u | xargs -I files cp -vu files $(WIN32PATH)
endif
.PHONY: win32-data win32dist win32dist-mingw
include $(srcdir)/ports.mk

View File

@@ -0,0 +1,258 @@
/* 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/>.
*
*/
// For _tcscat
#define FORBIDDEN_SYMBOL_EXCEPTION_strcat
#define WIN32_LEAN_AND_MEAN
#include <sdkddkver.h>
#if !defined(_WIN32_IE) || (_WIN32_IE < 0x500)
// required for SHGetSpecialFolderPath and SHGFP_TYPE_CURRENT in shlobj.h
#undef _WIN32_IE
#define _WIN32_IE 0x500
#endif
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x500)
// required for VER_MAJORVERSION, VER_MINORVERSION and VER_GREATER_EQUAL in winnt.h
// set to Windows 2000 which is the minimum needed for these constants
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x500
#endif
#include <windows.h>
#include <shellapi.h> // for CommandLineToArgvW()
#include <shlobj.h>
#include <tchar.h>
#include "common/ptr.h"
#include "common/scummsys.h"
#include "common/textconsole.h"
#include "backends/platform/sdl/win32/win32_wrapper.h"
// VerSetConditionMask, VerifyVersionInfo and SHGetFolderPath didn't appear until Windows 2000,
// so we need to check for them at runtime
ULONGLONG VerSetConditionMaskFunc(ULONGLONG dwlConditionMask, DWORD dwTypeMask, BYTE dwConditionMask) {
typedef ULONGLONG(WINAPI *VerSetConditionMaskFunction)(ULONGLONG conditionMask, DWORD typeMask, BYTE conditionOperator);
VerSetConditionMaskFunction verSetConditionMask = (VerSetConditionMaskFunction)(void *)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "VerSetConditionMask");
if (verSetConditionMask == nullptr)
return 0;
return verSetConditionMask(dwlConditionMask, dwTypeMask, dwConditionMask);
}
BOOL VerifyVersionInfoFunc(LPOSVERSIONINFOEXA lpVersionInformation, DWORD dwTypeMask, DWORDLONG dwlConditionMask) {
typedef BOOL(WINAPI *VerifyVersionInfoFunction)(LPOSVERSIONINFOEXA versionInformation, DWORD typeMask, DWORDLONG conditionMask);
VerifyVersionInfoFunction verifyVersionInfo = (VerifyVersionInfoFunction)(void *)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "VerifyVersionInfoA");
if (verifyVersionInfo == nullptr)
return FALSE;
return verifyVersionInfo(lpVersionInformation, dwTypeMask, dwlConditionMask);
}
HRESULT SHGetFolderPathFunc(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath) {
typedef HRESULT (WINAPI *SHGetFolderPathFunc)(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath);
SHGetFolderPathFunc pSHGetFolderPath = (SHGetFolderPathFunc)(void *)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")),
#ifndef UNICODE
"SHGetFolderPathA"
#else
"SHGetFolderPathW"
#endif
);
if (pSHGetFolderPath)
return pSHGetFolderPath(hwnd, csidl, hToken, dwFlags, pszPath);
typedef BOOL (WINAPI *SHGetSpecialFolderPathFunc)(HWND hwnd, LPTSTR pszPath, int csidl, BOOL fCreate);
SHGetSpecialFolderPathFunc pSHGetSpecialFolderPath = (SHGetSpecialFolderPathFunc)(void *)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")),
#ifndef UNICODE
"SHGetSpecialFolderPathA"
#else
"SHGetSpecialFolderPathW"
#endif
);
if (pSHGetSpecialFolderPath)
return pSHGetSpecialFolderPath(hwnd, pszPath, csidl & ~CSIDL_FLAG_MASK, csidl & CSIDL_FLAG_CREATE) ? S_OK : E_FAIL;
return E_NOTIMPL;
}
namespace Win32 {
bool getApplicationDataDirectory(TCHAR *applicationDataDirectory) {
HRESULT hr = SHGetFolderPathFunc(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, applicationDataDirectory);
if (hr != S_OK) {
if (hr != E_NOTIMPL) {
warning("Unable to locate application data directory");
}
return false;
}
_tcscat(applicationDataDirectory, TEXT("\\ScummVM"));
if (!CreateDirectory(applicationDataDirectory, NULL)) {
if (GetLastError() != ERROR_ALREADY_EXISTS) {
error("Cannot create ScummVM application data folder");
}
}
return true;
}
void getProcessDirectory(TCHAR *processDirectory, DWORD size) {
GetModuleFileName(NULL, processDirectory, size);
processDirectory[size - 1] = '\0'; // termination not guaranteed
// remove executable and final path separator
TCHAR *lastSeparator = _tcsrchr(processDirectory, '\\');
if (lastSeparator != NULL) {
*lastSeparator = '\0';
}
}
bool confirmWindowsVersion(int majorVersion, int minorVersion) {
OSVERSIONINFOEXA versionInfo;
DWORDLONG conditionMask = 0;
ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEXA));
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
versionInfo.dwMajorVersion = majorVersion;
versionInfo.dwMinorVersion = minorVersion;
conditionMask = VerSetConditionMaskFunc(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
conditionMask = VerSetConditionMaskFunc(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
return VerifyVersionInfoFunc(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask);
}
// for using ScopedPtr with malloc/free
template <typename T>
struct Freer {
inline void operator()(T *object) {
free(object);
}
};
bool moveFile(const Common::String &src, const Common::String &dst) {
Common::ScopedPtr<TCHAR, Freer<TCHAR>> tSrc(stringToTchar(src));
Common::ScopedPtr<TCHAR, Freer<TCHAR>> tDst(stringToTchar(dst));
if (MoveFileEx(tSrc.get(), tDst.get(), MOVEFILE_REPLACE_EXISTING)) {
return true;
}
// MoveFileEx may not be supported on the platform (Win9x)
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
// Fall back to deleting the destination before using MoveFile.
// MoveFile requires that the destination not already exist.
DeleteFile(tDst.get());
return MoveFile(tSrc.get(), tDst.get());
}
return false;
}
bool isDriveCD(char driveLetter) {
TCHAR drivePath[] = TEXT("x:\\");
drivePath[0] = (TCHAR)driveLetter;
return (GetDriveType(drivePath) == DRIVE_CDROM);
}
wchar_t *ansiToUnicode(const char *s) {
#ifndef UNICODE
uint codePage = CP_ACP;
#else
uint codePage = CP_UTF8;
#endif
DWORD size = MultiByteToWideChar(codePage, 0, s, -1, nullptr, 0);
if (size > 0) {
LPWSTR result = (LPWSTR)calloc(size, sizeof(WCHAR));
if (MultiByteToWideChar(codePage, 0, s, -1, result, size) != 0)
return result;
}
return nullptr;
}
char *unicodeToAnsi(const wchar_t *s) {
#ifndef UNICODE
uint codePage = CP_ACP;
#else
uint codePage = CP_UTF8;
#endif
DWORD size = WideCharToMultiByte(codePage, 0, s, -1, nullptr, 0, nullptr, nullptr);
if (size > 0) {
char *result = (char *)calloc(size, sizeof(char));
if (WideCharToMultiByte(codePage, 0, s, -1, result, size, nullptr, nullptr) != 0)
return result;
}
return nullptr;
}
TCHAR *stringToTchar(const Common::String& s) {
#ifndef UNICODE
char *t = (char *)malloc(s.size() + 1);
Common::strcpy_s(t, s.size() + 1, s.c_str());
return t;
#else
return ansiToUnicode(s.c_str());
#endif
}
Common::String tcharToString(const TCHAR *t) {
#ifndef UNICODE
return t;
#else
char *utf8 = unicodeToAnsi(t);
Common::String s = utf8;
free(utf8);
return s;
#endif
}
#ifdef UNICODE
char **getArgvUtf8(int *argc) {
// get command line arguments in wide-character
LPWSTR *wargv = CommandLineToArgvW(GetCommandLineW(), argc);
// convert each argument to utf8
char **argv = (char **)malloc((*argc + 1) * sizeof(char *));
for (int i = 0; i < *argc; ++i) {
argv[i] = Win32::unicodeToAnsi(wargv[i]);
}
argv[*argc] = nullptr; // null terminated array
LocalFree(wargv);
return argv;
}
void freeArgvUtf8(int argc, char **argv) {
for (int i = 0; i < argc; ++i) {
free(argv[i]);
}
free(argv);
}
#endif
} // End of namespace Win32

View File

@@ -0,0 +1,147 @@
/* 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/>.
*
*/
#ifndef PLATFORM_SDL_WIN32_WRAPPER_H
#define PLATFORM_SDL_WIN32_WRAPPER_H
#include "common/scummsys.h"
#include "common/str.h"
HRESULT SHGetFolderPathFunc(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath);
// Helper functions
namespace Win32 {
/**
* Gets the full path to the ScummVM application data directory
* in the user's profile and creates it if it doesn't exist.
*
* @param profileDirectory MAX_PATH sized output array
*
* @return True if the user's profile directory was found, false if
* it was not.
*
* @note if the user's profile directory is found but the "ScummVM"
* subdirectory can't be created then this function calls error().
*/
bool getApplicationDataDirectory(TCHAR *profileDirectory);
/**
* Gets the full path to the directory that the currently executing
* process resides in.
*
* @param processDirectory output array
* @param size size in characters of output array
*/
void getProcessDirectory(TCHAR *processDirectory, DWORD size);
/**
* Checks if the current running Windows version is greater or equal to the specified version.
* See: https://docs.microsoft.com/en-us/windows/win32/sysinfo/operating-system-version
*
* @param majorVersion The major version number (x.0)
* @param minorVersion The minor version number (0.x)
*/
bool confirmWindowsVersion(int majorVersion, int minorVersion);
/**
* Moves a file within the same volume. Replaces any existing file.
*/
bool moveFile(const Common::String &src, const Common::String &dst);
/**
* Returns true if the drive letter is a CDROM
*
* @param driveLetter The drive letter to test
*/
bool isDriveCD(char driveLetter);
/**
* Converts a C string into a Windows wide-character string.
* Used to interact with Win32 Unicode APIs with no ANSI fallback.
* If UNICODE is defined then the conversion will use code page CP_UTF8,
* otherwise CP_ACP will be used.
*
* @param s Source string
* @return Converted string
*
* @note Return value must be freed by the caller.
*/
wchar_t *ansiToUnicode(const char *s);
/**
* Converts a Windows wide-character string into a C string.
* Used to interact with Win32 Unicode APIs with no ANSI fallback.
* If UNICODE is defined then the conversion will use code page CP_UTF8,
* otherwise CP_ACP will be used.
*
* @param s Source string
* @return Converted string
*
* @note Return value must be freed by the caller.
*/
char *unicodeToAnsi(const wchar_t *s);
/**
* Converts a Common::String to a TCHAR array for the purpose of passing to
* a Windows API or CRT call. If UNICODE is defined then the string will be
* converted from UTF8 to wide characters, otherwise the character array
* will be copied with no conversion.
*
* @param s Source string
* @return Converted string
*
* @note Return value must be freed by the caller.
*/
TCHAR *stringToTchar(const Common::String& s);
/**
* Converts a TCHAR array returned from a Windows API or CRT call to a Common::String.
* If UNICODE is defined then the wide character array will be converted to UTF8,
* otherwise the char array will be copied with no conversion.
*
* @param s Source string
* @return Converted string
*/
Common::String tcharToString(const TCHAR *s);
#ifdef UNICODE
/**
* Returns command line arguments in argc / argv format in UTF8.
*
* @param argc argument count
* @return argument array
*
* @note Return value must be freed by the caller with freeArgvUtf8()
*/
char **getArgvUtf8(int *argc);
/**
* Frees an argument array created by getArgvUtf8()
*
* @param argc argument count in argv
* @param argv argument array created by getArgvUtf8()
*/
void freeArgvUtf8(int argc, char **argv);
#endif
} // End of namespace Win32
#endif