Skip to content
Permalink
Browse files

3DS: Implement magnify mode toggle on L and move keyboard to Y/DRIGHT

  • Loading branch information...
BallM4788 authored and bgK committed Oct 27, 2019
1 parent b342d42 commit 78de5724047f56bd3ecbfb9ab423bb6c943f6589
@@ -12,6 +12,7 @@ Table of Contents:
* 2.1 Default key mappings
* 2.2 Hover mode
* 2.3 Drag mode
* 2.4 Magnify mode

3.0) Supported Games

@@ -64,7 +65,8 @@ depending on if you're right or left-handed.
| A / D-left | Left-click |
| X / D-up | Right-click |
| B / D-down | ESC (skips cutscenes and such) |
| L | Use virtual keyboard |
| Y / D-right| Use virtual keyboard |
| L | Toggle magnify mode on/off |
| R | Toggle hover/drag modes |
| Start | Open game menu |
| Select | Open 3DS config menu |
@@ -81,6 +83,31 @@ mouse button without using buttons mapped to right/left-click.
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.

2.4) Magnify mode
-----------------
Due to the low resolutions of the 3DS's two screens (400x240 for the top, and 320x240
for the bottom), games that run at a higher resolution will inevitably lose some visual
detail from being scaled down. This can result in situations where essential information
is undiscernable, such as text. Magnify mode increases the scale factor of the top screen
back to 1; the bottom screen remains unchanged. The touchscreen can then be used to change
which part of the game display is being magnified. This can all be done even in situations
where the cursor is disabled, such as during full-motion video (FMV) segments.

When activating magnify mode, touchscreen controls are automatically switched to hover
mode; this is to reduce the risk of the user accidentally inputting a click when changing
the magnified area via dragging the stylus. Clicking can still be done at will as in normal
hover mode. Turning off magnify mode will revert controls back to what was being used
previously (ex: if drag mode was in use prior to activating magnify mode, drag mode will
be reactivated upon exiting magnify mode), as well as restore the top screen's previous
scale factor.

Currently magnify mode can only be used when the following conditions are met:
- In the 3DS config menu, "Use Screen" is set to "Both"
- A game is currently being played
- The horizontal and/or vertical resolution in-game is greater than that of the top screen

Magnify mode cannot be used in the Launcher menu.

3.0) Supported Games
--------------------
The full game engine compatibility list can be found here:
@@ -33,6 +33,7 @@ namespace _3DS {

static Common::Mutex *eventMutex;
static InputMode inputMode = MODE_DRAG;
static InputMode savedInputMode = MODE_DRAG;
static aptHookCookie cookie;
static bool optionMenuOpening = false;
static Common::String messageOSD;
@@ -146,13 +147,41 @@ static void eventThreadFunc(void *arg) {
}

// Button events
if (keysPressed & KEY_L) {
if (osys->getWidth() >= 400 || osys->getHeight() >= 240) {
if (osys->getMagnifyMode() == MODE_MAGOFF) {
osys->setMagnifyMode(MODE_MAGON);
if (inputMode == MODE_DRAG) {
inputMode = MODE_HOVER;
osys->displayMessageOnOSD("Magnify Mode On. Switching to Hover Mode...");
} else
osys->displayMessageOnOSD("Magnify Mode On");
} else {
osys->setMagnifyMode(MODE_MAGOFF);
osys->updateSize();
if (savedInputMode == MODE_DRAG) {
inputMode = savedInputMode;
osys->displayMessageOnOSD("Magnify Mode Off. Reactivating Drag Mode...");
} else
osys->displayMessageOnOSD("Magnify Mode Off");
}
} else {
if (osys->getWidth() == 0 || osys->getHeight() == 0) {
osys->displayMessageOnOSD("Magnify Mode cannot be activated in Launcher.");
} else
osys->displayMessageOnOSD("In-game resolution too small to magnify.");
}
}
if (keysPressed & KEY_R) {
if (inputMode == MODE_DRAG) {
inputMode = MODE_HOVER;
inputMode = savedInputMode = MODE_HOVER;
osys->displayMessageOnOSD("Hover Mode");
} else {
inputMode = MODE_DRAG;
osys->displayMessageOnOSD("Drag Mode");
if (osys->getMagnifyMode() == MODE_MAGOFF) {
inputMode = savedInputMode = MODE_DRAG;
osys->displayMessageOnOSD("Drag Mode");
} else
osys->displayMessageOnOSD("Cannot Switch to Drag Mode while Magnify Mode is On");
}
}
if (keysPressed & KEY_A || keysPressed & KEY_DLEFT || keysReleased & KEY_A || keysReleased & KEY_DLEFT) {
@@ -165,6 +194,16 @@ static void eventThreadFunc(void *arg) {
event.type = Common::EVENT_LBUTTONUP;
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);
}
if (keysPressed & KEY_X || keysPressed & KEY_DUP || keysReleased & KEY_X || keysReleased & KEY_DUP) {
// SIMULATE RIGHT CLICK
event.mouse.x = lastTouch.px;
@@ -175,7 +214,7 @@ static void eventThreadFunc(void *arg) {
event.type = Common::EVENT_RBUTTONUP;
pushEventQueue(eventQueue, event);
}
if (keysPressed & KEY_L) {
if (keysPressed & KEY_Y || keysPressed & KEY_DRIGHT) {
event.type = Common::EVENT_VIRTUAL_KEYBOARD;
pushEventQueue(eventQueue, event);
}
@@ -187,15 +226,18 @@ static void eventThreadFunc(void *arg) {
if (!optionMenuOpened)
optionMenuOpening = true;
}
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);

// If magnify mode is on when returning to Launcher, turn it off
if (g_system->getEventManager()->shouldRTL()) {
if (osys->getMagnifyMode() == MODE_MAGON) {
osys->setMagnifyMode(MODE_MAGOFF);
osys->updateSize();
if (savedInputMode == MODE_DRAG) {
inputMode = savedInputMode;
osys->displayMessageOnOSD("Magnify Mode Off. Reactivating Drag Mode.\nReturning to Launcher...");
} else
osys->displayMessageOnOSD("Magnify Mode Off. Returning to Launcher...");
}
}

// TODO: EVENT_PREDICTIVE_DIALOG
@@ -268,6 +310,10 @@ void OSystem_3DS::transformPoint(touchPosition &point) {
}
}

void OSystem_3DS::setMagnifyMode(MagnifyMode mode) {
_magnifyMode = mode;
}

void OSystem_3DS::displayMessageOnOSD(const char *msg) {
messageOSD = msg;
showMessageOSD = true;
@@ -151,6 +151,8 @@ void OSystem_3DS::initSize(uint width, uint height,
_gameHeight = height;
_gameTopTexture.create(width, height, _pfGameTexture);
_overlay.create(getOverlayWidth(), getOverlayHeight(), _pfGameTexture);
_topHalfWidth = _topWidth / 2;
_topHalfHeight = _topHeight / 2;

if (format) {
debug("pixelformat: %d %d %d %d %d", format->bytesPerPixel, format->rBits(), format->gBits(), format->bBits(), format->aBits());
@@ -198,6 +200,8 @@ void OSystem_3DS::updateSize() {
}
_gameTopTexture.setPosition(_gameTopX, _gameTopY);
_gameBottomTexture.setPosition(_gameBottomX, _gameBottomY);
_gameTopTexture.setOffset(0, 0);
_gameBottomTexture.setOffset(0, 0);
if (_overlayVisible)
_cursorTexture.setScale(1.f, 1.f);
else if (config.screen == kScreenTop)
@@ -275,6 +279,17 @@ void OSystem_3DS::updateScreen() {

C3D_FrameBegin(0);
_gameTopTexture.transfer();
if (_magnifyMode == MODE_MAGON) {
_topX = (_cursorX < _topHalfWidth) ?
0 : ((_cursorX < (_gameWidth - _topHalfWidth)) ?
_cursorX - _topHalfWidth : _gameWidth - _topWidth);
_topY = (_cursorY < _topHalfHeight) ?
0 : ((_cursorY < _gameHeight - _topHalfHeight) ?
_cursorY - _topHalfHeight : _gameHeight - _topHeight);
_gameTopTexture.setScale(1.f,1.f);
_gameTopTexture.setPosition(0,0);
_gameTopTexture.setOffset(_topX, _topY);
}
if (_overlayVisible) {
_overlay.transfer();
}
@@ -72,7 +72,12 @@ OSystem_3DS::OSystem_3DS():
_gameBottomY(0),
_gameWidth(320),
_gameHeight(240),
_topX(0),
_topY(0),
_topWidth(400),
_topHeight(240),
_overlayVisible(false),
_magnifyMode(MODE_MAGOFF),
exiting(false),
sleeping(false)
{
@@ -44,6 +44,11 @@ enum {
GFX_NEAREST = 1
};

enum MagnifyMode {
MODE_MAGON,
MODE_MAGOFF,
};

enum InputMode {
MODE_HOVER,
MODE_DRAG,
@@ -143,6 +148,9 @@ class OSystem_3DS : public EventsBaseBackend, public PaletteManager {
void updateFocus();
void updateConfig();
void updateSize();
void setMagnifyMode(MagnifyMode mode);
MagnifyMode getMagnifyMode(){ return _magnifyMode; }


private:
void initGraphics();
@@ -162,6 +170,9 @@ class OSystem_3DS : public EventsBaseBackend, public PaletteManager {
u16 _gameWidth, _gameHeight;
u16 _gameTopX, _gameTopY;
u16 _gameBottomX, _gameBottomY;
u16 _topWidth, _topHeight;
u16 _topHalfWidth, _topHalfHeight;
u16 _topX, _topY;

// Audio
Thread audioThread;
@@ -218,6 +229,7 @@ class OSystem_3DS : public EventsBaseBackend, public PaletteManager {
float _cursorDeltaX, _cursorDeltaY;
int _cursorHotspotX, _cursorHotspotY;
uint32 _cursorKeyColor;
MagnifyMode _magnifyMode;
};

} // namespace _3DS
@@ -42,6 +42,8 @@ Sprite::Sprite()
, actualHeight(0)
, posX(0)
, posY(0)
, offsetX(0)
, offsetY(0)
, scaleX(1.f)
, scaleY(1.f)
{
@@ -85,7 +87,6 @@ void Sprite::create(uint16 width, uint16 height, const Graphics::PixelFormat &f)
memcpy(vertices, tmp, sizeof(vertex) * 4);
}


void Sprite::free() {
linearFree(vertices);
linearFree(pixels);
@@ -138,12 +139,18 @@ void Sprite::setPosition(int x, int y) {
}
}

void Sprite::setOffset(uint16 x, uint16 y) {
offsetX = x;
offsetY = 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, true);
Mtx_Translate(&modelview, posX - offsetX, posY - offsetY, 0, true);
}
return &modelview;
}
@@ -52,9 +52,12 @@ class Sprite : public Graphics::Surface {
void markDirty(){ dirtyPixels = true; }

void setPosition(int x, int y);
void setOffset(uint16 x, uint16 y);
void setScale(float x, float y);
float getScaleX(){ return scaleX; }
float getScaleY(){ return scaleY; }
int getPosX(){ return posX; }
int getPosY(){ return posY; }
C3D_Mtx* getMatrix();

uint16 actualWidth;
@@ -68,6 +71,8 @@ class Sprite : public Graphics::Surface {
vertex* vertices;
int posX;
int posY;
uint16 offsetX;
uint16 offsetY;
float scaleX;
float scaleY;
};

0 comments on commit 78de572

Please sign in to comment.
You can’t perform that action at this time.