[Scummvm-cvs-logs] scummvm master -> 2cd0a99e2bc28fa8ec17f782405c4abfd047f5e1
sev-
sev at scummvm.org
Mon May 16 10:05:09 CEST 2016
This automated email contains information about 10 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
e2b9572a83 3DS: Initial commit
fe8d480057 3DS: Add to backend configuration list
f5d73cac8a 3DS: Add CIA format build, add timer handler thread, fix APT service suspending/sleeping/exiting
a0cc562f1f 3DS: Use linear GPU texture downscaling for better legibility in hi-res games
95566ed6e3 3DS: Add backend author to credits
1ea737bbd8 3DS: Maintain alphabetical order in configure file
e8dcfc3a4e 3DS: Fix code styling, add license header, remove unused portdefs.h
bfb9ecec35 3DS: Add README
1531b4ddbf 3DS: Add config class/dialog, c-pad cursor control, and option to disable screens
2cd0a99e2b Merge pull request #745 from Cruel/3ds
Commit: e2b9572a83badb7084f5b54e1a7e108af8e327f6
https://github.com/scummvm/scummvm/commit/e2b9572a83badb7084f5b54e1a7e108af8e327f6
Author: Thomas Edvalson (machin3 at gmail.com)
Date: 2016-04-06T02:12:02-04:00
Commit Message:
3DS: Initial commit
Changed paths:
A backends/platform/3ds/3ds.mk
A backends/platform/3ds/gui.cpp
A backends/platform/3ds/gui.h
A backends/platform/3ds/icon.png
A backends/platform/3ds/main.cpp
A backends/platform/3ds/module.mk
A backends/platform/3ds/osystem-audio.cpp
A backends/platform/3ds/osystem-events.cpp
A backends/platform/3ds/osystem-graphics.cpp
A backends/platform/3ds/osystem.cpp
A backends/platform/3ds/osystem.h
A backends/platform/3ds/portdefs.h
A backends/platform/3ds/shader.v.pica
A backends/platform/3ds/sprite.cpp
A backends/platform/3ds/sprite.h
base/commandLine.cpp
common/scummsys.h
configure
gui/credits.h
diff --git a/backends/platform/3ds/3ds.mk b/backends/platform/3ds/3ds.mk
new file mode 100644
index 0000000..bd8e743
--- /dev/null
+++ b/backends/platform/3ds/3ds.mk
@@ -0,0 +1,53 @@
+TARGET := scummvm
+
+APP_TITLE := ScummVM
+APP_DESCRIPTION := Point-and-click adventure game engines
+APP_AUTHOR := ScummVM Team
+APP_ICON := backends/platform/3ds/icon.png
+
+ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
+CXXFLAGS += -std=gnu++11
+ASFLAGS += -mfloat-abi=hard
+LDFLAGS += -specs=3dsx.specs $(ARCH) -L$(DEVKITPRO)/libctru/lib -L$(DEVKITPRO)/portlibs/3ds/lib
+
+.PHONY: clean_3ds
+
+all: $(TARGET).3dsx
+
+clean: clean_3ds
+
+clean_3ds:
+ $(RM) $(TARGET).3dsx
+
+$(TARGET).smdh: $(APP_ICON) $(MAKEFILE_LIST)
+ @smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@
+ @echo built ... $(notdir $@)
+
+$(TARGET).3dsx: $(EXECUTABLE) $(TARGET).smdh
+ @3dsxtool $< $@ --smdh=$(TARGET).smdh
+ @echo built ... $(notdir $@)
+
+#---------------------------------------------------------------------------------
+# rules for assembling GPU shaders
+#---------------------------------------------------------------------------------
+define shader-as
+ $(eval FILEPATH := $(patsubst %.shbin.o,%.shbin,$@))
+ $(eval FILE := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
+ picasso -o $(FILEPATH) $1
+ bin2s $(FILEPATH) | $(AS) -o $@
+ echo "extern const u8" `(echo $(FILE) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(FILEPATH) | tr . _)`.h
+ echo "extern const u8" `(echo $(FILE) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(FILEPATH) | tr . _)`.h
+ echo "extern const u32" `(echo $(FILE) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(FILEPATH) | tr . _)`.h
+endef
+
+%.shbin.o : %.v.pica %.g.pica
+ @echo $(notdir $^)
+ @$(call shader-as,$^)
+
+%.shbin.o : %.v.pica
+ @echo $(notdir $<)
+ @$(call shader-as,$<)
+
+%.shbin.o : %.shlist
+ @echo $(notdir $<)
+ @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
diff --git a/backends/platform/3ds/gui.cpp b/backends/platform/3ds/gui.cpp
new file mode 100644
index 0000000..0883d5a
--- /dev/null
+++ b/backends/platform/3ds/gui.cpp
@@ -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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "backends/platform/3ds/gui.h"
+#include "common/system.h"
+
+StatusMessageDialog* StatusMessageDialog::_opened = 0;
+
+StatusMessageDialog::StatusMessageDialog(const Common::String &message, uint32 duration)
+ : MessageDialog(message, 0, 0) {
+ _timer = g_system->getMillis() + duration;
+ if (_opened)
+ _opened->close();
+ _opened = this;
+}
+
+void StatusMessageDialog::handleTickle() {
+ MessageDialog::handleTickle();
+ if (g_system->getMillis() > _timer)
+ close();
+}
+
+void StatusMessageDialog::close() {
+ GUI::Dialog::close();
+ if (_opened)
+ _opened = 0;
+}
diff --git a/backends/platform/3ds/gui.h b/backends/platform/3ds/gui.h
new file mode 100644
index 0000000..66c6547
--- /dev/null
+++ b/backends/platform/3ds/gui.h
@@ -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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GUI_3DS_H
+#define GUI_3DS_H
+
+#include "gui/message.h"
+
+class StatusMessageDialog : public GUI::MessageDialog {
+public:
+ StatusMessageDialog(const Common::String &message, uint32 duration);
+
+ void handleTickle();
+
+protected:
+ virtual void close();
+
+ uint32 _timer;
+ static StatusMessageDialog* _opened;
+};
+
+#endif // GUI_3DS_H
diff --git a/backends/platform/3ds/icon.png b/backends/platform/3ds/icon.png
new file mode 100644
index 0000000..07022fb
Binary files /dev/null and b/backends/platform/3ds/icon.png differ
diff --git a/backends/platform/3ds/main.cpp b/backends/platform/3ds/main.cpp
new file mode 100644
index 0000000..4b5dbbb
--- /dev/null
+++ b/backends/platform/3ds/main.cpp
@@ -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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "osystem.h"
+#include <3ds.h>
+
+int main(int argc, char *argv[]) {
+ // Initialize basic libctru stuff
+ gfxInitDefault();
+ cfguInit();
+ osSetSpeedupEnable(true);
+// consoleInit(GFX_TOP, NULL);
+
+ g_system = new OSystem_3DS();
+ assert(g_system);
+
+ // Invoke the actual ScummVM main entry point
+// if (argc > 2)
+// res = scummvm_main(argc-2, &argv[2]);
+// else
+// res = scummvm_main(argc, argv);
+ scummvm_main(0, nullptr);
+
+ delete dynamic_cast<OSystem_3DS*>(g_system);
+
+ cfguExit();
+ gfxExit();
+ return 0;
+}
diff --git a/backends/platform/3ds/module.mk b/backends/platform/3ds/module.mk
new file mode 100644
index 0000000..9c1e26b
--- /dev/null
+++ b/backends/platform/3ds/module.mk
@@ -0,0 +1,16 @@
+MODULE := backends/platform/3ds
+
+MODULE_OBJS := \
+ main.o \
+ shader.shbin.o \
+ sprite.o \
+ gui.o \
+ osystem.o \
+ osystem-graphics.o \
+ osystem-audio.o \
+ osystem-events.o
+
+# 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)))
diff --git a/backends/platform/3ds/osystem-audio.cpp b/backends/platform/3ds/osystem-audio.cpp
new file mode 100644
index 0000000..7ff788b
--- /dev/null
+++ b/backends/platform/3ds/osystem-audio.cpp
@@ -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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "osystem.h"
+
+static bool exitAudioThread = false;
+static bool hasAudio = false;
+
+static void audioThreadFunc(void* arg) {
+ Audio::MixerImpl *mixer = (Audio::MixerImpl *) arg;
+ OSystem_3DS *osys = (OSystem_3DS*)g_system;
+
+ int i;
+ const int channel = 0;
+ int bufferIndex = 0;
+ const int bufferCount = 3;
+ const int bufferSize = 80000; // Can't be too small, based on delayMillis duration
+ const int sampleRate = 22050;
+ int sampleLen = 0;
+ uint32 lastTime = osys->getMillis(true);
+ uint32 time = lastTime;
+ ndspWaveBuf buffers[bufferCount];
+
+ for(i = 0; i < bufferCount; ++i) {
+ memset(&buffers[i], 0, sizeof(ndspWaveBuf));
+ buffers[i].data_vaddr = linearAlloc(bufferSize);
+ buffers[i].looping = false;
+ buffers[i].status = NDSP_WBUF_FREE;
+ }
+
+ ndspChnReset(channel);
+ ndspChnSetInterp(channel, NDSP_INTERP_LINEAR);
+ ndspChnSetRate(channel, sampleRate);
+ ndspChnSetFormat(channel, NDSP_FORMAT_STEREO_PCM16);
+
+ while(!exitAudioThread) {
+ bufferIndex++;
+ bufferIndex %= bufferCount;
+ ndspWaveBuf* buf = &buffers[bufferIndex];
+
+ osys->delayMillis(100); // Note: Increasing the delay requires a bigger buffer
+
+ time = osys->getMillis(true);
+ sampleLen = (time - lastTime) * 22 * 4; // sampleRate / 1000 * channelCount * sizeof(int16);
+ lastTime = time;
+
+ if (sampleLen > 0) {
+ buf->nsamples = mixer->mixCallback(buf->data_adpcm, sampleLen);
+ if (buf->nsamples > 0) {
+ DSP_FlushDataCache(buf->data_vaddr, bufferSize);
+ ndspChnWaveBufAdd(channel, buf);
+ }
+ }
+ }
+
+ for(i = 0; i < bufferCount; ++i)
+ linearFree(buffers[i].data_pcm8);
+}
+
+void OSystem_3DS::initAudio() {
+ _mixer = new Audio::MixerImpl(this, 22050);
+
+ hasAudio = R_SUCCEEDED(ndspInit());
+ _mixer->setReady(false);
+
+ if (hasAudio) {
+ s32 prio = 0;
+ svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
+ audioThread = threadCreate(&audioThreadFunc, _mixer, 32*1048, prio-1, -2, false);
+ }
+}
+
+void OSystem_3DS::destroyAudio() {
+ if (hasAudio) {
+ exitAudioThread = true;
+ threadJoin(audioThread, U64_MAX);
+ threadFree(audioThread);
+ ndspExit();
+ }
+
+ delete _mixer;
+ _mixer = 0;
+}
+
+Audio::Mixer *OSystem_3DS::getMixer() {
+ assert(_mixer);
+ return _mixer;
+}
diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
new file mode 100644
index 0000000..a4ce92c
--- /dev/null
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -0,0 +1,194 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "backends/platform/3ds/gui.h"
+#include "osystem.h"
+
+static Common::Mutex *eventMutex;
+static bool exitEventThread = false;
+static InputMode inputMode = MODE_DRAG;
+
+static void pushEventQueue(Common::Queue<Common::Event>* queue, Common::Event& event) {
+ Common::StackLock lock(*eventMutex);
+ queue->push(event);
+}
+
+static void eventThreadFunc(void* arg) {
+ OSystem_3DS* osys = (OSystem_3DS*) g_system;
+ auto eventQueue = (Common::Queue<Common::Event>*) arg;
+
+ uint32 touchStartTime = osys->getMillis();
+ touchPosition lastTouch = {0,0};
+ bool isRightClick = false;
+ Common::Event event;
+
+ while(!exitEventThread) {
+ osys->delayMillis(10);
+
+ hidScanInput();
+ touchPosition touch;
+ u32 held = hidKeysHeld();
+ u32 keysPressed = hidKeysDown();
+ u32 keysReleased = hidKeysUp();
+
+ if (!aptMainLoop()) {
+ event.type = Common::EVENT_QUIT;
+ pushEventQueue(eventQueue, event);
+ }
+ if (held & KEY_TOUCH) {
+ hidTouchRead(&touch);
+ osys->transformPoint(touch);
+
+ osys->warpMouse(touch.px, touch.py);
+ event.mouse.x = touch.px;
+ event.mouse.y = touch.py;
+
+ if (keysPressed & KEY_TOUCH) {
+ touchStartTime = osys->getMillis();
+ isRightClick = (held & KEY_X || held & KEY_DUP);
+ if (inputMode == MODE_DRAG) {
+ event.type = isRightClick ? Common::EVENT_RBUTTONDOWN : Common::EVENT_LBUTTONDOWN;
+ pushEventQueue(eventQueue, event);
+ }
+ }
+ else if (touch.px != lastTouch.px || touch.py != lastTouch.py) {
+ event.type = Common::EVENT_MOUSEMOVE;
+ pushEventQueue(eventQueue, event);
+ }
+
+ lastTouch = touch;
+ }
+ else if (keysReleased & KEY_TOUCH) {
+ event.mouse.x = lastTouch.px;
+ event.mouse.y = lastTouch.py;
+ printf("clicked %u, %u\n", lastTouch.px, lastTouch.py);
+ if (inputMode == MODE_DRAG) {
+ event.type = isRightClick ? Common::EVENT_RBUTTONUP : Common::EVENT_LBUTTONUP;
+ pushEventQueue(eventQueue, event);
+ }
+ else if (osys->getMillis() - touchStartTime < 200) {
+ // Process click in MODE_HOVER
+ event.type = Common::EVENT_MOUSEMOVE;
+ pushEventQueue(eventQueue, event);
+ event.type = isRightClick ? Common::EVENT_RBUTTONDOWN : Common::EVENT_LBUTTONDOWN;
+ pushEventQueue(eventQueue, event);
+ event.type = isRightClick ? Common::EVENT_RBUTTONUP : Common::EVENT_LBUTTONUP;
+ pushEventQueue(eventQueue, event);
+ }
+ }
+ if (keysPressed & KEY_R) {
+ if (inputMode == MODE_DRAG) {
+ inputMode = MODE_HOVER;
+ osys->displayMessageOnOSD("Hover Mode");
+ } else {
+ inputMode = MODE_DRAG;
+ osys->displayMessageOnOSD("Drag Mode");
+ }
+ }
+ if (keysPressed & KEY_A || keysPressed & KEY_DLEFT) {
+ // SIMULATE LEFT CLICK
+ event.mouse.x = lastTouch.px;
+ event.mouse.y = lastTouch.py;
+ event.type = Common::EVENT_LBUTTONDOWN;
+ pushEventQueue(eventQueue, event);
+ event.type = Common::EVENT_LBUTTONUP;
+ pushEventQueue(eventQueue, event);
+ }
+ if (keysPressed & KEY_X || keysPressed & KEY_DUP) {
+ // SIMULATE RIGHT CLICK
+ event.mouse.x = lastTouch.px;
+ event.mouse.y = lastTouch.py;
+ event.type = Common::EVENT_RBUTTONDOWN;
+ pushEventQueue(eventQueue, event);
+ event.type = Common::EVENT_RBUTTONUP;
+ pushEventQueue(eventQueue, event);
+ }
+ if (keysPressed & KEY_L) {
+ event.type = Common::EVENT_VIRTUAL_KEYBOARD;
+ pushEventQueue(eventQueue, event);
+ }
+ if (keysPressed & KEY_START) {
+ event.type = Common::EVENT_MAINMENU;
+ pushEventQueue(eventQueue, event);
+ }
+ if (keysPressed & KEY_SELECT) {
+ event.type = Common::EVENT_RTL;
+ pushEventQueue(eventQueue, event);
+ }
+ if (keysPressed & KEY_B || keysReleased & KEY_B || keysPressed & KEY_DDOWN || keysReleased & KEY_DDOWN) {
+ if (keysPressed & KEY_B || keysPressed & KEY_DDOWN)
+ event.type = Common::EVENT_KEYDOWN;
+ else
+ event.type = Common::EVENT_KEYUP;
+ event.kbd.keycode = Common::KEYCODE_ESCAPE;
+ event.kbd.ascii = Common::ASCII_ESCAPE;
+ event.kbd.flags = 0;
+ pushEventQueue(eventQueue, event);
+ }
+
+ // TODO: EVENT_PREDICTIVE_DIALOG
+ // EVENT_SCREEN_CHANGED
+ }
+}
+
+void OSystem_3DS::initEvents() {
+ eventMutex = new Common::Mutex();
+ s32 prio = 0;
+ svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
+ _eventThread = threadCreate(&eventThreadFunc, &_eventQueue, 2048, prio-1, -2, false);
+}
+
+void OSystem_3DS::destroyEvents() {
+ exitEventThread = true;
+ threadJoin(_eventThread, U64_MAX);
+ threadFree(_eventThread);
+ delete eventMutex;
+}
+
+void OSystem_3DS::transformPoint(touchPosition &point) {
+ if (!_overlayVisible) {
+ point.px = static_cast<float>(point.px) / _gameTexture.getScaleX() - _gameX;
+ point.py = static_cast<float>(point.py) / _gameTexture.getScaleY() - _gameY;
+ }
+}
+
+void OSystem_3DS::displayMessageOnOSD(const char *msg) {
+ _messageOSD = msg;
+ _showMessageOSD = true;
+}
+
+bool OSystem_3DS::pollEvent(Common::Event &event) {
+ if (_showMessageOSD) {
+ _showMessageOSD = false;
+ StatusMessageDialog dialog(_messageOSD, 800);
+ dialog.runModal();
+ }
+
+ Common::StackLock lock(*eventMutex);
+
+ if (_eventQueue.empty())
+ return false;
+
+ event = _eventQueue.pop();
+ return true;
+}
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
new file mode 100644
index 0000000..5e70dce
--- /dev/null
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -0,0 +1,465 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This _program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This _program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this _program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ */
+
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "backends/platform/3ds/osystem.h"
+#include "backends/platform/3ds/shader_shbin.h"
+#include <common/rect.h>
+#include <algorithm>
+
+// Used to transfer the final rendered display to the framebuffer
+#define DISPLAY_TRANSFER_FLAGS \
+ (GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | \
+ GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | \
+ GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
+ GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
+
+void OSystem_3DS::initGraphics() {
+ _pfGame = Graphics::PixelFormat::createFormatCLUT8();
+ _pfGameTexture = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
+
+ C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
+
+ // Initialize the render targets
+ _renderTargetTop =
+ C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
+ C3D_RenderTargetSetClear(_renderTargetTop, C3D_CLEAR_ALL, 0x0000000, 0);
+ C3D_RenderTargetSetOutput(_renderTargetTop, GFX_TOP, GFX_LEFT,
+ DISPLAY_TRANSFER_FLAGS);
+
+ _renderTargetBottom =
+ C3D_RenderTargetCreate(240, 320, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
+ C3D_RenderTargetSetClear(_renderTargetBottom, C3D_CLEAR_ALL, 0x00000000, 0);
+ C3D_RenderTargetSetOutput(_renderTargetBottom, GFX_BOTTOM, GFX_LEFT,
+ DISPLAY_TRANSFER_FLAGS);
+
+ // Load and bind simple default shader (shader.v.pica)
+ _dvlb = DVLB_ParseFile((u32*)shader_shbin, shader_shbin_size);
+ shaderProgramInit(&_program);
+ shaderProgramSetVsh(&_program, &_dvlb->DVLE[0]);
+ C3D_BindProgram(&_program);
+
+ _projectionLocation = shaderInstanceGetUniformLocation(_program.vertexShader, "projection");
+ _modelviewLocation = shaderInstanceGetUniformLocation(_program.vertexShader, "modelView");
+
+ C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
+ AttrInfo_Init(attrInfo);
+ AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position
+ AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=texcoord
+
+ Mtx_OrthoTilt(&_projectionTop, 0.0, 400.0, 240.0, 0.0, 0.0, 1.0);
+ Mtx_OrthoTilt(&_projectionBottom, 0.0, 320.0, 240.0, 0.0, 0.0, 1.0);
+
+ C3D_TexEnv* env = C3D_GetTexEnv(0);
+ C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, 0, 0);
+ C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
+ C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
+
+ C3D_DepthTest(false, GPU_GEQUAL, GPU_WRITE_ALL);
+ C3D_CullFace(GPU_CULL_NONE);
+}
+
+void OSystem_3DS::destroyGraphics() {
+ _gameScreen.free();
+ _gameTexture.free();
+ _overlay.free();
+
+ shaderProgramFree(&_program);
+ DVLB_Free(_dvlb);
+
+ C3D_RenderTargetDelete(_renderTargetTop);
+ C3D_RenderTargetDelete(_renderTargetBottom);
+
+ C3D_Fini();
+}
+
+bool OSystem_3DS::hasFeature(OSystem::Feature f) {
+ return (f == OSystem::kFeatureFullscreenMode ||
+ f == OSystem::kFeatureCursorPalette ||
+ f == OSystem::kFeatureOverlaySupportsAlpha);
+}
+
+void OSystem_3DS::setFeatureState(OSystem::Feature f, bool enable) {
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ _isFullscreen = enable;
+ break;
+ case OSystem::kFeatureCursorPalette:
+ _cursorPaletteEnabled = enable;
+ flushCursor();
+ break;
+ default:
+ break;
+ }
+}
+
+bool OSystem_3DS::getFeatureState(OSystem::Feature f) {
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ return _isFullscreen;
+ case OSystem::kFeatureCursorPalette:
+ return _cursorPaletteEnabled;
+ default:
+ return false;
+ }
+}
+
+const OSystem::GraphicsMode *
+OSystem_3DS::getSupportedGraphicsModes() const {
+ return s_graphicsModes;
+}
+
+int OSystem_3DS::getDefaultGraphicsMode() const {
+ return GFX_LINEAR;
+}
+
+bool OSystem_3DS::setGraphicsMode(int mode) {
+ return true;
+}
+
+void OSystem_3DS::resetGraphicsScale() {
+ printf("resetGraphicsScale\n");
+}
+
+int OSystem_3DS::getGraphicsMode() const {
+ return GFX_LINEAR;
+}
+void OSystem_3DS::initSize(uint width, uint height,
+ const Graphics::PixelFormat *format) {
+ printf("3ds initsize w:%d h:%d\n", width, height);
+ _gameWidth = width;
+ _gameHeight = height;
+ _gameTexture.create(width, height, _pfGameTexture);
+ _overlay.create(getOverlayWidth(), getOverlayHeight(), _pfGameTexture);
+
+ if (format) {
+ printf("pixelformat: %d %d %d %d %d\n", format->bytesPerPixel, format->rBits(), format->gBits(), format->bBits(), format->aBits());;
+ _pfGame = *format;
+ }
+
+ _gameScreen.create(width, height, _pfGame);
+
+ _focusDirty = true;
+ _focusRect = Common::Rect(_gameWidth, _gameHeight);
+
+ if (_isFullscreen) {
+ _gameRatio = 320.f / 240.f;
+ _gameX = _gameY = 0;
+ _gameTexture.setScale(320.f / width, 240.f / height);
+ } else {
+ _gameRatio = static_cast<float>(width) / height;
+ if (width > height) {
+ _gameX = 0;
+ _gameY = (240.f - 320.f / width * height) / 2.f;
+ } else {
+ _gameY = 0;
+ _gameX = (320.f - 240.f / height * width) / 2.f;
+ }
+ _gameTexture.setScale((width > 320) ? 320.f / width : 1.f,
+ (height > 240) ? 240.f / height : 1.f);
+ }
+ _gameTexture.setPosition(_gameX, _gameY);
+ _cursorTexture.setScale(_gameTexture.getScaleX(), _gameTexture.getScaleY());
+}
+
+Common::List<Graphics::PixelFormat> OSystem_3DS::getSupportedFormats() const {
+ Common::List<Graphics::PixelFormat> list;
+ list.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); // GPU_RGBA8
+ list.push_back(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); // GPU_RGB565
+// list.push_back(Graphics::PixelFormat(3, 0, 0, 0, 8, 0, 8, 16, 0)); // GPU_RGB8
+ list.push_back(Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); // RGB555 (needed for FMTOWNS?)
+ list.push_back(Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)); // GPU_RGBA5551
+ list.push_back(Graphics::PixelFormat::createFormatCLUT8());
+ return list;
+}
+
+void OSystem_3DS::beginGFXTransaction() {
+ //
+}
+OSystem::TransactionError OSystem_3DS::endGFXTransaction() {
+ return OSystem::kTransactionSuccess;
+}
+
+void OSystem_3DS::setPalette(const byte *colors, uint start, uint num) {
+// printf("setPalette\n");
+ assert(start + num <= 256);
+ memcpy(_palette + 3 * start, colors, 3 * num);
+
+ // Manually update all color that were changed
+ if (_gameScreen.format.bytesPerPixel == 1) {
+ flushGameScreen();
+ }
+}
+void OSystem_3DS::grabPalette(byte *colors, uint start, uint num) {
+// printf("grabPalette\n");
+ assert(start + num <= 256);
+ memcpy(colors, _palette + 3 * start, 3 * num);
+}
+
+void OSystem_3DS::copyRectToScreen(const void *buf, int pitch, int x,
+ int y, int w, int h) {
+ Common::Rect rect(x, y, x+w, y+h);
+ _gameScreen.copyRectToSurface(buf, pitch, x, y, w, h);
+ Graphics::Surface subSurface = _gameScreen.getSubArea(rect);
+
+ Graphics::Surface *convertedSubSurface = subSurface.convertTo(_pfGameTexture, _palette);
+ _gameTexture.copyRectToSurface(*convertedSubSurface, x, y, Common::Rect(w, h));
+
+ convertedSubSurface->free();
+ delete convertedSubSurface;
+ _gameTexture.markDirty();
+}
+
+void OSystem_3DS::flushGameScreen() {
+ Graphics::Surface *converted = _gameScreen.convertTo(_pfGameTexture, _palette);
+ _gameTexture.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
+ _gameTexture.markDirty();
+ converted->free();
+ delete converted;
+}
+
+Graphics::Surface *OSystem_3DS::lockScreen() {
+ printf("lockScreen\n");
+ return &_gameScreen;
+}
+void OSystem_3DS::unlockScreen() {
+ printf("unlockScreen\n");
+ flushGameScreen();
+}
+
+void OSystem_3DS::updateScreen() {
+
+ updateFocus();
+
+ C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
+ // Render top screen
+ C3D_FrameDrawOn(_renderTargetTop);
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionTop);
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, &_focusMatrix);
+ _gameTexture.render();
+ _gameTexture.render();
+
+ // Render bottom screen
+ C3D_FrameDrawOn(_renderTargetBottom);
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionBottom);
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _gameTexture.getMatrix());
+ _gameTexture.render();
+ if (_overlayVisible) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
+ _overlay.render();
+ }
+ if (_cursorVisible) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
+ _cursorTexture.render();
+ }
+ C3D_FrameEnd(0);
+}
+
+void OSystem_3DS::setShakePos(int shakeOffset) {
+ // TODO: implement this in overlay, top screen, and mouse too
+ _screenShakeOffset = shakeOffset;
+ _gameTexture.setPosition(_gameX, _gameY + shakeOffset);
+}
+
+void OSystem_3DS::setFocusRectangle(const Common::Rect &rect) {
+// printf("setfocus: %d %d %d %d\n", rect.left, rect.top, rect.width(), rect.height());
+ _focusRect = rect;
+ _focusDirty = true;
+ _focusClearTime = 0;
+}
+
+void OSystem_3DS::clearFocusRectangle() {
+ _focusClearTime = getMillis();
+}
+
+void OSystem_3DS::updateFocus() {
+
+ if (_focusClearTime && getMillis() - _focusClearTime > 5000) {
+ _focusClearTime = 0;
+ _focusDirty = true;
+ _focusRect = Common::Rect(_gameWidth, _gameHeight);
+ }
+
+ if (_focusDirty) {
+ float duration = 1.f / 20.f; // Focus animation in frame duration
+ float w = 400.f;
+ float h = 240.f;
+ float ratio = _focusRect.width() / _focusRect.height();
+ if (ratio > w/h) {
+ _focusTargetScaleX = w / _focusRect.width();
+ float newHeight = (float)_focusRect.width() / w/h;
+ _focusTargetScaleY = h / newHeight;
+ _focusTargetPosX = _focusTargetScaleX * _focusRect.left;
+ _focusTargetPosY = _focusTargetScaleY * ((float)_focusRect.top - (newHeight - _focusRect.height())/2.f);
+ } else {
+ _focusTargetScaleY = h / _focusRect.height();
+ float newWidth = (float)_focusRect.height() * w/h;
+ _focusTargetScaleX = w / newWidth;
+ _focusTargetPosY = _focusTargetScaleY * _focusRect.top;
+ _focusTargetPosX = _focusTargetScaleX * ((float)_focusRect.left - (newWidth - _focusRect.width())/2.f);
+ }
+ if (_focusTargetPosX < 0 && _focusTargetScaleY != 240.f / _gameHeight)
+ _focusTargetPosX = 0;
+ if (_focusTargetPosY < 0 && _focusTargetScaleX != 400.f / _gameWidth)
+ _focusTargetPosY = 0;
+ _focusStepPosX = duration * (_focusTargetPosX - _focusPosX);
+ _focusStepPosY = duration * (_focusTargetPosY - _focusPosY);
+ _focusStepScaleX = duration * (_focusTargetScaleX - _focusScaleX);
+ _focusStepScaleY = duration * (_focusTargetScaleY - _focusScaleY);
+ }
+
+ if (_focusDirty || _focusPosX != _focusTargetPosX || _focusPosY != _focusTargetPosY ||
+ _focusScaleX != _focusTargetScaleX || _focusScaleY != _focusTargetScaleY) {
+ _focusDirty = false;
+
+ if ((_focusStepPosX > 0 && _focusPosX > _focusTargetPosX) || (_focusStepPosX < 0 && _focusPosX < _focusTargetPosX))
+ _focusPosX = _focusTargetPosX;
+ else if (_focusPosX != _focusTargetPosX)
+ _focusPosX += _focusStepPosX;
+
+ if ((_focusStepPosY > 0 && _focusPosY > _focusTargetPosY) || (_focusStepPosY < 0 && _focusPosY < _focusTargetPosY))
+ _focusPosY = _focusTargetPosY;
+ else if (_focusPosY != _focusTargetPosY)
+ _focusPosY += _focusStepPosY;
+
+ if ((_focusStepScaleX > 0 && _focusScaleX > _focusTargetScaleX) || (_focusStepScaleX < 0 && _focusScaleX < _focusTargetScaleX))
+ _focusScaleX = _focusTargetScaleX;
+ else if (_focusScaleX != _focusTargetScaleX)
+ _focusScaleX += _focusStepScaleX;
+
+ if ((_focusStepScaleY > 0 && _focusScaleY > _focusTargetScaleY) || (_focusStepScaleY < 0 && _focusScaleY < _focusTargetScaleY))
+ _focusScaleY = _focusTargetScaleY;
+ else if (_focusScaleY != _focusTargetScaleY)
+ _focusScaleY += _focusStepScaleY;
+
+ Mtx_Identity(&_focusMatrix);
+ Mtx_Translate(&_focusMatrix, -_focusPosX, -_focusPosY, 0);
+ Mtx_Scale(&_focusMatrix, _focusScaleX, _focusScaleY, 1.f);
+ }
+}
+
+void OSystem_3DS::showOverlay() {
+ _overlayVisible = true;
+ _cursorTexture.setScale(1.f, 1.f);
+ updateScreen();
+}
+
+void OSystem_3DS::hideOverlay() {
+ _overlayVisible = false;
+ _cursorTexture.setScale(_gameTexture.getScaleX(), _gameTexture.getScaleY());
+ updateScreen();
+}
+
+Graphics::PixelFormat OSystem_3DS::getOverlayFormat() const {
+ return _pfGameTexture;
+}
+
+void OSystem_3DS::clearOverlay() {
+ _overlay.clear();
+}
+
+void OSystem_3DS::grabOverlay(void *buf, int pitch) {
+ for(int y = 0; y < getOverlayHeight(); ++y) {
+ memcpy(buf, _overlay.getBasePtr(0, y), pitch);
+ }
+}
+
+void OSystem_3DS::copyRectToOverlay(const void *buf, int pitch, int x,
+ int y, int w, int h) {
+ _overlay.copyRectToSurface(buf, pitch, x, y, w, h);
+ _overlay.markDirty();
+}
+
+int16 OSystem_3DS::getOverlayHeight() {
+ return 240;
+}
+
+int16 OSystem_3DS::getOverlayWidth() {
+ return 320;
+}
+
+bool OSystem_3DS::showMouse(bool visible) {
+ _cursorVisible = visible;
+ flushCursor();
+ return !visible;
+}
+
+void OSystem_3DS::warpMouse(int x, int y) {
+ _cursorX = x;
+ _cursorY = y;
+ // TODO: adjust for _cursorScalable ?
+ _cursorTexture.setPosition(x - _cursorHotspotX + (_overlayVisible ? 0 : _gameX),
+ y - _cursorHotspotY + (_overlayVisible ? 0 : _gameY));
+}
+
+void OSystem_3DS::setMouseCursor(const void *buf, uint w, uint h,
+ int hotspotX, int hotspotY,
+ uint32 keycolor, bool dontScale,
+ const Graphics::PixelFormat *format) {
+ _cursorScalable = !dontScale;
+ _cursorHotspotX = hotspotX;
+ _cursorHotspotY = hotspotY;
+ _cursorKeyColor = keycolor;
+ _pfCursor = !format ? Graphics::PixelFormat::createFormatCLUT8() : *format;
+
+ if (w != _cursor.w || h != _cursor.h || _cursor.format != _pfCursor) {
+ _cursor.create(w, h, _pfCursor);
+ _cursorTexture.create(w, h, _pfGameTexture);
+ }
+
+ _cursor.copyRectToSurface(buf, w, 0, 0, w, h);
+ flushCursor();
+
+ warpMouse(_cursorX, _cursorY);
+}
+
+void OSystem_3DS::setCursorPalette(const byte *colors, uint start, uint num) {
+ assert(start + num <= 256);
+ memcpy(_cursorPalette + 3 * start, colors, 3 * num);
+ _cursorPaletteEnabled = true;
+ flushCursor();
+}
+
+void OSystem_3DS::flushCursor() {
+ if (_cursor.getPixels()) {
+ Graphics::Surface *converted = _cursor.convertTo(_pfGameTexture, _cursorPaletteEnabled ? _cursorPalette : _palette);
+ _cursorTexture.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
+ _cursorTexture.markDirty();
+ converted->free();
+ delete converted;
+
+ if (_pfCursor.bytesPerPixel == 1) {
+ uint* dest = (uint*) _cursorTexture.getPixels();
+ byte* src = (byte*) _cursor.getPixels();
+ for (int y = 0; y < _cursor.h; ++y) {
+ for (int x = 0; x < _cursor.w; ++x) {
+ if (*src++ == _cursorKeyColor)
+ *dest++ = 0;
+ else
+ dest++;
+ }
+ dest += _cursorTexture.w - _cursorTexture.actualWidth;
+ }
+ }
+ }
+}
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
new file mode 100644
index 0000000..fa2980a
--- /dev/null
+++ b/backends/platform/3ds/osystem.cpp
@@ -0,0 +1,173 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "osystem.h"
+
+#include "backends/saves/default/default-saves.h"
+#include "backends/timer/default/default-timer.h"
+#include "backends/events/default/default-events.h"
+#include "audio/mixer_intern.h"
+#include "common/scummsys.h"
+#include "common/config-manager.h"
+#include "common/str.h"
+
+#include "backends/fs/posix/posix-fs-factory.h"
+#include "backends/fs/posix/posix-fs.h"
+#include <unistd.h>
+#include <time.h>
+
+OSystem_3DS::OSystem_3DS():
+_focusDirty(true),
+_focusRect(Common::Rect(1,1)),
+_focusPosX(0),
+_focusPosY(0),
+_focusTargetPosX(0),
+_focusTargetPosY(0),
+_focusStepPosX(0),
+_focusStepPosY(0),
+_focusScaleX(1.f),
+_focusScaleY(1.f),
+_focusTargetScaleX(1.f),
+_focusTargetScaleY(1.f),
+_focusStepScaleX(0.f),
+_focusStepScaleY(0.f),
+_focusClearTime(0),
+_showMessageOSD(false),
+_isFullscreen(false),
+_cursorVisible(false),
+_cursorScalable(false),
+_cursorPaletteEnabled(false),
+_cursorX(0),
+_cursorY(0),
+_cursorHotspotX(0),
+_cursorHotspotY(0),
+_gameX(0),
+_gameY(0),
+_gameWidth(320),
+_gameHeight(240) {
+ chdir("/");
+ _fsFactory = new POSIXFilesystemFactory();
+ Posix::assureDirectoryExists("/3ds/scummvm/saves/");
+}
+
+OSystem_3DS::~OSystem_3DS() {
+ destroyEvents();
+ destroyAudio();
+ destroyGraphics();
+
+ delete _timerManager;
+ _timerManager = 0;
+}
+
+void OSystem_3DS::quit() {
+ //
+}
+
+void OSystem_3DS::initBackend() {
+ ConfMan.registerDefault("fullscreen", true);
+ ConfMan.registerDefault("aspect_ratio", true);
+ if (!ConfMan.hasKey("vkeybd_pack_name"))
+ ConfMan.set("vkeybd_pack_name", "vkeybd_small");
+ if (!ConfMan.hasKey("vkeybdpath"))
+ ConfMan.set("vkeybdpath", "/3ds/scummvm/kb");
+ if (!ConfMan.hasKey("themepath"))
+ ConfMan.set("themepath", "/3ds/scummvm");
+ if (!ConfMan.hasKey("gui_theme"))
+ ConfMan.set("gui_theme", "builtin");
+
+ _timerManager = new DefaultTimerManager();
+ _savefileManager = new DefaultSaveFileManager("/3ds/scummvm/saves/");
+
+ initGraphics();
+ initAudio();
+ initEvents();
+ EventsBaseBackend::initBackend();
+}
+
+Common::String OSystem_3DS::getDefaultConfigFileName() {
+ return "/3ds/scummvm/scummvm.ini";
+}
+
+uint32 OSystem_3DS::getMillis(bool skipRecord) {
+ return svcGetSystemTick() / TICKS_PER_MSEC;
+}
+
+void OSystem_3DS::delayMillis(uint msecs) {
+ svcSleepThread(msecs * 1000000);
+}
+
+void OSystem_3DS::getTimeAndDate(TimeDate& td) const {
+ time_t curTime = time(0);
+ struct tm t = *localtime(&curTime);
+ td.tm_sec = t.tm_sec;
+ td.tm_min = t.tm_min;
+ td.tm_hour = t.tm_hour;
+ td.tm_mday = t.tm_mday;
+ td.tm_mon = t.tm_mon;
+ td.tm_year = t.tm_year;
+ td.tm_wday = t.tm_wday;
+}
+
+OSystem::MutexRef OSystem_3DS::createMutex() {
+ RecursiveLock* mutex = new RecursiveLock();
+ RecursiveLock_Init(mutex);
+ return (OSystem::MutexRef) mutex;
+}
+void OSystem_3DS::lockMutex(MutexRef mutex) {
+ RecursiveLock_Lock((RecursiveLock *)mutex);
+}
+void OSystem_3DS::unlockMutex(MutexRef mutex) {
+ RecursiveLock_Unlock((RecursiveLock *)mutex);
+}
+void OSystem_3DS::deleteMutex(MutexRef mutex) {
+ delete (RecursiveLock *)mutex;
+}
+
+Common::String OSystem_3DS::getSystemLanguage() const {
+ u8 langcode;
+ CFGU_GetSystemLanguage(&langcode);
+ switch (langcode) {
+ case CFG_LANGUAGE_JP: return "ja_JP";
+ case CFG_LANGUAGE_EN: return "en_US";
+ case CFG_LANGUAGE_FR: return "fr_FR";
+ case CFG_LANGUAGE_DE: return "de_DE";
+ case CFG_LANGUAGE_IT: return "it_IT";
+ case CFG_LANGUAGE_ES: return "es_ES";
+ case CFG_LANGUAGE_ZH: return "zh_CN";
+ case CFG_LANGUAGE_KO: return "ko_KR";
+ case CFG_LANGUAGE_NL: return "nl_NL";
+ case CFG_LANGUAGE_PT: return "pt_BR";
+ case CFG_LANGUAGE_RU: return "ru_RU";
+ case CFG_LANGUAGE_TW: return "zh_HK";
+ default: return "en_US";
+ }
+}
+
+void OSystem_3DS::fatalError() {
+ printf("FatalError!\n");
+}
+
+void OSystem_3DS::logMessage(LogMessageType::Type type, const char *message) {
+ printf("3DS log: %s\n", message);
+}
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
new file mode 100644
index 0000000..98d9ad0
--- /dev/null
+++ b/backends/platform/3ds/osystem.h
@@ -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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PLATFORM_3DS_H
+#define PLATFORM_3DS_H
+
+#include <citro3d.h>
+#include "backends/mutex/mutex.h"
+#include "backends/base-backend.h"
+#include "graphics/palette.h"
+#include "base/main.h"
+#include "audio/mixer_intern.h"
+#include "backends/graphics/graphics.h"
+#include "backends/platform/3ds/sprite.h"
+#include "common/rect.h"
+#include "common/queue.h"
+
+#define TICKS_PER_MSEC 268123
+
+enum {
+ GFX_LINEAR = 0,
+ GFX_NEAREST = 1
+};
+
+enum InputMode {
+ MODE_HOVER,
+ MODE_DRAG,
+};
+
+static const OSystem::GraphicsMode s_graphicsModes[] = {
+ {"default", "Default Test", GFX_LINEAR},
+ { 0, 0, 0 }
+};
+
+class OSystem_3DS : public EventsBaseBackend, public PaletteManager {
+public:
+ OSystem_3DS();
+ ~OSystem_3DS();
+
+ virtual void initBackend();
+
+ virtual bool hasFeature(OSystem::Feature f);
+ virtual void setFeatureState(OSystem::Feature f, bool enable);
+ virtual bool getFeatureState(OSystem::Feature f);
+
+ virtual bool pollEvent(Common::Event &event);
+
+ virtual uint32 getMillis(bool skipRecord = false);
+ virtual void delayMillis(uint msecs);
+ virtual void getTimeAndDate(TimeDate &t) const;
+
+ virtual MutexRef createMutex();
+ virtual void lockMutex(MutexRef mutex);
+ virtual void unlockMutex(MutexRef mutex);
+ virtual void deleteMutex(MutexRef mutex);
+
+ virtual void logMessage(LogMessageType::Type type, const char *message);
+
+ virtual Audio::Mixer *getMixer();
+ virtual PaletteManager *getPaletteManager() { return this; }
+ virtual Common::String getSystemLanguage() const;
+ virtual void fatalError();
+ virtual void quit();
+
+ virtual Common::String getDefaultConfigFileName();
+
+ // Graphics
+ virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
+ int getDefaultGraphicsMode() const;
+ bool setGraphicsMode(int mode);
+ void resetGraphicsScale();
+ int getGraphicsMode() const;
+ inline Graphics::PixelFormat getScreenFormat() const { return _pfGame; }
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
+ void initSize(uint width, uint height,
+ const Graphics::PixelFormat *format = NULL);
+ virtual int getScreenChangeID() const { return 0; };
+
+ void beginGFXTransaction();
+ OSystem::TransactionError endGFXTransaction();
+ int16 getHeight(){ return _gameHeight; }
+ int16 getWidth(){ return _gameWidth; }
+ void setPalette(const byte *colors, uint start, uint num);
+ void grabPalette(byte *colors, uint start, uint num);
+ void copyRectToScreen(const void *buf, int pitch, int x, int y, int w,
+ int h);
+ Graphics::Surface *lockScreen();
+ void unlockScreen();
+ void updateScreen();
+ void setShakePos(int shakeOffset);
+ void setFocusRectangle(const Common::Rect &rect);
+ void clearFocusRectangle();
+ void showOverlay();
+ void hideOverlay();
+ Graphics::PixelFormat getOverlayFormat() const;
+ void clearOverlay();
+ void grabOverlay(void *buf, int pitch);
+ void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w,
+ int h);
+ virtual int16 getOverlayHeight();
+ virtual int16 getOverlayWidth();
+ virtual void displayMessageOnOSD(const char *msg);
+
+ bool showMouse(bool visible);
+ void warpMouse(int x, int y);
+ void setMouseCursor(const void *buf, uint w, uint h, int hotspotX,
+ int hotspotY, uint32 keycolor, bool dontScale = false,
+ const Graphics::PixelFormat *format = NULL);
+ void setCursorPalette(const byte *colors, uint start, uint num);
+
+ void transformPoint(touchPosition &point);
+
+ void updateFocus();
+
+private:
+ void initGraphics();
+ void destroyGraphics();
+ void initAudio();
+ void destroyAudio();
+ void initEvents();
+ void destroyEvents();
+
+ void flushGameScreen();
+ void flushCursor();
+
+protected:
+ Audio::MixerImpl *_mixer;
+
+private:
+ u16 _gameWidth, _gameHeight;
+ u16 _gameX, _gameY;
+ float _gameRatio;
+
+ // Audio
+ Thread audioThread;
+
+ // Graphics
+ Graphics::PixelFormat _pfGame;
+ Graphics::PixelFormat _pfGameTexture;
+ Graphics::PixelFormat _pfCursor;
+ byte _palette[3 * 256];
+ byte _cursorPalette[3 * 256];
+
+ Graphics::Surface _gameScreen;
+ Sprite _gameTexture;
+ Sprite _overlay;
+
+ int _screenShakeOffset;
+ bool _overlayVisible;
+ bool _isFullscreen;
+
+ DVLB_s *_dvlb;
+ shaderProgram_s _program;
+ int _projectionLocation;
+ int _modelviewLocation;
+ C3D_Mtx _projectionTop;
+ C3D_Mtx _projectionBottom;
+ C3D_RenderTarget* _renderTargetTop;
+ C3D_RenderTarget* _renderTargetBottom;
+
+ // Focus
+ Common::Rect _focusRect;
+ bool _focusDirty;
+ C3D_Mtx _focusMatrix;
+ int _focusPosX, _focusPosY;
+ int _focusTargetPosX, _focusTargetPosY;
+ float _focusStepPosX, _focusStepPosY;
+ float _focusScaleX, _focusScaleY;
+ float _focusTargetScaleX, _focusTargetScaleY;
+ float _focusStepScaleX, _focusStepScaleY;
+ uint32 _focusClearTime;
+
+ // Events
+ Thread _eventThread;
+ Common::Queue<Common::Event> _eventQueue;
+
+ Common::String _messageOSD;
+ bool _showMessageOSD;
+
+ // Cursor
+ Graphics::Surface _cursor;
+ Sprite _cursorTexture;
+ bool _cursorPaletteEnabled;
+ bool _cursorVisible;
+ bool _cursorScalable;
+ int _cursorX, _cursorY;
+ int _cursorHotspotX, _cursorHotspotY;
+ uint32 _cursorKeyColor;
+};
+
+#endif
diff --git a/backends/platform/3ds/portdefs.h b/backends/platform/3ds/portdefs.h
new file mode 100644
index 0000000..f58cf5a
--- /dev/null
+++ b/backends/platform/3ds/portdefs.h
@@ -0,0 +1,28 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _PORTDEFS_H_
+#define _PORTDEFS_H_
+
+#define LURE_CLICKABLE_MENUS
+
+#endif
diff --git a/backends/platform/3ds/shader.v.pica b/backends/platform/3ds/shader.v.pica
new file mode 100644
index 0000000..a359768
--- /dev/null
+++ b/backends/platform/3ds/shader.v.pica
@@ -0,0 +1,40 @@
+; PICA200 vertex shader
+
+; Uniforms
+.fvec projection[4], modelView[4]
+
+; Constants
+.constf myconst(0.0, 1.0, -1.0, 0.1)
+.alias zeros myconst.xxxx ; Vector full of zeros
+.alias ones myconst.yyyy ; Vector full of ones
+
+; Outputs
+.out outpos position
+.out outtex texcoord0
+
+; Inputs (defined as aliases for convenience)
+.alias inpos v0
+.alias intex v1
+
+.proc main
+ ; Force the w component of inpos to be 1.0
+ mov r0.xyz, inpos
+ mov r0.w, ones
+
+ ; r1 = modelView * inpos
+ dp4 r1.x, modelView[0], r0
+ dp4 r1.y, modelView[1], r0
+ dp4 r1.z, modelView[2], r0
+ dp4 r1.w, modelView[3], r0
+
+ ; outpos = projection * r1
+ dp4 outpos.x, projection[0], r1
+ dp4 outpos.y, projection[1], r1
+ dp4 outpos.z, projection[2], r1
+ dp4 outpos.w, projection[3], r1
+
+ mov outtex, intex
+
+ end
+.end
+
diff --git a/backends/platform/3ds/sprite.cpp b/backends/platform/3ds/sprite.cpp
new file mode 100644
index 0000000..d779fa4
--- /dev/null
+++ b/backends/platform/3ds/sprite.cpp
@@ -0,0 +1,144 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "backends/platform/3ds/sprite.h"
+#include <algorithm>
+#include <3ds.h>
+
+static uint nextHigher2(uint v) {
+ if (v == 0)
+ return 1;
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ return ++v;
+}
+
+Sprite::Sprite()
+: dirtyPixels(true)
+, dirtyMatrix(true)
+, actualWidth(0)
+, actualHeight(0)
+, posX(0)
+, posY(0)
+, scaleX(1.f)
+, scaleY(1.f)
+{
+ Mtx_Identity(&modelview);
+
+ vertices = (vertex*)linearAlloc(sizeof(vertex) * 4);
+}
+
+Sprite::~Sprite() {
+ //
+}
+
+void Sprite::create(uint16 width, uint16 height, const Graphics::PixelFormat &f) {
+ free();
+
+ actualWidth = width;
+ actualHeight = height;
+ format = f;
+ w = std::max(nextHigher2(width), 64u);
+ h = std::max(nextHigher2(height), 64u);;
+ pitch = w * format.bytesPerPixel;
+ dirtyPixels = true;
+
+ if (width && height) {
+ pixels = linearAlloc(h * pitch);
+ C3D_TexInit(&texture, w, h, GPU_RGBA8);
+ C3D_TexSetFilter(&texture, GPU_LINEAR, GPU_NEAREST);
+ assert(pixels && texture.data);
+ clear();
+ }
+
+ float x = 0.f, y = 0.f;
+ float u = (float)width/w;
+ float v = (float)height/h;
+ vertex tmp[4] = {
+ {{x, y, 0.5f}, {0, 0}},
+ {{x+width, y, 0.5f}, {u, 0}},
+ {{x, y+height, 0.5f}, {0, v}},
+ {{x+width, y+height, 0.5f}, {u, v}},
+ };
+ memcpy(vertices, tmp, sizeof(vertex) * 4);
+}
+
+
+void Sprite::free() {
+ linearFree(vertices);
+ linearFree(pixels);
+ C3D_TexDelete(&texture);
+ pixels = 0;
+ w = h = pitch = 0;
+ actualWidth = actualHeight = 0;
+ format = Graphics::PixelFormat();
+}
+
+void Sprite::convertToInPlace(const Graphics::PixelFormat &dstFormat, const byte *palette) {
+ //
+}
+
+void Sprite::render() {
+ if (dirtyPixels) {
+ dirtyPixels = false;
+ GSPGPU_FlushDataCache(pixels, w * h * format.bytesPerPixel);
+ C3D_SafeDisplayTransfer((u32*)pixels, GX_BUFFER_DIM(w, h), (u32*)texture.data, GX_BUFFER_DIM(w, h), TEXTURE_TRANSFER_FLAGS);
+ gspWaitForPPF();
+ }
+ C3D_TexBind(0, &texture);
+
+ C3D_BufInfo* bufInfo = C3D_GetBufInfo();
+ BufInfo_Init(bufInfo);
+ BufInfo_Add(bufInfo, vertices, sizeof(vertex), 2, 0x10);
+ C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 4);
+}
+
+void Sprite::clear(uint32 color) {
+ dirtyPixels = true;
+ memset(pixels, color, w * h * format.bytesPerPixel);
+}
+
+void Sprite::setScale (float x, float y) {
+ scaleX = x;
+ scaleY = y;
+ dirtyMatrix = true;
+}
+
+void Sprite::setPosition(int x, int y) {
+ posX = x;
+ posY = y;
+ dirtyMatrix = true;
+}
+
+C3D_Mtx* Sprite::getMatrix() {
+ if (dirtyMatrix) {
+ dirtyMatrix = false;
+ Mtx_Identity(&modelview);
+ Mtx_Scale(&modelview, scaleX, scaleY, 1.f);
+ Mtx_Translate(&modelview, posX, posY, 0);
+ }
+ return &modelview;
+}
diff --git a/backends/platform/3ds/sprite.h b/backends/platform/3ds/sprite.h
new file mode 100644
index 0000000..6d88ae4
--- /dev/null
+++ b/backends/platform/3ds/sprite.h
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GRAPHICS_SPRITE_3DS_H
+#define GRAPHICS_SPRITE_3DS_H
+
+#include <citro3d.h>
+#include "graphics/surface.h"
+
+#define TEXTURE_TRANSFER_FLAGS \
+ (GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | \
+ GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGBA8) | \
+ GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
+
+typedef struct {
+ float position[3];
+ float texcoord[2];
+} vertex;
+
+class Sprite : public Graphics::Surface {
+public:
+ Sprite();
+ ~Sprite();
+ void create(uint16 width, uint16 height, const Graphics::PixelFormat &format);
+ void free();
+ void convertToInPlace(const Graphics::PixelFormat &dstFormat, const byte *palette = 0);
+ void render();
+ void clear(uint32 color = 0);
+ void markDirty(){ dirtyPixels = true; }
+
+ void setPosition(int x, int y);
+ void setScale(float x, float y);
+ float getScaleX(){ return scaleX; }
+ float getScaleY(){ return scaleY; }
+ C3D_Mtx* getMatrix();
+
+ uint16 actualWidth;
+ uint16 actualHeight;
+
+private:
+ bool dirtyPixels;
+ bool dirtyMatrix;
+ C3D_Mtx modelview;
+ C3D_Tex texture;
+ vertex* vertices;
+ int posX;
+ int posY;
+ float scaleX;
+ float scaleY;
+};
+
+#endif
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 105d810..1d42043 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -57,7 +57,7 @@ static const char USAGE_STRING[] =
;
// DONT FIXME: DO NOT ORDER ALPHABETICALLY, THIS IS ORDERED BY IMPORTANCE/CATEGORY! :)
-#if defined(__SYMBIAN32__) || defined(__GP32__) || defined(ANDROID) || defined(__DS__)
+#if defined(__SYMBIAN32__) || defined(__GP32__) || defined(ANDROID) || defined(__DS__) || defined(__3DS__)
static const char HELP_STRING[] = "NoUsageString"; // save more data segment space
#else
static const char HELP_STRING[] =
diff --git a/common/scummsys.h b/common/scummsys.h
index 7c2978f..5e1069f 100644
--- a/common/scummsys.h
+++ b/common/scummsys.h
@@ -251,6 +251,7 @@
#if defined(__DC__) || \
defined(__DS__) || \
+ defined(__3DS__) || \
defined(__GP32__) || \
defined(IPHONE) || \
defined(__PLAYSTATION2__) || \
@@ -367,7 +368,7 @@
#endif
#ifndef STRINGBUFLEN
- #if defined(__N64__) || defined(__DS__)
+ #if defined(__N64__) || defined(__DS__) || defined(__3DS__)
#define STRINGBUFLEN 256
#else
#define STRINGBUFLEN 1024
diff --git a/configure b/configure
index 0e7a5a9..fbf6fab 100755
--- a/configure
+++ b/configure
@@ -439,7 +439,7 @@ get_system_exe_extension() {
arm-riscos)
_exeext=",ff8"
;;
- dreamcast | ds | gamecube | n64 | ps2 | psp | wii)
+ dreamcast | ds | 3ds | gamecube | n64 | ps2 | psp | wii)
_exeext=".elf"
;;
gph-linux)
@@ -842,7 +842,7 @@ Usage: $0 [OPTIONS]...
Configuration:
-h, --help display this help and exit
- --backend=BACKEND backend to build (android, tizen, dc, dingux, ds, gcw0,
+ --backend=BACKEND backend to build (android, tizen, dc, dingux, ds, 3ds, gcw0,
gph, iphone, ios7, linuxmoto, maemo, n64, null, openpandora,
ps2, psp, samsungtv, sdl, webos, wii, wince) [sdl]
@@ -879,6 +879,7 @@ Special configuration feature:
raspberrypi for Raspberry Pi
dreamcast for Sega Dreamcast
ds for Nintendo DS
+ 3ds for Nintendo 3DS
gamecube for Nintendo GameCube
gcw0 for GCW Zero
gp2x for GP2X
@@ -1351,6 +1352,11 @@ ds)
_host_cpu=arm
_host_alias=arm-eabi
;;
+3ds)
+ _host_os=3ds
+ _host_cpu=arm
+ _host_alias=arm-none-eabi
+ ;;
gamecube)
_host_os=gamecube
_host_cpu=powerpc
@@ -1584,7 +1590,7 @@ android)
exit 1
fi
;;
-ds | gamecube | wii)
+ds | 3ds | gamecube | wii)
if test -z "$DEVKITPRO"; then
echo "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to devkitPRO>"
exit 1
@@ -1840,7 +1846,7 @@ if test "$have_gcc" = yes ; then
case $_host_os in
# newlib-based system include files suppress non-C89 function
# declarations under __STRICT_ANSI__
- amigaos* | android | dreamcast | ds | gamecube | mingw* | n64 | psp | ps2 | ps3 | tizen | wii | wince )
+ amigaos* | android | dreamcast | ds | 3ds | gamecube | mingw* | n64 | psp | ps2 | ps3 | tizen | wii | wince )
;;
*)
append_var CXXFLAGS "-ansi"
@@ -2354,7 +2360,7 @@ case $_host_os in
echo "Could not determine prefix for static libraries"
fi
fi
-
+
# If _xcodetoolspath is not set yet use xcode-select to get the path
if test -z "$_xcodetoolspath"; then
_xcodetoolspath=`xcode-select -print-path`/Tools
@@ -2400,6 +2406,27 @@ case $_host_os in
append_var LDFLAGS "-L$DEVKITPRO/libnds/lib"
append_var LIBS "-lnds9"
;;
+ 3ds)
+ _optimization_level=-O2
+ append_var DEFINES "-D__3DS__"
+ append_var DEFINES "-D_3DS"
+ append_var DEFINES "-DARM11"
+ append_var CXXFLAGS "-march=armv6k"
+ append_var CXXFLAGS "-mtune=mpcore"
+ append_var CXXFLAGS "-mword-relocations"
+ append_var CXXFLAGS "-mfloat-abi=hard"
+ append_var CXXFLAGS "-ffunction-sections"
+ append_var CXXFLAGS "-fomit-frame-pointer"
+ append_var CXXFLAGS "-isystem $DEVKITPRO/libctru/include"
+ append_var CXXFLAGS "-isystem $DEVKITPRO/devkitARM/arm-none-eabi/include"
+ append_var CXXFLAGS "-isystem $DEVKITPRO/portlibs/3ds/include"
+ if test "$_dynamic_modules" = no ; then
+ append_var LDFLAGS "-Wl,--gc-sections"
+ else
+ append_var LDFLAGS "-Wl,--no-gc-sections"
+ fi
+ append_var LIBS "-lcitro3d -lctru"
+ ;;
freebsd*)
append_var LDFLAGS "-L/usr/local/lib"
append_var CXXFLAGS "-I/usr/local/include"
@@ -2706,6 +2733,25 @@ if test -n "$_host"; then
_mt32emu=no
_port_mk="backends/platform/ds/ds.mk"
;;
+ 3ds)
+ append_var DEFINES "-DDISABLE_FANCY_THEMES"
+ append_var DEFINES "-DDISABLE_SID"
+ append_var DEFINES "-DDISABLE_NES_APU"
+ append_var DEFINES "-DDISABLE_NES_APU"
+ append_var DEFINES "-DSTREAM_AUDIO_FROM_DISK"
+ _backend="3ds"
+ _build_scalers=no
+ _vkeybd=yes
+ _mt32emu=no
+ _vorbis=no
+ _tremor=yes
+ _mad=yes
+ _zlib=yes
+ _jpeg=yes
+ _png=yes
+ _freetype2=yes
+ _port_mk="backends/platform/3ds/3ds.mk"
+ ;;
gamecube)
_backend="wii"
_build_scalers=no
@@ -3221,7 +3267,7 @@ esac
# Enable 16bit support only for backends which support it
#
case $_backend in
- android | dingux | dc | gph | iphone | ios7 | maemo | openpandora | psp | samsungtv | sdl | tizen | webos | wii)
+ android | dingux | dc | 3ds | gph | iphone | ios7 | maemo | openpandora | psp | samsungtv | sdl | tizen | webos | wii)
if test "$_16bit" = auto ; then
_16bit=yes
else
@@ -3300,7 +3346,7 @@ case $_host_os in
amigaos* | cygwin* | dreamcast | ds | gamecube | mingw* | n64 | ps2 | ps3 | psp | wii | wince)
_posix=no
;;
- android | beos* | bsd* | darwin* | freebsd* | gnu* | gph-linux | haiku* | hpux* | iphone | ios7 | irix*| k*bsd*-gnu* | linux* | maemo | mint* | netbsd* | openbsd* | solaris* | sunos* | uclinux* | webos)
+ 3ds | android | beos* | bsd* | darwin* | freebsd* | gnu* | gph-linux | haiku* | hpux* | iphone | ios7 | irix*| k*bsd*-gnu* | linux* | maemo | mint* | netbsd* | openbsd* | solaris* | sunos* | uclinux* | webos)
_posix=yes
;;
os2-emx*)
diff --git a/gui/credits.h b/gui/credits.h
index cb9a10f..a560209 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -366,6 +366,9 @@ static const char *credits[] = {
"C2""(retired)",
"C0""Tarek Soliman",
"",
+"C1""Nintendo 3DS",
+"C0""Thomas Edvalson",
+"",
"C1""Nintendo 64",
"C0""Fabio Battaglia",
"",
Commit: fe8d48005717a4c77d34da1a5f9e4b5bfc597c6f
https://github.com/scummvm/scummvm/commit/fe8d48005717a4c77d34da1a5f9e4b5bfc597c6f
Author: Thomas Edvalson (machin3 at gmail.com)
Date: 2016-04-06T12:12:46-04:00
Commit Message:
3DS: Add to backend configuration list
Changed paths:
configure
diff --git a/configure b/configure
index fbf6fab..03fd5a8 100755
--- a/configure
+++ b/configure
@@ -3231,6 +3231,8 @@ case $_backend in
append_var DEFINES "-DSDL_BACKEND"
add_line_to_config_mk "SDL_BACKEND = 1"
;;
+ 3ds)
+ ;;
sdl)
;;
*)
Commit: f5d73cac8a2d21962ed34b18de5aee36c2bce9ad
https://github.com/scummvm/scummvm/commit/f5d73cac8a2d21962ed34b18de5aee36c2bce9ad
Author: Thomas Edvalson (machin3 at gmail.com)
Date: 2016-04-11T15:15:42-04:00
Commit Message:
3DS: Add CIA format build, add timer handler thread, fix APT service suspending/sleeping/exiting
Changed paths:
A backends/platform/3ds/app/banner.png
A backends/platform/3ds/app/banner.wav
A backends/platform/3ds/app/icon.png
A backends/platform/3ds/app/scummvm.rsf
R backends/platform/3ds/icon.png
backends/platform/3ds/3ds.mk
backends/platform/3ds/osystem-audio.cpp
backends/platform/3ds/osystem-events.cpp
backends/platform/3ds/osystem-graphics.cpp
backends/platform/3ds/osystem.cpp
backends/platform/3ds/osystem.h
configure
diff --git a/backends/platform/3ds/3ds.mk b/backends/platform/3ds/3ds.mk
index bd8e743..7ab5899 100644
--- a/backends/platform/3ds/3ds.mk
+++ b/backends/platform/3ds/3ds.mk
@@ -3,7 +3,11 @@ TARGET := scummvm
APP_TITLE := ScummVM
APP_DESCRIPTION := Point-and-click adventure game engines
APP_AUTHOR := ScummVM Team
-APP_ICON := backends/platform/3ds/icon.png
+APP_ICON := backends/platform/3ds/app/icon.png
+
+APP_RSF := backends/platform/3ds/app/scummvm.rsf
+APP_BANNER_IMAGE:= backends/platform/3ds/app/banner.png
+APP_BANNER_AUDIO:= backends/platform/3ds/app/banner.wav
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
CXXFLAGS += -std=gnu++11
@@ -12,20 +16,27 @@ LDFLAGS += -specs=3dsx.specs $(ARCH) -L$(DEVKITPRO)/libctru/lib -L$(DEVKITPRO)/
.PHONY: clean_3ds
-all: $(TARGET).3dsx
-
clean: clean_3ds
clean_3ds:
$(RM) $(TARGET).3dsx
+ $(RM) $(TARGET).cia
-$(TARGET).smdh: $(APP_ICON) $(MAKEFILE_LIST)
- @smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@
+$(TARGET).smdh: $(APP_ICON)
+ @bannertool makesmdh -s "$(APP_TITLE)" -l "$(APP_DESCRIPTION)" -p "$(APP_AUTHOR)" -i $(APP_ICON) -o $@
@echo built ... $(notdir $@)
$(TARGET).3dsx: $(EXECUTABLE) $(TARGET).smdh
@3dsxtool $< $@ --smdh=$(TARGET).smdh
@echo built ... $(notdir $@)
+
+$(TARGET).bnr: $(APP_BANNER_IMAGE) $(APP_BANNER_AUDIO)
+ @bannertool makebanner -o $@ -i $(APP_BANNER_IMAGE) -a $(APP_BANNER_AUDIO)
+ @echo built ... $(notdir $@)
+
+$(TARGET).cia: $(EXECUTABLE) $(APP_RSF) $(TARGET).smdh $(TARGET).bnr
+ @makerom -f cia -target t -exefslogo -o $@ -elf $(EXECUTABLE) -rsf $(APP_RSF) -banner $(TARGET).bnr -icon $(TARGET).smdh
+ @echo built ... $(notdir $@)
#---------------------------------------------------------------------------------
# rules for assembling GPU shaders
diff --git a/backends/platform/3ds/app/banner.png b/backends/platform/3ds/app/banner.png
new file mode 100644
index 0000000..a3b0215
Binary files /dev/null and b/backends/platform/3ds/app/banner.png differ
diff --git a/backends/platform/3ds/app/banner.wav b/backends/platform/3ds/app/banner.wav
new file mode 100644
index 0000000..e0b684b
Binary files /dev/null and b/backends/platform/3ds/app/banner.wav differ
diff --git a/backends/platform/3ds/app/icon.png b/backends/platform/3ds/app/icon.png
new file mode 100644
index 0000000..07022fb
Binary files /dev/null and b/backends/platform/3ds/app/icon.png differ
diff --git a/backends/platform/3ds/app/scummvm.rsf b/backends/platform/3ds/app/scummvm.rsf
new file mode 100644
index 0000000..d403bdb
--- /dev/null
+++ b/backends/platform/3ds/app/scummvm.rsf
@@ -0,0 +1,218 @@
+BasicInfo:
+ Title : ScummVM
+ ProductCode : ScummVM
+ Logo : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem
+
+TitleInfo:
+ Category : Application
+ UniqueId : 0xFF321
+
+Option:
+ UseOnSD : true # true if App is to be installed to SD
+ FreeProductCode : true # Removes limitations on ProductCode
+ MediaFootPadding : false # If true CCI files are created with padding
+ EnableCrypt : false # Enables encryption for NCCH and CIA
+ EnableCompress : false # Compresses where applicable (currently only exefs:/.code)
+
+AccessControlInfo:
+ CoreVersion : 2
+
+ # Exheader Format Version
+ DescVersion : 2
+
+ # Minimum Required Kernel Version (below is for 4.5.0)
+ ReleaseKernelMajor : "02"
+ ReleaseKernelMinor : "33"
+
+ # ExtData
+ UseExtSaveData : false # enables ExtData
+ #ExtSaveDataId : 0x300 # only set this when the ID is different to the UniqueId
+
+ # FS:USER Archive Access Permissions
+ # Uncomment as required
+ FileSystemAccess:
+ #- CategorySystemApplication
+ #- CategoryHardwareCheck
+ #- CategoryFileSystemTool
+ #- Debug
+ #- TwlCardBackup
+ #- TwlNandData
+ #- Boss
+ - DirectSdmc
+ #- Core
+ #- CtrNandRo
+ #- CtrNandRw
+ #- CtrNandRoWrite
+ #- CategorySystemSettings
+ #- CardBoard
+ #- ExportImportIvs
+ #- DirectSdmcWrite
+ #- SwitchCleanup
+ #- SaveDataMove
+ #- Shop
+ #- Shell
+ #- CategoryHomeMenu
+
+ # Process Settings
+ MemoryType : Application # Application/System/Base
+ SystemMode : 64MB # 64MB(Default)/96MB/80MB/72MB/32MB
+ IdealProcessor : 0
+ AffinityMask : 1
+ Priority : 16
+ MaxCpu : 0 # Let system decide
+ HandleTableSize : 0x200
+ DisableDebug : false
+ EnableForceDebug : false
+ CanWriteSharedPage : true
+ CanUsePrivilegedPriority : false
+ CanUseNonAlphabetAndNumber : true
+ PermitMainFunctionArgument : true
+ CanShareDeviceMemory : true
+ RunnableOnSleep : false
+ SpecialMemoryArrange : true
+
+ # New3DS Exclusive Process Settings
+ SystemModeExt : 124MB # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode
+ CpuSpeed : 804MHz # 268MHz(Default)/804MHz
+ EnableL2Cache : true # false(default)/true
+ CanAccessCore2 : true
+
+ # Virtual Address Mappings
+ IORegisterMapping:
+ - 1ff00000-1ff7ffff # DSP memory
+ MemoryMapping:
+ - 1f000000-1f5fffff:r # VRAM
+
+ # Accessible SVCs, <Name>:<ID>
+ SystemCallAccess:
+ ArbitrateAddress: 34
+ Break: 60
+ CancelTimer: 28
+ ClearEvent: 25
+ ClearTimer: 29
+ CloseHandle: 35
+ ConnectToPort: 45
+ ControlMemory: 1
+ CreateAddressArbiter: 33
+ CreateEvent: 23
+ CreateMemoryBlock: 30
+ CreateMutex: 19
+ CreateSemaphore: 21
+ CreateThread: 8
+ CreateTimer: 26
+ DuplicateHandle: 39
+ ExitProcess: 3
+ ExitThread: 9
+ GetCurrentProcessorNumber: 17
+ GetHandleInfo: 41
+ GetProcessId: 53
+ GetProcessIdOfThread: 54
+ GetProcessIdealProcessor: 6
+ GetProcessInfo: 43
+ GetResourceLimit: 56
+ GetResourceLimitCurrentValues: 58
+ GetResourceLimitLimitValues: 57
+ GetSystemInfo: 42
+ GetSystemTick: 40
+ GetThreadContext: 59
+ GetThreadId: 55
+ GetThreadIdealProcessor: 15
+ GetThreadInfo: 44
+ GetThreadPriority: 11
+ MapMemoryBlock: 31
+ OutputDebugString: 61
+ QueryMemory: 2
+ ReleaseMutex: 20
+ ReleaseSemaphore: 22
+ SendSyncRequest1: 46
+ SendSyncRequest2: 47
+ SendSyncRequest3: 48
+ SendSyncRequest4: 49
+ SendSyncRequest: 50
+ SetThreadPriority: 12
+ SetTimer: 27
+ SignalEvent: 24
+ SleepThread: 10
+ UnmapMemoryBlock: 32
+ WaitSynchronization1: 36
+ WaitSynchronizationN: 37
+ Backdoor: 123
+
+ # Service List
+ # Maximum 34 services (32 if firmware is prior to 9.3.0)
+ ServiceAccessControl:
+ - cfg:u
+ - fs:USER
+ - gsp::Gpu
+ - hid:USER
+ - ndm:u
+ - pxi:dev
+ - APT:U
+ - ac:u
+ - act:u
+ - am:net
+ - boss:U
+ - cam:u
+ - cecd:u
+ - dsp::DSP
+ - frd:u
+ - http:C
+ - ir:USER
+ - ir:u
+ - ir:rst
+ - ldr:ro
+ - mic:u
+ - news:u
+ - nim:aoc
+ - nwm::UDS
+ - ptm:u
+ - qtm:u
+ - soc:U
+ - ssl:C
+ - y2r:u
+
+
+SystemControlInfo:
+ SaveDataSize: 0K
+ RemasterVersion: 0
+ StackSize: 0x40000
+
+ # Modules that run services listed above should be included below
+ # Maximum 48 dependencies
+ # If a module is listed that isn't present on the 3DS, the title will get stuck at the logo (3ds waves)
+ # So act, nfc and qtm are commented for 4.x support. Uncomment if you need these.
+ # <module name>:<module titleid>
+ Dependency:
+ ac: 0x0004013000002402
+ #act: 0x0004013000003802
+ am: 0x0004013000001502
+ boss: 0x0004013000003402
+ camera: 0x0004013000001602
+ cecd: 0x0004013000002602
+ cfg: 0x0004013000001702
+ codec: 0x0004013000001802
+ csnd: 0x0004013000002702
+ dlp: 0x0004013000002802
+ dsp: 0x0004013000001a02
+ friends: 0x0004013000003202
+ gpio: 0x0004013000001b02
+ gsp: 0x0004013000001c02
+ hid: 0x0004013000001d02
+ http: 0x0004013000002902
+ i2c: 0x0004013000001e02
+ ir: 0x0004013000003302
+ mcu: 0x0004013000001f02
+ mic: 0x0004013000002002
+ ndm: 0x0004013000002b02
+ news: 0x0004013000003502
+ #nfc: 0x0004013000004002
+ nim: 0x0004013000002c02
+ nwm: 0x0004013000002d02
+ pdn: 0x0004013000002102
+ ps: 0x0004013000003102
+ ptm: 0x0004013000002202
+ #qtm: 0x0004013020004202
+ ro: 0x0004013000003702
+ socket: 0x0004013000002e02
+ spi: 0x0004013000002302
+ ssl: 0x0004013000002f02
diff --git a/backends/platform/3ds/icon.png b/backends/platform/3ds/icon.png
deleted file mode 100644
index 07022fb..0000000
Binary files a/backends/platform/3ds/icon.png and /dev/null differ
diff --git a/backends/platform/3ds/osystem-audio.cpp b/backends/platform/3ds/osystem-audio.cpp
index 7ff788b..7e4822b 100644
--- a/backends/platform/3ds/osystem-audio.cpp
+++ b/backends/platform/3ds/osystem-audio.cpp
@@ -21,8 +21,8 @@
*/
#include "osystem.h"
+#include "audio/mixer.h"
-static bool exitAudioThread = false;
static bool hasAudio = false;
static void audioThreadFunc(void* arg) {
@@ -34,7 +34,7 @@ static void audioThreadFunc(void* arg) {
int bufferIndex = 0;
const int bufferCount = 3;
const int bufferSize = 80000; // Can't be too small, based on delayMillis duration
- const int sampleRate = 22050;
+ const int sampleRate = mixer->getOutputRate();
int sampleLen = 0;
uint32 lastTime = osys->getMillis(true);
uint32 time = lastTime;
@@ -52,18 +52,18 @@ static void audioThreadFunc(void* arg) {
ndspChnSetRate(channel, sampleRate);
ndspChnSetFormat(channel, NDSP_FORMAT_STEREO_PCM16);
- while(!exitAudioThread) {
- bufferIndex++;
- bufferIndex %= bufferCount;
- ndspWaveBuf* buf = &buffers[bufferIndex];
-
+ while(!osys->exiting) {
osys->delayMillis(100); // Note: Increasing the delay requires a bigger buffer
time = osys->getMillis(true);
sampleLen = (time - lastTime) * 22 * 4; // sampleRate / 1000 * channelCount * sizeof(int16);
lastTime = time;
- if (sampleLen > 0) {
+ if (!osys->sleeping && sampleLen > 0) {
+ bufferIndex++;
+ bufferIndex %= bufferCount;
+ ndspWaveBuf* buf = &buffers[bufferIndex];
+
buf->nsamples = mixer->mixCallback(buf->data_adpcm, sampleLen);
if (buf->nsamples > 0) {
DSP_FlushDataCache(buf->data_vaddr, bufferSize);
@@ -91,7 +91,6 @@ void OSystem_3DS::initAudio() {
void OSystem_3DS::destroyAudio() {
if (hasAudio) {
- exitAudioThread = true;
threadJoin(audioThread, U64_MAX);
threadFree(audioThread);
ndspExit();
diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
index a4ce92c..46efdd3 100644
--- a/backends/platform/3ds/osystem-events.cpp
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -21,12 +21,13 @@
*/
#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "backends/timer/default/default-timer.h"
#include "backends/platform/3ds/gui.h"
#include "osystem.h"
static Common::Mutex *eventMutex;
-static bool exitEventThread = false;
static InputMode inputMode = MODE_DRAG;
+static aptHookCookie cookie;
static void pushEventQueue(Common::Queue<Common::Event>* queue, Common::Event& event) {
Common::StackLock lock(*eventMutex);
@@ -42,8 +43,10 @@ static void eventThreadFunc(void* arg) {
bool isRightClick = false;
Common::Event event;
- while(!exitEventThread) {
- osys->delayMillis(10);
+ while(!osys->exiting) {
+ do {
+ osys->delayMillis(10);
+ } while (osys->sleeping && !osys->exiting);
hidScanInput();
touchPosition touch;
@@ -51,10 +54,6 @@ static void eventThreadFunc(void* arg) {
u32 keysPressed = hidKeysDown();
u32 keysReleased = hidKeysUp();
- if (!aptMainLoop()) {
- event.type = Common::EVENT_QUIT;
- pushEventQueue(eventQueue, event);
- }
if (held & KEY_TOUCH) {
hidTouchRead(&touch);
osys->transformPoint(touch);
@@ -151,15 +150,53 @@ static void eventThreadFunc(void* arg) {
}
}
+static void aptHookFunc(APT_HookType hookType, void* param) {
+ auto eventQueue = (Common::Queue<Common::Event>*) param;
+ OSystem_3DS* osys = (OSystem_3DS*) g_system;
+ Common::Event event;
+
+ switch (hookType) {
+ case APTHOOK_ONSUSPEND:
+ case APTHOOK_ONSLEEP:
+ event.type = Common::EVENT_MAINMENU;
+ pushEventQueue(eventQueue, event);
+ osys->sleeping = true;
+ break;
+ case APTHOOK_ONRESTORE:
+ case APTHOOK_ONWAKEUP:
+ osys->sleeping = false;
+ break;
+ default:
+ event.type = Common::EVENT_QUIT;
+ pushEventQueue(eventQueue, event);
+ break;
+ }
+}
+
+static void timerThreadFunc(void *arg) {
+ OSystem_3DS* osys = (OSystem_3DS*) arg;
+ DefaultTimerManager *tm = (DefaultTimerManager *) osys->getTimerManager();
+ while (!osys->exiting) {
+ tm->handler();
+ g_system->delayMillis(10);
+ aptMainLoop(); // Call apt hook when necessary
+ }
+}
+
void OSystem_3DS::initEvents() {
eventMutex = new Common::Mutex();
s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
- _eventThread = threadCreate(&eventThreadFunc, &_eventQueue, 2048, prio-1, -2, false);
+ _timerThread = threadCreate(&timerThreadFunc, this, 32*1024, prio-1, -2, false);
+ _eventThread = threadCreate(&eventThreadFunc, &_eventQueue, 32*1024, prio-1, -2, false);
+
+ aptHook(&cookie, aptHookFunc, &_eventQueue);
}
void OSystem_3DS::destroyEvents() {
- exitEventThread = true;
+ threadJoin(_timerThread, U64_MAX);
+ threadFree(_timerThread);
+
threadJoin(_eventThread, U64_MAX);
threadFree(_eventThread);
delete eventMutex;
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 5e70dce..7ee4efa 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -180,6 +180,12 @@ void OSystem_3DS::initSize(uint width, uint height,
}
_gameTexture.setPosition(_gameX, _gameY);
_cursorTexture.setScale(_gameTexture.getScaleX(), _gameTexture.getScaleY());
+
+ float ratio = 400.f / _gameWidth;
+ int y = (_gameHeight * ratio - 240.f) / 2;
+ Mtx_Identity(&_focusMatrix);
+ Mtx_Translate(&_focusMatrix, 0, -y, 0);
+ Mtx_Scale(&_focusMatrix, ratio, ratio, 1.f);
}
Common::List<Graphics::PixelFormat> OSystem_3DS::getSupportedFormats() const {
@@ -248,8 +254,11 @@ void OSystem_3DS::unlockScreen() {
}
void OSystem_3DS::updateScreen() {
+
+ if (sleeping || exiting)
+ return;
- updateFocus();
+// updateFocus();
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
// Render top screen
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index fa2980a..d3fc1c7 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -65,13 +65,16 @@ _cursorHotspotY(0),
_gameX(0),
_gameY(0),
_gameWidth(320),
-_gameHeight(240) {
- chdir("/");
+_gameHeight(240),
+exiting(false),
+sleeping(false) {
+ chdir("sdmc:/");
_fsFactory = new POSIXFilesystemFactory();
Posix::assureDirectoryExists("/3ds/scummvm/saves/");
}
OSystem_3DS::~OSystem_3DS() {
+ exiting = true;
destroyEvents();
destroyAudio();
destroyGraphics();
@@ -81,7 +84,7 @@ OSystem_3DS::~OSystem_3DS() {
}
void OSystem_3DS::quit() {
- //
+ printf("OSystem_3DS::quit()\n");
}
void OSystem_3DS::initBackend() {
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index 98d9ad0..a8c2a90 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -55,6 +55,9 @@ class OSystem_3DS : public EventsBaseBackend, public PaletteManager {
public:
OSystem_3DS();
~OSystem_3DS();
+
+ volatile bool exiting;
+ volatile bool sleeping;
virtual void initBackend();
@@ -191,6 +194,7 @@ private:
// Events
Thread _eventThread;
+ Thread _timerThread;
Common::Queue<Common::Event> _eventQueue;
Common::String _messageOSD;
diff --git a/configure b/configure
index 03fd5a8..c23f9e7 100755
--- a/configure
+++ b/configure
@@ -2409,7 +2409,7 @@ case $_host_os in
3ds)
_optimization_level=-O2
append_var DEFINES "-D__3DS__"
- append_var DEFINES "-D_3DS"
+ append_var DEFINES "-DARM"
append_var DEFINES "-DARM11"
append_var CXXFLAGS "-march=armv6k"
append_var CXXFLAGS "-mtune=mpcore"
@@ -2737,8 +2737,6 @@ if test -n "$_host"; then
append_var DEFINES "-DDISABLE_FANCY_THEMES"
append_var DEFINES "-DDISABLE_SID"
append_var DEFINES "-DDISABLE_NES_APU"
- append_var DEFINES "-DDISABLE_NES_APU"
- append_var DEFINES "-DSTREAM_AUDIO_FROM_DISK"
_backend="3ds"
_build_scalers=no
_vkeybd=yes
@@ -2749,6 +2747,8 @@ if test -n "$_host"; then
_zlib=yes
_jpeg=yes
_png=yes
+ _flac=yes
+ _faad=yes
_freetype2=yes
_port_mk="backends/platform/3ds/3ds.mk"
;;
@@ -4592,6 +4592,9 @@ case $_backend in
# during linking stage
append_var LIBS "-lc -lgcc -lnosys"
;;
+ 3ds)
+ append_var LIBS "-logg -lpng"
+ ;;
esac
Commit: a0cc562f1f8cbf51fb92d0f230c2d7fb0274090d
https://github.com/scummvm/scummvm/commit/a0cc562f1f8cbf51fb92d0f230c2d7fb0274090d
Author: Thomas Edvalson (machin3 at gmail.com)
Date: 2016-04-11T15:21:58-04:00
Commit Message:
3DS: Use linear GPU texture downscaling for better legibility in hi-res games
Changed paths:
backends/platform/3ds/sprite.cpp
diff --git a/backends/platform/3ds/sprite.cpp b/backends/platform/3ds/sprite.cpp
index d779fa4..0d5780e 100644
--- a/backends/platform/3ds/sprite.cpp
+++ b/backends/platform/3ds/sprite.cpp
@@ -69,7 +69,7 @@ void Sprite::create(uint16 width, uint16 height, const Graphics::PixelFormat &f)
if (width && height) {
pixels = linearAlloc(h * pitch);
C3D_TexInit(&texture, w, h, GPU_RGBA8);
- C3D_TexSetFilter(&texture, GPU_LINEAR, GPU_NEAREST);
+ C3D_TexSetFilter(&texture, GPU_LINEAR, GPU_LINEAR);
assert(pixels && texture.data);
clear();
}
Commit: 95566ed6e3cf42c208d6aede6de0c29ef3a816d5
https://github.com/scummvm/scummvm/commit/95566ed6e3cf42c208d6aede6de0c29ef3a816d5
Author: Thomas Edvalson (machin3 at gmail.com)
Date: 2016-04-14T00:38:46-04:00
Commit Message:
3DS: Add backend author to credits
Changed paths:
AUTHORS
devtools/credits.pl
diff --git a/AUTHORS b/AUTHORS
index eff485c..22d6e37 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -302,6 +302,9 @@ ScummVM Team
Frantisek Dufka - (retired)
Tarek Soliman
+ Nintendo 3DS:
+ Thomas Edvalson
+
Nintendo 64:
Fabio Battaglia
diff --git a/devtools/credits.pl b/devtools/credits.pl
index c67793c..9e0fcc6 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -844,6 +844,10 @@ begin_credits("Credits");
add_person("Frantisek Dufka", "fanoush", "(retired)");
add_person("Tarek Soliman", "tsoliman", "");
end_section();
+
+ begin_section("Nintendo 3DS");
+ add_person("Thomas Edvalson", "Cruel", "");
+ end_section();
begin_section("Nintendo 64");
add_person("Fabio Battaglia", "Hkz", "");
Commit: 1ea737bbd87b27c1acf068f20845611a44adb98d
https://github.com/scummvm/scummvm/commit/1ea737bbd87b27c1acf068f20845611a44adb98d
Author: Thomas Edvalson (machin3 at gmail.com)
Date: 2016-04-14T01:09:51-04:00
Commit Message:
3DS: Maintain alphabetical order in configure file
Changed paths:
configure
diff --git a/configure b/configure
index c23f9e7..449271a 100755
--- a/configure
+++ b/configure
@@ -439,7 +439,7 @@ get_system_exe_extension() {
arm-riscos)
_exeext=",ff8"
;;
- dreamcast | ds | 3ds | gamecube | n64 | ps2 | psp | wii)
+ 3ds | dreamcast | ds | gamecube | n64 | ps2 | psp | wii)
_exeext=".elf"
;;
gph-linux)
@@ -842,9 +842,9 @@ Usage: $0 [OPTIONS]...
Configuration:
-h, --help display this help and exit
- --backend=BACKEND backend to build (android, tizen, dc, dingux, ds, 3ds, gcw0,
+ --backend=BACKEND backend to build (3ds, android, dc, dingux, ds, gcw0,
gph, iphone, ios7, linuxmoto, maemo, n64, null, openpandora,
- ps2, psp, samsungtv, sdl, webos, wii, wince) [sdl]
+ ps2, psp, samsungtv, sdl, tizen, webos, wii, wince) [sdl]
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
@@ -870,16 +870,15 @@ Fine tuning of the installation directories:
Special configuration feature:
--host=HOST cross-compile to target HOST (arm-linux, ...)
- special targets: android-arm for Android ARM
+ special targets: 3ds for Nintendo 3DS
+ android-arm for Android ARM
android-mips for Android MIPS
android-x86 for Android x86
- tizen for Samsung Tizen
caanoo for Caanoo
dingux for Dingux
raspberrypi for Raspberry Pi
dreamcast for Sega Dreamcast
ds for Nintendo DS
- 3ds for Nintendo 3DS
gamecube for Nintendo GameCube
gcw0 for GCW Zero
gp2x for GP2X
@@ -897,6 +896,7 @@ Special configuration feature:
ps3 for PlayStation 3
psp for PlayStation Portable
samsungtv for Samsung TV
+ tizen for Samsung Tizen
webos for HP Palm WebOS
wii for Nintendo Wii
wince for Windows CE
@@ -1304,6 +1304,11 @@ get_system_exe_extension $guessed_host
NATIVEEXEEXT=$_exeext
case $_host in
+3ds)
+ _host_os=3ds
+ _host_cpu=arm
+ _host_alias=arm-none-eabi
+ ;;
android | android-arm | android-v7a | android-arm-v7a | ouya)
_host_os=android
_host_cpu=arm
@@ -1352,11 +1357,6 @@ ds)
_host_cpu=arm
_host_alias=arm-eabi
;;
-3ds)
- _host_os=3ds
- _host_cpu=arm
- _host_alias=arm-none-eabi
- ;;
gamecube)
_host_os=gamecube
_host_cpu=powerpc
@@ -1590,7 +1590,7 @@ android)
exit 1
fi
;;
-ds | 3ds | gamecube | wii)
+3ds | ds | gamecube | wii)
if test -z "$DEVKITPRO"; then
echo "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to devkitPRO>"
exit 1
@@ -1846,7 +1846,7 @@ if test "$have_gcc" = yes ; then
case $_host_os in
# newlib-based system include files suppress non-C89 function
# declarations under __STRICT_ANSI__
- amigaos* | android | dreamcast | ds | 3ds | gamecube | mingw* | n64 | psp | ps2 | ps3 | tizen | wii | wince )
+ 3ds | amigaos* | android | dreamcast | ds | gamecube | mingw* | n64 | psp | ps2 | ps3 | tizen | wii | wince )
;;
*)
append_var CXXFLAGS "-ansi"
@@ -2146,6 +2146,27 @@ esac
echo_n "Checking hosttype... "
echo $_host_os
case $_host_os in
+ 3ds)
+ _optimization_level=-O2
+ append_var DEFINES "-D__3DS__"
+ append_var DEFINES "-DARM"
+ append_var DEFINES "-DARM11"
+ append_var CXXFLAGS "-march=armv6k"
+ append_var CXXFLAGS "-mtune=mpcore"
+ append_var CXXFLAGS "-mword-relocations"
+ append_var CXXFLAGS "-mfloat-abi=hard"
+ append_var CXXFLAGS "-ffunction-sections"
+ append_var CXXFLAGS "-fomit-frame-pointer"
+ append_var CXXFLAGS "-I$DEVKITPRO/libctru/include"
+ append_var CXXFLAGS "-I$DEVKITPRO/portlibs/3ds/include"
+ if test "$_dynamic_modules" = no ; then
+ append_var LDFLAGS "-Wl,--gc-sections"
+ else
+ append_var LDFLAGS "-Wl,--no-gc-sections"
+ fi
+ append_var LDFLAGS "-L$DEVKITPRO/portlibs/3ds/lib"
+ append_var LIBS "-lcitro3d -lctru"
+ ;;
amigaos*)
append_var LDFLAGS "-Wl,--export-dynamic"
append_var LDFLAGS "-L/sdk/local/newlib/lib"
@@ -2406,27 +2427,6 @@ case $_host_os in
append_var LDFLAGS "-L$DEVKITPRO/libnds/lib"
append_var LIBS "-lnds9"
;;
- 3ds)
- _optimization_level=-O2
- append_var DEFINES "-D__3DS__"
- append_var DEFINES "-DARM"
- append_var DEFINES "-DARM11"
- append_var CXXFLAGS "-march=armv6k"
- append_var CXXFLAGS "-mtune=mpcore"
- append_var CXXFLAGS "-mword-relocations"
- append_var CXXFLAGS "-mfloat-abi=hard"
- append_var CXXFLAGS "-ffunction-sections"
- append_var CXXFLAGS "-fomit-frame-pointer"
- append_var CXXFLAGS "-isystem $DEVKITPRO/libctru/include"
- append_var CXXFLAGS "-isystem $DEVKITPRO/devkitARM/arm-none-eabi/include"
- append_var CXXFLAGS "-isystem $DEVKITPRO/portlibs/3ds/include"
- if test "$_dynamic_modules" = no ; then
- append_var LDFLAGS "-Wl,--gc-sections"
- else
- append_var LDFLAGS "-Wl,--no-gc-sections"
- fi
- append_var LIBS "-lcitro3d -lctru"
- ;;
freebsd*)
append_var LDFLAGS "-L/usr/local/lib"
append_var CXXFLAGS "-I/usr/local/include"
@@ -2604,6 +2604,18 @@ if test -n "$_host"; then
# Cross-compiling mode - add your target here if needed
echo "Cross-compiling to $_host"
case "$_host" in
+ 3ds)
+ append_var DEFINES "-DDISABLE_FANCY_THEMES"
+ append_var DEFINES "-DDISABLE_SID"
+ append_var DEFINES "-DDISABLE_NES_APU"
+ _backend="3ds"
+ _build_scalers=no
+ _vkeybd=yes
+ _mt32emu=no
+ # Should use Tremor instead of Vorbis
+ _vorbis=no
+ _port_mk="backends/platform/3ds/3ds.mk"
+ ;;
android | android-arm | android-v7a | android-arm-v7a | android-mips | android-x86 | ouya)
# we link a .so as default
append_var LDFLAGS "-shared"
@@ -2733,25 +2745,6 @@ if test -n "$_host"; then
_mt32emu=no
_port_mk="backends/platform/ds/ds.mk"
;;
- 3ds)
- append_var DEFINES "-DDISABLE_FANCY_THEMES"
- append_var DEFINES "-DDISABLE_SID"
- append_var DEFINES "-DDISABLE_NES_APU"
- _backend="3ds"
- _build_scalers=no
- _vkeybd=yes
- _mt32emu=no
- _vorbis=no
- _tremor=yes
- _mad=yes
- _zlib=yes
- _jpeg=yes
- _png=yes
- _flac=yes
- _faad=yes
- _freetype2=yes
- _port_mk="backends/platform/3ds/3ds.mk"
- ;;
gamecube)
_backend="wii"
_build_scalers=no
@@ -3081,6 +3074,8 @@ fi
# Backend related stuff
#
case $_backend in
+ 3ds)
+ ;;
android)
append_var DEFINES "-DREDUCE_MEMORY_USAGE"
append_var CXXFLAGS "-Wa,--noexecstack"
@@ -3183,6 +3178,8 @@ case $_backend in
append_var LDFLAGS "-shared"
append_var LDFLAGS "-fpic"
;;
+ sdl)
+ ;;
tizen)
# dirent.h not available. NONSTANDARD_PORT==ensure portdefs.h is included
append_var DEFINES "-DTIZEN -DDISABLE_STDIO_FILESTREAM -DNONSTANDARD_PORT"
@@ -3231,10 +3228,6 @@ case $_backend in
append_var DEFINES "-DSDL_BACKEND"
add_line_to_config_mk "SDL_BACKEND = 1"
;;
- 3ds)
- ;;
- sdl)
- ;;
*)
echo "support for $_backend backend not implemented in configure script yet"
exit 1
@@ -3269,7 +3262,7 @@ esac
# Enable 16bit support only for backends which support it
#
case $_backend in
- android | dingux | dc | 3ds | gph | iphone | ios7 | maemo | openpandora | psp | samsungtv | sdl | tizen | webos | wii)
+ 3ds | android | dingux | dc | gph | iphone | ios7 | maemo | openpandora | psp | samsungtv | sdl | tizen | webos | wii)
if test "$_16bit" = auto ; then
_16bit=yes
else
@@ -4561,6 +4554,14 @@ fi
# after all of CXXFLAGS, LDFLAGS, LIBS etc. have been setup
#
case $_backend in
+ 3ds)
+ if test "$_freetype2" = yes -a "$_png" = yes; then
+ append_var LIBS "-lpng"
+ fi
+ if test "$_tremor" = yes -o "$_flac" = yes; then
+ append_var LIBS "-logg"
+ fi
+ ;;
android)
# ssp at this point so the cxxtests link
if test "$_debug_build" = yes; then
@@ -4592,9 +4593,6 @@ case $_backend in
# during linking stage
append_var LIBS "-lc -lgcc -lnosys"
;;
- 3ds)
- append_var LIBS "-logg -lpng"
- ;;
esac
Commit: e8dcfc3a4efeeaffad0380e88223fabbc12e1423
https://github.com/scummvm/scummvm/commit/e8dcfc3a4efeeaffad0380e88223fabbc12e1423
Author: Thomas Edvalson (machin3 at gmail.com)
Date: 2016-04-19T03:22:32-04:00
Commit Message:
3DS: Fix code styling, add license header, remove unused portdefs.h
Changed paths:
R backends/platform/3ds/portdefs.h
backends/platform/3ds/osystem-audio.cpp
backends/platform/3ds/osystem-events.cpp
backends/platform/3ds/osystem-graphics.cpp
backends/platform/3ds/osystem.cpp
backends/platform/3ds/shader.v.pica
backends/platform/3ds/sprite.cpp
diff --git a/backends/platform/3ds/osystem-audio.cpp b/backends/platform/3ds/osystem-audio.cpp
index 7e4822b..da74ab6 100644
--- a/backends/platform/3ds/osystem-audio.cpp
+++ b/backends/platform/3ds/osystem-audio.cpp
@@ -25,9 +25,9 @@
static bool hasAudio = false;
-static void audioThreadFunc(void* arg) {
- Audio::MixerImpl *mixer = (Audio::MixerImpl *) arg;
- OSystem_3DS *osys = (OSystem_3DS*)g_system;
+static void audioThreadFunc(void *arg) {
+ Audio::MixerImpl *mixer = (Audio::MixerImpl *)arg;
+ OSystem_3DS *osys = (OSystem_3DS *)g_system;
int i;
const int channel = 0;
@@ -40,7 +40,7 @@ static void audioThreadFunc(void* arg) {
uint32 time = lastTime;
ndspWaveBuf buffers[bufferCount];
- for(i = 0; i < bufferCount; ++i) {
+ for (i = 0; i < bufferCount; ++i) {
memset(&buffers[i], 0, sizeof(ndspWaveBuf));
buffers[i].data_vaddr = linearAlloc(bufferSize);
buffers[i].looping = false;
@@ -52,7 +52,7 @@ static void audioThreadFunc(void* arg) {
ndspChnSetRate(channel, sampleRate);
ndspChnSetFormat(channel, NDSP_FORMAT_STEREO_PCM16);
- while(!osys->exiting) {
+ while (!osys->exiting) {
osys->delayMillis(100); // Note: Increasing the delay requires a bigger buffer
time = osys->getMillis(true);
@@ -62,7 +62,7 @@ static void audioThreadFunc(void* arg) {
if (!osys->sleeping && sampleLen > 0) {
bufferIndex++;
bufferIndex %= bufferCount;
- ndspWaveBuf* buf = &buffers[bufferIndex];
+ ndspWaveBuf *buf = &buffers[bufferIndex];
buf->nsamples = mixer->mixCallback(buf->data_adpcm, sampleLen);
if (buf->nsamples > 0) {
@@ -72,7 +72,7 @@ static void audioThreadFunc(void* arg) {
}
}
- for(i = 0; i < bufferCount; ++i)
+ for (i = 0; i < bufferCount; ++i)
linearFree(buffers[i].data_pcm8);
}
@@ -85,7 +85,7 @@ void OSystem_3DS::initAudio() {
if (hasAudio) {
s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
- audioThread = threadCreate(&audioThreadFunc, _mixer, 32*1048, prio-1, -2, false);
+ audioThread = threadCreate(&audioThreadFunc, _mixer, 32 * 1048, prio - 1, -2, false);
}
}
diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
index 46efdd3..5135e3a 100644
--- a/backends/platform/3ds/osystem-events.cpp
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -20,30 +20,29 @@
*
*/
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/timer/default/default-timer.h"
-#include "backends/platform/3ds/gui.h"
+#include "gui.h"
#include "osystem.h"
static Common::Mutex *eventMutex;
static InputMode inputMode = MODE_DRAG;
static aptHookCookie cookie;
-static void pushEventQueue(Common::Queue<Common::Event>* queue, Common::Event& event) {
+static void pushEventQueue(Common::Queue<Common::Event> *queue, Common::Event &event) {
Common::StackLock lock(*eventMutex);
queue->push(event);
}
-static void eventThreadFunc(void* arg) {
- OSystem_3DS* osys = (OSystem_3DS*) g_system;
- auto eventQueue = (Common::Queue<Common::Event>*) arg;
+static void eventThreadFunc(void *arg) {
+ OSystem_3DS *osys = (OSystem_3DS *)g_system;
+ auto eventQueue = (Common::Queue<Common::Event> *)arg;
uint32 touchStartTime = osys->getMillis();
- touchPosition lastTouch = {0,0};
+ touchPosition lastTouch = {0, 0};
bool isRightClick = false;
Common::Event event;
- while(!osys->exiting) {
+ while (!osys->exiting) {
do {
osys->delayMillis(10);
} while (osys->sleeping && !osys->exiting);
@@ -69,23 +68,19 @@ static void eventThreadFunc(void* arg) {
event.type = isRightClick ? Common::EVENT_RBUTTONDOWN : Common::EVENT_LBUTTONDOWN;
pushEventQueue(eventQueue, event);
}
- }
- else if (touch.px != lastTouch.px || touch.py != lastTouch.py) {
+ } else if (touch.px != lastTouch.px || touch.py != lastTouch.py) {
event.type = Common::EVENT_MOUSEMOVE;
pushEventQueue(eventQueue, event);
}
lastTouch = touch;
- }
- else if (keysReleased & KEY_TOUCH) {
+ } else if (keysReleased & KEY_TOUCH) {
event.mouse.x = lastTouch.px;
event.mouse.y = lastTouch.py;
- printf("clicked %u, %u\n", lastTouch.px, lastTouch.py);
if (inputMode == MODE_DRAG) {
event.type = isRightClick ? Common::EVENT_RBUTTONUP : Common::EVENT_LBUTTONUP;
pushEventQueue(eventQueue, event);
- }
- else if (osys->getMillis() - touchStartTime < 200) {
+ } else if (osys->getMillis() - touchStartTime < 200) {
// Process click in MODE_HOVER
event.type = Common::EVENT_MOUSEMOVE;
pushEventQueue(eventQueue, event);
@@ -144,15 +139,15 @@ static void eventThreadFunc(void* arg) {
event.kbd.flags = 0;
pushEventQueue(eventQueue, event);
}
-
+
// TODO: EVENT_PREDICTIVE_DIALOG
// EVENT_SCREEN_CHANGED
}
}
-static void aptHookFunc(APT_HookType hookType, void* param) {
- auto eventQueue = (Common::Queue<Common::Event>*) param;
- OSystem_3DS* osys = (OSystem_3DS*) g_system;
+static void aptHookFunc(APT_HookType hookType, void *param) {
+ auto eventQueue = (Common::Queue<Common::Event> *)param;
+ OSystem_3DS *osys = (OSystem_3DS *)g_system;
Common::Event event;
switch (hookType) {
@@ -174,8 +169,8 @@ static void aptHookFunc(APT_HookType hookType, void* param) {
}
static void timerThreadFunc(void *arg) {
- OSystem_3DS* osys = (OSystem_3DS*) arg;
- DefaultTimerManager *tm = (DefaultTimerManager *) osys->getTimerManager();
+ OSystem_3DS *osys = (OSystem_3DS *)arg;
+ DefaultTimerManager *tm = (DefaultTimerManager *)osys->getTimerManager();
while (!osys->exiting) {
tm->handler();
g_system->delayMillis(10);
@@ -187,8 +182,8 @@ void OSystem_3DS::initEvents() {
eventMutex = new Common::Mutex();
s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
- _timerThread = threadCreate(&timerThreadFunc, this, 32*1024, prio-1, -2, false);
- _eventThread = threadCreate(&eventThreadFunc, &_eventQueue, 32*1024, prio-1, -2, false);
+ _timerThread = threadCreate(&timerThreadFunc, this, 32 * 1024, prio - 1, -2, false);
+ _eventThread = threadCreate(&eventThreadFunc, &_eventQueue, 32 * 1024, prio - 1, -2, false);
aptHook(&cookie, aptHookFunc, &_eventQueue);
}
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 7ee4efa..0e50d2b 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -21,11 +21,9 @@
*
*/
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/platform/3ds/osystem.h"
#include "backends/platform/3ds/shader_shbin.h"
-#include <common/rect.h>
-#include <algorithm>
+#include "common/rect.h"
// Used to transfer the final rendered display to the framebuffer
#define DISPLAY_TRANSFER_FLAGS \
@@ -62,7 +60,7 @@ void OSystem_3DS::initGraphics() {
_projectionLocation = shaderInstanceGetUniformLocation(_program.vertexShader, "projection");
_modelviewLocation = shaderInstanceGetUniformLocation(_program.vertexShader, "modelView");
- C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
+ C3D_AttrInfo *attrInfo = C3D_GetAttrInfo();
AttrInfo_Init(attrInfo);
AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position
AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=texcoord
@@ -70,7 +68,7 @@ void OSystem_3DS::initGraphics() {
Mtx_OrthoTilt(&_projectionTop, 0.0, 400.0, 240.0, 0.0, 0.0, 1.0);
Mtx_OrthoTilt(&_projectionBottom, 0.0, 320.0, 240.0, 0.0, 0.0, 1.0);
- C3D_TexEnv* env = C3D_GetTexEnv(0);
+ C3D_TexEnv *env = C3D_GetTexEnv(0);
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, 0, 0);
C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
@@ -138,7 +136,7 @@ bool OSystem_3DS::setGraphicsMode(int mode) {
}
void OSystem_3DS::resetGraphicsScale() {
- printf("resetGraphicsScale\n");
+ debug("resetGraphicsScale");
}
int OSystem_3DS::getGraphicsMode() const {
@@ -146,14 +144,14 @@ int OSystem_3DS::getGraphicsMode() const {
}
void OSystem_3DS::initSize(uint width, uint height,
const Graphics::PixelFormat *format) {
- printf("3ds initsize w:%d h:%d\n", width, height);
+ debug("3ds initsize w:%d h:%d", width, height);
_gameWidth = width;
_gameHeight = height;
_gameTexture.create(width, height, _pfGameTexture);
_overlay.create(getOverlayWidth(), getOverlayHeight(), _pfGameTexture);
if (format) {
- printf("pixelformat: %d %d %d %d %d\n", format->bytesPerPixel, format->rBits(), format->gBits(), format->bBits(), format->aBits());;
+ debug("pixelformat: %d %d %d %d %d", format->bytesPerPixel, format->rBits(), format->gBits(), format->bBits(), format->aBits());;
_pfGame = *format;
}
@@ -207,7 +205,6 @@ OSystem::TransactionError OSystem_3DS::endGFXTransaction() {
}
void OSystem_3DS::setPalette(const byte *colors, uint start, uint num) {
-// printf("setPalette\n");
assert(start + num <= 256);
memcpy(_palette + 3 * start, colors, 3 * num);
@@ -217,7 +214,6 @@ void OSystem_3DS::setPalette(const byte *colors, uint start, uint num) {
}
}
void OSystem_3DS::grabPalette(byte *colors, uint start, uint num) {
-// printf("grabPalette\n");
assert(start + num <= 256);
memcpy(colors, _palette + 3 * start, 3 * num);
}
@@ -245,11 +241,9 @@ void OSystem_3DS::flushGameScreen() {
}
Graphics::Surface *OSystem_3DS::lockScreen() {
- printf("lockScreen\n");
return &_gameScreen;
}
void OSystem_3DS::unlockScreen() {
- printf("unlockScreen\n");
flushGameScreen();
}
@@ -291,7 +285,7 @@ void OSystem_3DS::setShakePos(int shakeOffset) {
}
void OSystem_3DS::setFocusRectangle(const Common::Rect &rect) {
-// printf("setfocus: %d %d %d %d\n", rect.left, rect.top, rect.width(), rect.height());
+ debug("setfocus: %d %d %d %d", rect.left, rect.top, rect.width(), rect.height());
_focusRect = rect;
_focusDirty = true;
_focusClearTime = 0;
@@ -388,7 +382,7 @@ void OSystem_3DS::clearOverlay() {
}
void OSystem_3DS::grabOverlay(void *buf, int pitch) {
- for(int y = 0; y < getOverlayHeight(); ++y) {
+ for (int y = 0; y < getOverlayHeight(); ++y) {
memcpy(buf, _overlay.getBasePtr(0, y), pitch);
}
}
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index d3fc1c7..af0b7b5 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -20,7 +20,9 @@
*
*/
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#define FORBIDDEN_SYMBOL_EXCEPTION_printf
+#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
+#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
#include "osystem.h"
@@ -38,36 +40,37 @@
#include <time.h>
OSystem_3DS::OSystem_3DS():
-_focusDirty(true),
-_focusRect(Common::Rect(1,1)),
-_focusPosX(0),
-_focusPosY(0),
-_focusTargetPosX(0),
-_focusTargetPosY(0),
-_focusStepPosX(0),
-_focusStepPosY(0),
-_focusScaleX(1.f),
-_focusScaleY(1.f),
-_focusTargetScaleX(1.f),
-_focusTargetScaleY(1.f),
-_focusStepScaleX(0.f),
-_focusStepScaleY(0.f),
-_focusClearTime(0),
-_showMessageOSD(false),
-_isFullscreen(false),
-_cursorVisible(false),
-_cursorScalable(false),
-_cursorPaletteEnabled(false),
-_cursorX(0),
-_cursorY(0),
-_cursorHotspotX(0),
-_cursorHotspotY(0),
-_gameX(0),
-_gameY(0),
-_gameWidth(320),
-_gameHeight(240),
-exiting(false),
-sleeping(false) {
+ _focusDirty(true),
+ _focusRect(Common::Rect(1, 1)),
+ _focusPosX(0),
+ _focusPosY(0),
+ _focusTargetPosX(0),
+ _focusTargetPosY(0),
+ _focusStepPosX(0),
+ _focusStepPosY(0),
+ _focusScaleX(1.f),
+ _focusScaleY(1.f),
+ _focusTargetScaleX(1.f),
+ _focusTargetScaleY(1.f),
+ _focusStepScaleX(0.f),
+ _focusStepScaleY(0.f),
+ _focusClearTime(0),
+ _showMessageOSD(false),
+ _isFullscreen(false),
+ _cursorVisible(false),
+ _cursorScalable(false),
+ _cursorPaletteEnabled(false),
+ _cursorX(0),
+ _cursorY(0),
+ _cursorHotspotX(0),
+ _cursorHotspotY(0),
+ _gameX(0),
+ _gameY(0),
+ _gameWidth(320),
+ _gameHeight(240),
+ exiting(false),
+ sleeping(false)
+{
chdir("sdmc:/");
_fsFactory = new POSIXFilesystemFactory();
Posix::assureDirectoryExists("/3ds/scummvm/saves/");
@@ -133,18 +136,18 @@ void OSystem_3DS::getTimeAndDate(TimeDate& td) const {
}
OSystem::MutexRef OSystem_3DS::createMutex() {
- RecursiveLock* mutex = new RecursiveLock();
+ RecursiveLock *mutex = new RecursiveLock();
RecursiveLock_Init(mutex);
return (OSystem::MutexRef) mutex;
}
void OSystem_3DS::lockMutex(MutexRef mutex) {
- RecursiveLock_Lock((RecursiveLock *)mutex);
+ RecursiveLock_Lock((RecursiveLock*)mutex);
}
void OSystem_3DS::unlockMutex(MutexRef mutex) {
- RecursiveLock_Unlock((RecursiveLock *)mutex);
+ RecursiveLock_Unlock((RecursiveLock*)mutex);
}
void OSystem_3DS::deleteMutex(MutexRef mutex) {
- delete (RecursiveLock *)mutex;
+ delete (RecursiveLock*)mutex;
}
Common::String OSystem_3DS::getSystemLanguage() const {
diff --git a/backends/platform/3ds/portdefs.h b/backends/platform/3ds/portdefs.h
deleted file mode 100644
index f58cf5a..0000000
--- a/backends/platform/3ds/portdefs.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef _PORTDEFS_H_
-#define _PORTDEFS_H_
-
-#define LURE_CLICKABLE_MENUS
-
-#endif
diff --git a/backends/platform/3ds/shader.v.pica b/backends/platform/3ds/shader.v.pica
index a359768..2d18985 100644
--- a/backends/platform/3ds/shader.v.pica
+++ b/backends/platform/3ds/shader.v.pica
@@ -1,4 +1,23 @@
-; PICA200 vertex shader
+;* ScummVM - Graphic Adventure Engine
+;*
+;* ScummVM is the legal property of its developers, whose names
+;* are too numerous to list here. Please refer to the COPYRIGHT
+;* file distributed with this source distribution.
+;*
+;* This program is free software; you can redistribute it and/or
+;* modify it under the terms of the GNU General Public License
+;* as published by the Free Software Foundation; either version 2
+;* of the License, or (at your option) any later version.
+;*
+;* This program is distributed in the hope that it will be useful,
+;* but WITHOUT ANY WARRANTY; without even the implied warranty of
+;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;* GNU General Public License for more details.
+;*
+;* You should have received a copy of the GNU General Public License
+;* along with this program; if not, write to the Free Software
+;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+;*
; Uniforms
.fvec projection[4], modelView[4]
diff --git a/backends/platform/3ds/sprite.cpp b/backends/platform/3ds/sprite.cpp
index 0d5780e..a0aee38 100644
--- a/backends/platform/3ds/sprite.cpp
+++ b/backends/platform/3ds/sprite.cpp
@@ -19,9 +19,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
#include "backends/platform/3ds/sprite.h"
-#include <algorithm>
+#include "common/util.h"
#include <3ds.h>
static uint nextHigher2(uint v) {
@@ -37,18 +37,18 @@ static uint nextHigher2(uint v) {
}
Sprite::Sprite()
-: dirtyPixels(true)
-, dirtyMatrix(true)
-, actualWidth(0)
-, actualHeight(0)
-, posX(0)
-, posY(0)
-, scaleX(1.f)
-, scaleY(1.f)
+ : dirtyPixels(true)
+ , dirtyMatrix(true)
+ , actualWidth(0)
+ , actualHeight(0)
+ , posX(0)
+ , posY(0)
+ , scaleX(1.f)
+ , scaleY(1.f)
{
Mtx_Identity(&modelview);
- vertices = (vertex*)linearAlloc(sizeof(vertex) * 4);
+ vertices = (vertex *)linearAlloc(sizeof(vertex) * 4);
}
Sprite::~Sprite() {
@@ -61,8 +61,8 @@ void Sprite::create(uint16 width, uint16 height, const Graphics::PixelFormat &f)
actualWidth = width;
actualHeight = height;
format = f;
- w = std::max(nextHigher2(width), 64u);
- h = std::max(nextHigher2(height), 64u);;
+ w = MAX(nextHigher2(width), 64u);
+ h = MAX(nextHigher2(height), 64u);;
pitch = w * format.bytesPerPixel;
dirtyPixels = true;
@@ -110,7 +110,7 @@ void Sprite::render() {
}
C3D_TexBind(0, &texture);
- C3D_BufInfo* bufInfo = C3D_GetBufInfo();
+ C3D_BufInfo *bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo);
BufInfo_Add(bufInfo, vertices, sizeof(vertex), 2, 0x10);
C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 4);
Commit: bfb9ecec3573ed07bc9639426efd8289d05e00a6
https://github.com/scummvm/scummvm/commit/bfb9ecec3573ed07bc9639426efd8289d05e00a6
Author: Thomas Edvalson (machin3 at gmail.com)
Date: 2016-04-19T14:52:58-04:00
Commit Message:
3DS: Add README
Changed paths:
A backends/platform/3ds/README
diff --git a/backends/platform/3ds/README b/backends/platform/3ds/README
new file mode 100644
index 0000000..516e694
--- /dev/null
+++ b/backends/platform/3ds/README
@@ -0,0 +1,185 @@
+ScummVM 3DS README
+------------------------------------------------------------------------
+
+Table of Contents:
+------------------
+1.0) Installation
+ * 1.1 3DSX installation
+ * 1.2 CIA installation
+2.0) Controls
+ * 2.1 Default key mappings
+ * 2.2 Hover mode
+ * 2.3 Drag mode
+3.0) Supported Games
+4.0) Compiling
+ * 4.1 Prerequisites
+ * * 4.1.1 Compiling third-party libraries
+ * 4.2 Compiling ScummVM
+ * 4.3 Warning for 3DSX build
+
+
+
+1.0) Installation
+-----------------
+There are two possible formats to be used: 3DSX and CIA (recommended).
+The 3DSX format is exclusively used by the Homebrew Launcher and its derivatives.
+The CIA format can be installed directly to the 3DS home menu and can be launched
+using any CFW (Custom Firmware) of your choice.
+
+Installing the Homebrew Launcher or any CFW is beyond the scope of this README.
+Look elsewhere to see how to install those if you do not already have them set up.
+
+
+1.1) 3DSX installation
+----------------
+The CIA format is recommended for stability and maximum game support. If that is
+not an option, you will need one of a collection of 3DS titles installed on your
+system in order to properly launch ScummVM as a 3DSX. This is because the
+Homebrew Launcher hijacks other processes to run 3DSX homebrew, and ScummVM is a
+particularly large homebrew that can't be launched with the resources provided
+by standard system applications.
+
+You will need one of the following (installed or physically in cart slot):
+
+- Youtube
+- Monster Hunter 4 Ultimate Special Demo
+- Monster Hunter 4 Ultimate
+- Monster Hunter 4G
+- Super Smash Bros. for Nintendo 3DS Demo
+- Super Smash Bros. for Nintendo 3DS Special Demo
+- Super Smash Bros. for Nintendo 3DS
+
+Once you have one of the above, you need to merely extract all ScummVM 3DS files
+to the root of your SD card so that all files reside in the /3ds/scummvm/ directory.
+
+
+1.2) CIA installation
+---------------------
+The CIA format requires a DSP binary dump saved on your SD card as /3ds/dspfirm.cdc
+for proper audio support. You can search online to find software to dump this.
+Not having this file will cause many problems with games that need audio, sometimes
+even crashing, so this is NOT considered optional.
+
+Using any CIA installation software (search elsewhere for that), you need to install
+the scummvm.cia file. Then, just like what is done with the 3DSX installation, you
+need to extract all ScummVM 3DS files (scummvm.cia excluded) to the root of your SD
+card so that all files reside in the /3ds/scummvm/ directory.
+
+
+
+2.0) Controls
+-------------
+
+2.1) Default key mappings
+-------------------------
+The D-Pad and A/B/X/Y buttons have mirrored usage. So they do the same things
+depending on if you're right or left-handed.
+
+| Buttons | Function |
+|------------|--------------------------------|
+| A / D-left | Left-click |
+| X / D-up | Right-click |
+| B / D-down | ESC (skips cutscenes and such) |
+| L | Use virtual keyboard |
+| R | Toggle hover/drag modes |
+| Start | Open game menu |
+| Select | Open 3DS config menu |
+| Circle Pad | Move the cursor |
+
+
+2.2) Hover mode
+---------------
+When you use the touchscreen, you are simulating the mere moving of the mouse. You
+can click only with taps, meaning it is impossible to drag stuff or hold down a
+mouse button without using buttons mapped to right/left-click.
+
+
+2.3) Drag mode
+--------------
+Every time you touch and release the touchscreen, you are simulating the click and
+release of the mouse buttons. At the moment, this is only a left-click.
+
+
+
+3.0) Supported Games
+--------------------
+The full game engine compatibility list can be found here:
+http://scummvm.org/compatibility/
+
+While all the above games should run on the 3DS (report if they do not), there are
+many games which are unplayable due to the lack of CPU speed on the 3DS. So if
+you play any games that run really slow, this is not considered a bug, but rather
+a hardware limitation. Though possible GPU optimizations are always in the works.
+The New 3DS console has much better performance, but there are still many newer and
+high-resolution games that cannot be played. A list of these unplayable games and
+game engines will eventually be listed here.
+
+
+
+4.0) Compiling
+--------------
+
+4.1) Prerequisites
+------------------
+ - devkitARM (presumably with libctru, picasso and such)
+ - citro3d
+ - Optional: You should compile third-party libraries for the 3ds (commonly referred
+ to as portlibs in the devkitPRO community). Some games requires these to operate
+ properly.
+
+
+4.1.1) Compiling third-party libraries
+--------------------------------------
+Most libraries used can be compiled with same commands and configuration flags.
+
+It is assumed that you have these environment variables defined:
+ - DEVKITPRO Your root devkitPro directory
+ - DEVKITARM Your root devkitARM directory (probably same as $DEVKITPRO/devkitARM)
+ - CTRULIB Your root libctru directory (probably same as $DEVKITPRO/libctru)
+
+In the source directory of the library:
+ - $ export PORTLIBS=$DEVKITPRO/portlibs/armv6k
+ - $ export PATH=$DEVKITARM/bin:$PATH
+ - $ export PKG_CONFIG_PATH=$PORTLIBS/lib/pkgconfig
+ - $ export CFLAGS="-g -march=armv6k -mtune=mpcore -mfloat-abi=hard -O2
+ -mword-relocations -ffunction-sections -fdata-sections"
+ - $ export CPPFLAGS="-I$PORTLIBS/include -I$CTRULIB/include"
+ - $ export LDFLAGS="-L$PORTLIBS/lib"
+ - $ mkdir -p $PORTLIBS
+ - $ ./configure --prefix=$PORTLIBS --host=arm-none-eabi --disable-shared
+ --enable-static
+ - $ make
+ - $ make install
+
+Useful libraries (and special config flags needed):
+ - zlib
+ - libpng
+ - libjpeg
+ - freetype2 --without-bzip2 --without-harfbuzz
+ - libmad
+ - tremor
+ - flac --disable-cpplibs --without-flac
+ - faad
+
+
+4.2) Compiling ScummVM
+----------------------
+ - $ ./configure --host=3ds
+ - $ make
+
+Additionally compile to specific formats to be used on the 3ds:
+ - $ make scummvm.3dsx
+ - $ make scummvm.cia
+
+
+4.3) Warning for 3DSX build
+---------------------------
+The above configuration command will include all game engines by default and will
+likely be too massive to run using the 3DSX format. Until dynamic modules are figured
+out, you should configure engines like this for 3DSX builds:
+
+ - $ ./configure --host=3ds --disable-all-engines--enable-engine=scumm-7-8,myst,riven,
+ sword1,sword2,sword25,sci,lure,sky,agi,agos
+
+Choose whatever engines you want, but if the ELF's .text section exceeds ~10MB, it
+won't be playable unless it's a CIA.
Commit: 1531b4ddbf685f22970b7365515318b847e4f4f3
https://github.com/scummvm/scummvm/commit/1531b4ddbf685f22970b7365515318b847e4f4f3
Author: Thomas Edvalson (machin3 at gmail.com)
Date: 2016-04-22T16:43:59-04:00
Commit Message:
3DS: Add config class/dialog, c-pad cursor control, and option to disable screens
Changed paths:
A backends/platform/3ds/config.cpp
A backends/platform/3ds/config.h
A backends/platform/3ds/options-dialog.cpp
A backends/platform/3ds/options-dialog.h
backends/platform/3ds/app/scummvm.rsf
backends/platform/3ds/main.cpp
backends/platform/3ds/module.mk
backends/platform/3ds/osystem-audio.cpp
backends/platform/3ds/osystem-events.cpp
backends/platform/3ds/osystem-graphics.cpp
backends/platform/3ds/osystem.cpp
backends/platform/3ds/osystem.h
diff --git a/backends/platform/3ds/app/scummvm.rsf b/backends/platform/3ds/app/scummvm.rsf
index d403bdb..a451894 100644
--- a/backends/platform/3ds/app/scummvm.rsf
+++ b/backends/platform/3ds/app/scummvm.rsf
@@ -170,6 +170,7 @@ AccessControlInfo:
- soc:U
- ssl:C
- y2r:u
+ - gsp::Lcd
SystemControlInfo:
diff --git a/backends/platform/3ds/config.cpp b/backends/platform/3ds/config.cpp
new file mode 100644
index 0000000..117b979
--- /dev/null
+++ b/backends/platform/3ds/config.cpp
@@ -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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "osystem.h"
+#include "options-dialog.h"
+#include "common/config-manager.h"
+#include <3ds.h>
+
+namespace _3DS {
+
+Config config;
+static Common::String prefix = "3ds_";
+
+static bool confGetBool(Common::String key, bool defaultVal) {
+ if (ConfMan.hasKey(prefix + key))
+ return ConfMan.getBool(prefix + key);
+ return defaultVal;
+}
+
+static void confSetBool(Common::String key, bool val) {
+ ConfMan.setBool(prefix + key, val);
+}
+
+static int confGetInt(Common::String key, int defaultVal) {
+ if (ConfMan.hasKey(prefix + key))
+ return ConfMan.getInt(prefix + key);
+ return defaultVal;
+}
+
+static void confSetInt(Common::String key, int val) {
+ ConfMan.setInt(prefix + key, val);
+}
+
+void loadConfig() {
+ config.showCursor = confGetBool("showcursor", true);
+ config.snapToBorder = confGetBool("snaptoborder", true);
+ config.stretchToFit = confGetBool("stretchtofit", false);
+ config.sensitivity = confGetInt("sensitivity", -5);
+ config.screen = confGetInt("screen", kScreenBoth);
+
+ // Turn off the backlight of any screen not used
+ if (R_SUCCEEDED(gspLcdInit())) {
+ if (config.screen == kScreenTop) {
+ GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_TOP);
+ GSPLCD_PowerOffBacklight(GSPLCD_SCREEN_BOTTOM);
+ } else if (config.screen == kScreenBottom) {
+ GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTTOM);
+ GSPLCD_PowerOffBacklight(GSPLCD_SCREEN_TOP);
+ } else
+ GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTH);
+ gspLcdExit();
+ }
+
+ OSystem_3DS *osys = (OSystem_3DS *)g_system;
+ osys->updateConfig();
+}
+
+void saveConfig() {
+ confSetBool("showcursor", config.showCursor);
+ confSetBool("snaptoborder", config.snapToBorder);
+ confSetBool("stretchtofit", config.stretchToFit);
+ confSetInt("sensitivity", config.sensitivity);
+ confSetInt("screen", config.screen);
+ ConfMan.flushToDisk();
+}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/config.h b/backends/platform/3ds/config.h
new file mode 100644
index 0000000..c8b7573
--- /dev/null
+++ b/backends/platform/3ds/config.h
@@ -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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CONFIG_3DS_H
+#define CONFIG_3DS_H
+
+#include "common/str.h"
+
+namespace _3DS {
+
+struct Config {
+ bool showCursor;
+ bool snapToBorder;
+ bool stretchToFit;
+ int sensitivity;
+ int screen;
+};
+
+extern Config config;
+
+void loadConfig();
+void saveConfig();
+
+} // namespace _3DS
+
+#endif // CONFIG_3DS_H
diff --git a/backends/platform/3ds/main.cpp b/backends/platform/3ds/main.cpp
index 4b5dbbb..6cc2c5c 100644
--- a/backends/platform/3ds/main.cpp
+++ b/backends/platform/3ds/main.cpp
@@ -20,8 +20,6 @@
*
*/
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
-
#include "osystem.h"
#include <3ds.h>
@@ -32,7 +30,7 @@ int main(int argc, char *argv[]) {
osSetSpeedupEnable(true);
// consoleInit(GFX_TOP, NULL);
- g_system = new OSystem_3DS();
+ g_system = new _3DS::OSystem_3DS();
assert(g_system);
// Invoke the actual ScummVM main entry point
@@ -42,8 +40,14 @@ int main(int argc, char *argv[]) {
// res = scummvm_main(argc, argv);
scummvm_main(0, nullptr);
- delete dynamic_cast<OSystem_3DS*>(g_system);
-
+ delete dynamic_cast<_3DS::OSystem_3DS*>(g_system);
+
+ // Turn on both screen backlights before exiting.
+ if (R_SUCCEEDED(gspLcdInit())) {
+ GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTH);
+ gspLcdExit();
+ }
+
cfguExit();
gfxExit();
return 0;
diff --git a/backends/platform/3ds/module.mk b/backends/platform/3ds/module.mk
index 9c1e26b..3eb15ae 100644
--- a/backends/platform/3ds/module.mk
+++ b/backends/platform/3ds/module.mk
@@ -5,6 +5,8 @@ MODULE_OBJS := \
shader.shbin.o \
sprite.o \
gui.o \
+ config.o \
+ options-dialog.o \
osystem.o \
osystem-graphics.o \
osystem-audio.o \
diff --git a/backends/platform/3ds/options-dialog.cpp b/backends/platform/3ds/options-dialog.cpp
new file mode 100644
index 0000000..0f8bfd0
--- /dev/null
+++ b/backends/platform/3ds/options-dialog.cpp
@@ -0,0 +1,98 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "options-dialog.h"
+#include "config.h"
+#include "gui/dialog.h"
+#include "gui/gui-manager.h"
+#include "gui/widgets/list.h"
+#include "gui/widgets/tab.h"
+#include "osystem.h"
+#include "engines/scumm/scumm.h"
+#include "gui/widgets/popup.h"
+
+#include "common/translation.h"
+
+namespace _3DS {
+
+bool optionMenuOpened = false;
+
+OptionsDialog::OptionsDialog() : GUI::Dialog(20, 20, 280, 200) {
+
+ optionMenuOpened = true;
+
+ new GUI::ButtonWidget(this, 120, 180, 72, 16, _("~C~lose"), 0, GUI::kCloseCmd);
+ new GUI::ButtonWidget(this, 200, 180, 72, 16, _("~S~ave"), 0, GUI::kOKCmd);
+
+ _showCursorCheckbox = new GUI::CheckboxWidget(this, 5, 5, 130, 20, _("Show mouse cursor"), 0, 0, 'T');
+ _showCursorCheckbox->setState(config.showCursor);
+
+ _snapToBorderCheckbox = new GUI::CheckboxWidget(this, 5, 22, 130, 20, _("Snap to edges"), 0, 0, 'T');
+ _snapToBorderCheckbox->setState(config.snapToBorder);
+
+ _stretchToFitCheckbox = new GUI::CheckboxWidget(this, 140, 5, 130, 20, _("Stretch to fit"), 0, 0, 'T');
+ _stretchToFitCheckbox->setState(config.stretchToFit);
+
+ new GUI::StaticTextWidget(this, 0, 60, 110, 15, _("Use Screen:"), Graphics::kTextAlignRight);
+ _screenRadioGroup = new GUI::RadiobuttonGroup(this, kScreenRadioGroup);
+ _screenTopRadioWidget = new GUI::RadiobuttonWidget(this, 120, 50, 60, 20, _screenRadioGroup, kScreenTop, _("Top"));
+ _screenBottomRadioWidget = new GUI::RadiobuttonWidget(this, 190, 50, 80, 20, _screenRadioGroup, kScreenBottom, _("Bottom"));
+ _screenBothRadioWidget = new GUI::RadiobuttonWidget(this, 155, 70, 80, 20, _screenRadioGroup, kScreenBoth, _("Both"));
+ _screenRadioGroup->setValue(config.screen);
+
+ new GUI::StaticTextWidget(this, 0, 100, 110, 15, _("C-Pad Sensitivity:"), Graphics::kTextAlignRight);
+ _sensitivity = new GUI::SliderWidget(this, 115, 100, 160, 15, "TODO: Add tooltip", 1);
+ _sensitivity->setMinValue(-15);
+ _sensitivity->setMaxValue(30);
+ _sensitivity->setValue(config.sensitivity);
+ _sensitivity->setFlags(GUI::WIDGET_CLEARBG);
+}
+
+OptionsDialog::~OptionsDialog() {
+ optionMenuOpened = false;
+}
+
+void OptionsDialog::updateConfigManager() {
+ config.showCursor = _showCursorCheckbox->getState();
+ config.snapToBorder = _snapToBorderCheckbox->getState();
+ config.stretchToFit = _stretchToFitCheckbox->getState();
+ config.sensitivity = _sensitivity->getValue();
+ config.screen = _screenRadioGroup->getValue();
+ saveConfig();
+ loadConfig();
+}
+
+void OptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
+ switch(cmd) {
+ case GUI::kOKCmd:
+ updateConfigManager();
+ // Fall through
+ case GUI::kCloseCmd:
+ close();
+ break;
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ break;
+ }
+}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/options-dialog.h b/backends/platform/3ds/options-dialog.h
new file mode 100644
index 0000000..6673b88
--- /dev/null
+++ b/backends/platform/3ds/options-dialog.h
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef OPTIONS_DIALOG_3DS_H
+#define OPTIONS_DIALOG_3DS_H
+
+
+#include "common/scummsys.h"
+#include "common/str.h"
+#include "gui/object.h"
+#include "gui/widget.h"
+#include "gui/dialog.h"
+#include "gui/widgets/tab.h"
+#include "scumm/dialogs.h"
+
+namespace _3DS {
+
+enum {
+ kSave = 0x10000000,
+ kScreenRadioGroup,
+ kScreenTop,
+ kScreenBottom,
+ kScreenBoth,
+};
+
+extern bool optionMenuOpened;
+
+class OptionsDialog : public GUI::Dialog {
+
+public:
+ OptionsDialog();
+ ~OptionsDialog();
+
+protected:
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+ void updateConfigManager();
+
+ GUI::SliderWidget *_sensitivity;
+ GUI::CheckboxWidget *_showCursorCheckbox;
+ GUI::CheckboxWidget *_snapToBorderCheckbox;
+ GUI::CheckboxWidget *_stretchToFitCheckbox;
+
+ GUI::RadiobuttonGroup *_screenRadioGroup;
+ GUI::RadiobuttonWidget *_screenTopRadioWidget;
+ GUI::RadiobuttonWidget *_screenBottomRadioWidget;
+ GUI::RadiobuttonWidget *_screenBothRadioWidget;
+};
+
+} // namespace _3DS
+
+#endif // OPTIONS_DIALOG_3DS_H
diff --git a/backends/platform/3ds/osystem-audio.cpp b/backends/platform/3ds/osystem-audio.cpp
index da74ab6..17e419c 100644
--- a/backends/platform/3ds/osystem-audio.cpp
+++ b/backends/platform/3ds/osystem-audio.cpp
@@ -23,6 +23,8 @@
#include "osystem.h"
#include "audio/mixer.h"
+namespace _3DS {
+
static bool hasAudio = false;
static void audioThreadFunc(void *arg) {
@@ -104,3 +106,5 @@ Audio::Mixer *OSystem_3DS::getMixer() {
assert(_mixer);
return _mixer;
}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
index 5135e3a..ae8a9b8 100644
--- a/backends/platform/3ds/osystem-events.cpp
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -21,12 +21,20 @@
*/
#include "backends/timer/default/default-timer.h"
+#include "engines/engine.h"
#include "gui.h"
+#include "options-dialog.h"
+#include "config.h"
#include "osystem.h"
+namespace _3DS {
+
static Common::Mutex *eventMutex;
static InputMode inputMode = MODE_DRAG;
static aptHookCookie cookie;
+static bool optionMenuOpening = false;
+static Common::String messageOSD;
+static bool showMessageOSD = false;
static void pushEventQueue(Common::Queue<Common::Event> *queue, Common::Event &event) {
Common::StackLock lock(*eventMutex);
@@ -40,6 +48,12 @@ static void eventThreadFunc(void *arg) {
uint32 touchStartTime = osys->getMillis();
touchPosition lastTouch = {0, 0};
bool isRightClick = false;
+ float cursorX = 0;
+ float cursorY = 0;
+ float cursorDeltaX = 0;
+ float cursorDeltaY = 0;
+ int circleDeadzone = 20;
+ int borderSnapZone = 6;
Common::Event event;
while (!osys->exiting) {
@@ -49,12 +63,35 @@ static void eventThreadFunc(void *arg) {
hidScanInput();
touchPosition touch;
+ circlePosition circle;
u32 held = hidKeysHeld();
u32 keysPressed = hidKeysDown();
u32 keysReleased = hidKeysUp();
+ // C-Pad used to control the cursor
+ hidCircleRead(&circle);
+ if (circle.dx < circleDeadzone && circle.dx > -circleDeadzone)
+ circle.dx = 0;
+ if (circle.dy < circleDeadzone && circle.dy > -circleDeadzone)
+ circle.dy = 0;
+ cursorDeltaX = (0.0002f + config.sensitivity / 100000.f) * circle.dx * abs(circle.dx);
+ cursorDeltaY = (0.0002f + config.sensitivity / 100000.f) * circle.dy * abs(circle.dy);
+
+ // Touch screen events
if (held & KEY_TOUCH) {
hidTouchRead(&touch);
+ if (config.snapToBorder) {
+ if (touch.px < borderSnapZone)
+ touch.px = 0;
+ if (touch.px > 319 - borderSnapZone)
+ touch.px = 319;
+ if (touch.py < borderSnapZone)
+ touch.py = 0;
+ if (touch.py > 239 - borderSnapZone)
+ touch.py = 239;
+ }
+ cursorX = touch.px;
+ cursorY = touch.py;
osys->transformPoint(touch);
osys->warpMouse(touch.px, touch.py);
@@ -89,7 +126,24 @@ static void eventThreadFunc(void *arg) {
event.type = isRightClick ? Common::EVENT_RBUTTONUP : Common::EVENT_LBUTTONUP;
pushEventQueue(eventQueue, event);
}
+ } else if (cursorDeltaX != 0 || cursorDeltaY != 0) {
+ cursorX += cursorDeltaX;
+ cursorY -= cursorDeltaY;
+ if (cursorX < 0) cursorX = 0;
+ if (cursorY < 0) cursorY = 0;
+ if (cursorX > 320) cursorX = 320;
+ if (cursorY > 240) cursorY = 240;
+ lastTouch.px = cursorX;
+ lastTouch.py = cursorY;
+ osys->transformPoint(lastTouch);
+ osys->warpMouse(lastTouch.px, lastTouch.py);
+ event.mouse.x = lastTouch.px;
+ event.mouse.y = lastTouch.py;
+ event.type = Common::EVENT_MOUSEMOVE;
+ pushEventQueue(eventQueue, event);
}
+
+ // Button events
if (keysPressed & KEY_R) {
if (inputMode == MODE_DRAG) {
inputMode = MODE_HOVER;
@@ -99,22 +153,24 @@ static void eventThreadFunc(void *arg) {
osys->displayMessageOnOSD("Drag Mode");
}
}
- if (keysPressed & KEY_A || keysPressed & KEY_DLEFT) {
+ if (keysPressed & KEY_A || keysPressed & KEY_DLEFT || keysReleased & KEY_A || keysReleased & KEY_DLEFT) {
// SIMULATE LEFT CLICK
event.mouse.x = lastTouch.px;
event.mouse.y = lastTouch.py;
- event.type = Common::EVENT_LBUTTONDOWN;
- pushEventQueue(eventQueue, event);
- event.type = Common::EVENT_LBUTTONUP;
+ if (keysPressed & KEY_A || keysPressed & KEY_DLEFT)
+ event.type = Common::EVENT_LBUTTONDOWN;
+ else
+ event.type = Common::EVENT_LBUTTONUP;
pushEventQueue(eventQueue, event);
}
- if (keysPressed & KEY_X || keysPressed & KEY_DUP) {
+ if (keysPressed & KEY_X || keysPressed & KEY_DUP || keysReleased & KEY_X || keysReleased & KEY_DUP) {
// SIMULATE RIGHT CLICK
event.mouse.x = lastTouch.px;
event.mouse.y = lastTouch.py;
- event.type = Common::EVENT_RBUTTONDOWN;
- pushEventQueue(eventQueue, event);
- event.type = Common::EVENT_RBUTTONUP;
+ if (keysPressed & KEY_X || keysPressed & KEY_DUP)
+ event.type = Common::EVENT_RBUTTONDOWN;
+ else
+ event.type = Common::EVENT_RBUTTONUP;
pushEventQueue(eventQueue, event);
}
if (keysPressed & KEY_L) {
@@ -126,8 +182,8 @@ static void eventThreadFunc(void *arg) {
pushEventQueue(eventQueue, event);
}
if (keysPressed & KEY_SELECT) {
- event.type = Common::EVENT_RTL;
- pushEventQueue(eventQueue, event);
+ if (!optionMenuOpened)
+ optionMenuOpening = true;
}
if (keysPressed & KEY_B || keysReleased & KEY_B || keysPressed & KEY_DDOWN || keysReleased & KEY_DDOWN) {
if (keysPressed & KEY_B || keysPressed & KEY_DDOWN)
@@ -146,25 +202,32 @@ static void eventThreadFunc(void *arg) {
}
static void aptHookFunc(APT_HookType hookType, void *param) {
- auto eventQueue = (Common::Queue<Common::Event> *)param;
OSystem_3DS *osys = (OSystem_3DS *)g_system;
- Common::Event event;
switch (hookType) {
case APTHOOK_ONSUSPEND:
case APTHOOK_ONSLEEP:
- event.type = Common::EVENT_MAINMENU;
- pushEventQueue(eventQueue, event);
+ if (g_engine)
+ g_engine->pauseEngine(true);
osys->sleeping = true;
+ if (R_SUCCEEDED(gspLcdInit())) {
+ GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTH);
+ gspLcdExit();
+ }
break;
case APTHOOK_ONRESTORE:
case APTHOOK_ONWAKEUP:
+ if (g_engine)
+ g_engine->pauseEngine(false);
osys->sleeping = false;
+ loadConfig();
break;
- default:
+ default: {
+ Common::StackLock lock(*eventMutex);
+ Common::Event event;
event.type = Common::EVENT_QUIT;
- pushEventQueue(eventQueue, event);
- break;
+ g_system->getEventManager()->pushEvent(event);
+ }
}
}
@@ -172,9 +235,8 @@ static void timerThreadFunc(void *arg) {
OSystem_3DS *osys = (OSystem_3DS *)arg;
DefaultTimerManager *tm = (DefaultTimerManager *)osys->getTimerManager();
while (!osys->exiting) {
- tm->handler();
g_system->delayMillis(10);
- aptMainLoop(); // Call apt hook when necessary
+ tm->handler();
}
}
@@ -185,7 +247,7 @@ void OSystem_3DS::initEvents() {
_timerThread = threadCreate(&timerThreadFunc, this, 32 * 1024, prio - 1, -2, false);
_eventThread = threadCreate(&eventThreadFunc, &_eventQueue, 32 * 1024, prio - 1, -2, false);
- aptHook(&cookie, aptHookFunc, &_eventQueue);
+ aptHook(&cookie, aptHookFunc, this);
}
void OSystem_3DS::destroyEvents() {
@@ -199,21 +261,33 @@ void OSystem_3DS::destroyEvents() {
void OSystem_3DS::transformPoint(touchPosition &point) {
if (!_overlayVisible) {
- point.px = static_cast<float>(point.px) / _gameTexture.getScaleX() - _gameX;
- point.py = static_cast<float>(point.py) / _gameTexture.getScaleY() - _gameY;
+ point.px = static_cast<float>(point.px) / _gameBottomTexture.getScaleX() - _gameBottomX;
+ point.py = static_cast<float>(point.py) / _gameBottomTexture.getScaleY() - _gameBottomY;
}
}
void OSystem_3DS::displayMessageOnOSD(const char *msg) {
- _messageOSD = msg;
- _showMessageOSD = true;
+ messageOSD = msg;
+ showMessageOSD = true;
}
bool OSystem_3DS::pollEvent(Common::Event &event) {
- if (_showMessageOSD) {
- _showMessageOSD = false;
- StatusMessageDialog dialog(_messageOSD, 800);
+ if (showMessageOSD) {
+ showMessageOSD = false;
+ StatusMessageDialog dialog(messageOSD, 800);
+ dialog.runModal();
+ }
+
+ aptMainLoop(); // Call apt hook when necessary
+
+ if (optionMenuOpening) {
+ optionMenuOpening = false;
+ OptionsDialog dialog;
+ if (g_engine)
+ g_engine->pauseEngine(true);
dialog.runModal();
+ if (g_engine)
+ g_engine->pauseEngine(false);
}
Common::StackLock lock(*eventMutex);
@@ -224,3 +298,5 @@ bool OSystem_3DS::pollEvent(Common::Event &event) {
event = _eventQueue.pop();
return true;
}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 0e50d2b..0cfd70c 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -24,6 +24,8 @@
#include "backends/platform/3ds/osystem.h"
#include "backends/platform/3ds/shader_shbin.h"
#include "common/rect.h"
+#include "options-dialog.h"
+#include "config.h"
// Used to transfer the final rendered display to the framebuffer
#define DISPLAY_TRANSFER_FLAGS \
@@ -32,6 +34,8 @@
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
+namespace _3DS {
+
void OSystem_3DS::initGraphics() {
_pfGame = Graphics::PixelFormat::createFormatCLUT8();
_pfGameTexture = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
@@ -79,7 +83,8 @@ void OSystem_3DS::initGraphics() {
void OSystem_3DS::destroyGraphics() {
_gameScreen.free();
- _gameTexture.free();
+ _gameTopTexture.free();
+ _gameBottomTexture.free();
_overlay.free();
shaderProgramFree(&_program);
@@ -92,16 +97,12 @@ void OSystem_3DS::destroyGraphics() {
}
bool OSystem_3DS::hasFeature(OSystem::Feature f) {
- return (f == OSystem::kFeatureFullscreenMode ||
- f == OSystem::kFeatureCursorPalette ||
+ return (f == OSystem::kFeatureCursorPalette ||
f == OSystem::kFeatureOverlaySupportsAlpha);
}
void OSystem_3DS::setFeatureState(OSystem::Feature f, bool enable) {
switch (f) {
- case OSystem::kFeatureFullscreenMode:
- _isFullscreen = enable;
- break;
case OSystem::kFeatureCursorPalette:
_cursorPaletteEnabled = enable;
flushCursor();
@@ -113,8 +114,6 @@ void OSystem_3DS::setFeatureState(OSystem::Feature f, bool enable) {
bool OSystem_3DS::getFeatureState(OSystem::Feature f) {
switch (f) {
- case OSystem::kFeatureFullscreenMode:
- return _isFullscreen;
case OSystem::kFeatureCursorPalette:
return _cursorPaletteEnabled;
default:
@@ -147,7 +146,7 @@ void OSystem_3DS::initSize(uint width, uint height,
debug("3ds initsize w:%d h:%d", width, height);
_gameWidth = width;
_gameHeight = height;
- _gameTexture.create(width, height, _pfGameTexture);
+ _gameTopTexture.create(width, height, _pfGameTexture);
_overlay.create(getOverlayWidth(), getOverlayHeight(), _pfGameTexture);
if (format) {
@@ -160,30 +159,48 @@ void OSystem_3DS::initSize(uint width, uint height,
_focusDirty = true;
_focusRect = Common::Rect(_gameWidth, _gameHeight);
- if (_isFullscreen) {
- _gameRatio = 320.f / 240.f;
- _gameX = _gameY = 0;
- _gameTexture.setScale(320.f / width, 240.f / height);
+ updateSize();
+}
+
+void OSystem_3DS::updateSize() {
+ if (config.stretchToFit) {
+ _gameTopX = _gameTopY = _gameBottomX = _gameBottomY = 0;
+ _gameTopTexture.setScale(400.f / _gameWidth, 240.f / _gameHeight);
+ _gameBottomTexture.setScale(320.f / _gameWidth, 240.f / _gameHeight);
} else {
- _gameRatio = static_cast<float>(width) / height;
- if (width > height) {
- _gameX = 0;
- _gameY = (240.f - 320.f / width * height) / 2.f;
+ float ratio = static_cast<float>(_gameWidth) / _gameHeight;
+
+ if (ratio > 400.f / 240.f) {
+ float r = 400.f / _gameWidth;
+ _gameTopTexture.setScale(r, r);
+ _gameTopX = 0;
+ _gameTopY = (240.f - r * _gameHeight) / 2.f;
} else {
- _gameY = 0;
- _gameX = (320.f - 240.f / height * width) / 2.f;
+ float r = 240.f / _gameHeight;
+ _gameTopTexture.setScale(r, r);
+ _gameTopY = 0;
+ _gameTopX = (400.f - r * _gameWidth) / 2.f;
+ }
+ if (ratio > 320.f / 240.f) {
+ float r = 320.f / _gameWidth;
+ _gameBottomTexture.setScale(r, r);
+ _gameBottomX = 0;
+ _gameBottomY = (240.f - r * _gameHeight) / 2.f;
+ } else {
+ float r = 240.f / _gameHeight;
+ _gameBottomTexture.setScale(r, r);
+ _gameBottomY = 0;
+ _gameBottomX = (320.f - r * _gameWidth) / 2.f;
}
- _gameTexture.setScale((width > 320) ? 320.f / width : 1.f,
- (height > 240) ? 240.f / height : 1.f);
}
- _gameTexture.setPosition(_gameX, _gameY);
- _cursorTexture.setScale(_gameTexture.getScaleX(), _gameTexture.getScaleY());
-
- float ratio = 400.f / _gameWidth;
- int y = (_gameHeight * ratio - 240.f) / 2;
- Mtx_Identity(&_focusMatrix);
- Mtx_Translate(&_focusMatrix, 0, -y, 0);
- Mtx_Scale(&_focusMatrix, ratio, ratio, 1.f);
+ _gameTopTexture.setPosition(_gameTopX, _gameTopY);
+ _gameBottomTexture.setPosition(_gameBottomX, _gameBottomY);
+ if (_overlayVisible)
+ _cursorTexture.setScale(1.f, 1.f);
+ else if (config.screen == kScreenTop)
+ _cursorTexture.setScale(_gameTopTexture.getScaleX(), _gameTopTexture.getScaleY());
+ else
+ _cursorTexture.setScale(_gameBottomTexture.getScaleX(), _gameBottomTexture.getScaleY());
}
Common::List<Graphics::PixelFormat> OSystem_3DS::getSupportedFormats() const {
@@ -225,17 +242,17 @@ void OSystem_3DS::copyRectToScreen(const void *buf, int pitch, int x,
Graphics::Surface subSurface = _gameScreen.getSubArea(rect);
Graphics::Surface *convertedSubSurface = subSurface.convertTo(_pfGameTexture, _palette);
- _gameTexture.copyRectToSurface(*convertedSubSurface, x, y, Common::Rect(w, h));
+ _gameTopTexture.copyRectToSurface(*convertedSubSurface, x, y, Common::Rect(w, h));
convertedSubSurface->free();
delete convertedSubSurface;
- _gameTexture.markDirty();
+ _gameTopTexture.markDirty();
}
void OSystem_3DS::flushGameScreen() {
Graphics::Surface *converted = _gameScreen.convertTo(_pfGameTexture, _palette);
- _gameTexture.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
- _gameTexture.markDirty();
+ _gameTopTexture.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
+ _gameTopTexture.markDirty();
converted->free();
delete converted;
}
@@ -257,23 +274,36 @@ void OSystem_3DS::updateScreen() {
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
// Render top screen
C3D_FrameDrawOn(_renderTargetTop);
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionTop);
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, &_focusMatrix);
- _gameTexture.render();
- _gameTexture.render();
+ if (config.screen == kScreenTop || config.screen == kScreenBoth) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionTop);
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _gameTopTexture.getMatrix());
+ _gameTopTexture.render();
+ _gameTopTexture.render();
+ if (_overlayVisible && config.screen == kScreenTop) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
+ _overlay.render();
+ }
+ if (_cursorVisible && config.showCursor && config.screen == kScreenTop) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
+ _cursorTexture.render();
+ }
+ }
// Render bottom screen
C3D_FrameDrawOn(_renderTargetBottom);
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionBottom);
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _gameTexture.getMatrix());
- _gameTexture.render();
- if (_overlayVisible) {
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
- _overlay.render();
- }
- if (_cursorVisible) {
- C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
- _cursorTexture.render();
+ if (config.screen == kScreenBottom || config.screen == kScreenBoth) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionBottom);
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _gameBottomTexture.getMatrix());
+ _gameTopTexture.render();
+ _gameTopTexture.render();
+ if (_overlayVisible) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
+ _overlay.render();
+ }
+ if (_cursorVisible && config.showCursor) {
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
+ _cursorTexture.render();
+ }
}
C3D_FrameEnd(0);
}
@@ -281,7 +311,8 @@ void OSystem_3DS::updateScreen() {
void OSystem_3DS::setShakePos(int shakeOffset) {
// TODO: implement this in overlay, top screen, and mouse too
_screenShakeOffset = shakeOffset;
- _gameTexture.setPosition(_gameX, _gameY + shakeOffset);
+ _gameTopTexture.setPosition(_gameTopX, _gameTopY + _gameTopTexture.getScaleY() * shakeOffset);
+ _gameBottomTexture.setPosition(_gameBottomX, _gameBottomY + _gameBottomTexture.getScaleY() * shakeOffset);
}
void OSystem_3DS::setFocusRectangle(const Common::Rect &rect) {
@@ -363,13 +394,13 @@ void OSystem_3DS::updateFocus() {
void OSystem_3DS::showOverlay() {
_overlayVisible = true;
- _cursorTexture.setScale(1.f, 1.f);
+ updateSize();
updateScreen();
}
void OSystem_3DS::hideOverlay() {
_overlayVisible = false;
- _cursorTexture.setScale(_gameTexture.getScaleX(), _gameTexture.getScaleY());
+ updateSize();
updateScreen();
}
@@ -410,9 +441,25 @@ bool OSystem_3DS::showMouse(bool visible) {
void OSystem_3DS::warpMouse(int x, int y) {
_cursorX = x;
_cursorY = y;
+ warning("x:%d y:%d", x, y);
// TODO: adjust for _cursorScalable ?
- _cursorTexture.setPosition(x - _cursorHotspotX + (_overlayVisible ? 0 : _gameX),
- y - _cursorHotspotY + (_overlayVisible ? 0 : _gameY));
+ int offsetx = 0;
+ int offsety = 0;
+ x -= _cursorHotspotX;
+ y -= _cursorHotspotY;
+ if (!_overlayVisible) {
+ offsetx += config.screen == kScreenTop ? _gameTopX : _gameBottomX;
+ offsety += config.screen == kScreenTop ? _gameTopY : _gameBottomY;
+ }
+ float scalex = config.screen == kScreenTop ? (float)_gameTopTexture.actualWidth / _gameWidth : 1.f;
+ float scaley = config.screen == kScreenTop ? (float)_gameTopTexture.actualHeight / _gameHeight : 1.f;
+ _cursorTexture.setPosition(scalex * x + offsetx,
+ scaley * y + offsety);
+}
+
+void OSystem_3DS::setCursorDelta(float deltaX, float deltaY) {
+ _cursorDeltaX = deltaX;
+ _cursorDeltaY = deltaY;
}
void OSystem_3DS::setMouseCursor(const void *buf, uint w, uint h,
@@ -466,3 +513,5 @@ void OSystem_3DS::flushCursor() {
}
}
}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index af0b7b5..f6278eb 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -33,12 +33,15 @@
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/str.h"
+#include "config.h"
#include "backends/fs/posix/posix-fs-factory.h"
#include "backends/fs/posix/posix-fs.h"
#include <unistd.h>
#include <time.h>
+namespace _3DS {
+
OSystem_3DS::OSystem_3DS():
_focusDirty(true),
_focusRect(Common::Rect(1, 1)),
@@ -55,19 +58,20 @@ OSystem_3DS::OSystem_3DS():
_focusStepScaleX(0.f),
_focusStepScaleY(0.f),
_focusClearTime(0),
- _showMessageOSD(false),
- _isFullscreen(false),
+ _cursorPaletteEnabled(false),
_cursorVisible(false),
_cursorScalable(false),
- _cursorPaletteEnabled(false),
_cursorX(0),
_cursorY(0),
_cursorHotspotX(0),
_cursorHotspotY(0),
- _gameX(0),
- _gameY(0),
+ _gameTopX(0),
+ _gameTopY(0),
+ _gameBottomX(0),
+ _gameBottomY(0),
_gameWidth(320),
_gameHeight(240),
+ _overlayVisible(false),
exiting(false),
sleeping(false)
{
@@ -91,6 +95,7 @@ void OSystem_3DS::quit() {
}
void OSystem_3DS::initBackend() {
+ loadConfig();
ConfMan.registerDefault("fullscreen", true);
ConfMan.registerDefault("aspect_ratio", true);
if (!ConfMan.hasKey("vkeybd_pack_name"))
@@ -111,6 +116,13 @@ void OSystem_3DS::initBackend() {
EventsBaseBackend::initBackend();
}
+void OSystem_3DS::updateConfig() {
+ if (_gameScreen.getPixels()) {
+ updateSize();
+ warpMouse(_cursorX, _cursorY);
+ }
+}
+
Common::String OSystem_3DS::getDefaultConfigFileName() {
return "/3ds/scummvm/scummvm.ini";
}
@@ -177,3 +189,5 @@ void OSystem_3DS::fatalError() {
void OSystem_3DS::logMessage(LogMessageType::Type type, const char *message) {
printf("3DS log: %s\n", message);
}
+
+} // namespace _3DS
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index a8c2a90..478085a 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -35,7 +35,9 @@
#include "common/queue.h"
#define TICKS_PER_MSEC 268123
-
+
+namespace _3DS {
+
enum {
GFX_LINEAR = 0,
GFX_NEAREST = 1
@@ -54,7 +56,7 @@ static const OSystem::GraphicsMode s_graphicsModes[] = {
class OSystem_3DS : public EventsBaseBackend, public PaletteManager {
public:
OSystem_3DS();
- ~OSystem_3DS();
+ virtual ~OSystem_3DS();
volatile bool exiting;
volatile bool sleeping;
@@ -130,9 +132,14 @@ public:
const Graphics::PixelFormat *format = NULL);
void setCursorPalette(const byte *colors, uint start, uint num);
+ // Transform point from touchscreen coords into gamescreen coords
void transformPoint(touchPosition &point);
+ void setCursorDelta(float deltaX, float deltaY);
+
void updateFocus();
+ void updateConfig();
+ void updateSize();
private:
void initGraphics();
@@ -150,8 +157,8 @@ protected:
private:
u16 _gameWidth, _gameHeight;
- u16 _gameX, _gameY;
- float _gameRatio;
+ u16 _gameTopX, _gameTopY;
+ u16 _gameBottomX, _gameBottomY;
// Audio
Thread audioThread;
@@ -164,12 +171,12 @@ private:
byte _cursorPalette[3 * 256];
Graphics::Surface _gameScreen;
- Sprite _gameTexture;
+ Sprite _gameTopTexture;
+ Sprite _gameBottomTexture;
Sprite _overlay;
int _screenShakeOffset;
bool _overlayVisible;
- bool _isFullscreen;
DVLB_s *_dvlb;
shaderProgram_s _program;
@@ -196,9 +203,6 @@ private:
Thread _eventThread;
Thread _timerThread;
Common::Queue<Common::Event> _eventQueue;
-
- Common::String _messageOSD;
- bool _showMessageOSD;
// Cursor
Graphics::Surface _cursor;
@@ -206,9 +210,12 @@ private:
bool _cursorPaletteEnabled;
bool _cursorVisible;
bool _cursorScalable;
- int _cursorX, _cursorY;
+ float _cursorX, _cursorY;
+ float _cursorDeltaX, _cursorDeltaY;
int _cursorHotspotX, _cursorHotspotY;
uint32 _cursorKeyColor;
};
+} // namespace _3DS
+
#endif
Commit: 2cd0a99e2bc28fa8ec17f782405c4abfd047f5e1
https://github.com/scummvm/scummvm/commit/2cd0a99e2bc28fa8ec17f782405c4abfd047f5e1
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-05-16T10:05:00+02:00
Commit Message:
Merge pull request #745 from Cruel/3ds
3DS: New Backend
Changed paths:
A backends/platform/3ds/3ds.mk
A backends/platform/3ds/README
A backends/platform/3ds/app/banner.png
A backends/platform/3ds/app/banner.wav
A backends/platform/3ds/app/icon.png
A backends/platform/3ds/app/scummvm.rsf
A backends/platform/3ds/config.cpp
A backends/platform/3ds/config.h
A backends/platform/3ds/gui.cpp
A backends/platform/3ds/gui.h
A backends/platform/3ds/main.cpp
A backends/platform/3ds/module.mk
A backends/platform/3ds/options-dialog.cpp
A backends/platform/3ds/options-dialog.h
A backends/platform/3ds/osystem-audio.cpp
A backends/platform/3ds/osystem-events.cpp
A backends/platform/3ds/osystem-graphics.cpp
A backends/platform/3ds/osystem.cpp
A backends/platform/3ds/osystem.h
A backends/platform/3ds/shader.v.pica
A backends/platform/3ds/sprite.cpp
A backends/platform/3ds/sprite.h
AUTHORS
base/commandLine.cpp
common/scummsys.h
configure
devtools/credits.pl
gui/credits.h
More information about the Scummvm-git-logs
mailing list