mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-10 21:03:31 +00:00
3DS: Implement dynamic graphics modes to improve performance
When launching a game, switch the graphics mode if necessary (and by extension the pixel formats used for Graphics::Surfaces and Sprites) to the one that most closely matches the pixel format used in-game. Additional Fixes: - Fix to prevent cursor position from changing when exiting a menu. - Fix to prevent updating of Magnification viewport position when virtual keyboard is open. - Cosmetic code fixes for improper whitespace and missing curly brackets. - Remove RGB8 as a mode option because: 1) It was already commented out in the master 3DS backend. 2) There are currently no games that explicitly require it. Notes: - As these graphics modes are automatically implemented on a per-game basis, they are meant for backend use only and are purposefully not accessible through the Options menu. - RGBA8 (aka RGBA8888) remains the default pixel format, being used for the launcher menu, CLUT8, and for games which do not specify a particular format.
This commit is contained in:
parent
99b9db456a
commit
b08ab0e130
@ -22,9 +22,9 @@
|
||||
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
|
||||
|
||||
#include "config.h"
|
||||
#include "osystem.h"
|
||||
#include "options-dialog.h"
|
||||
#include "backends/platform/3ds/config.h"
|
||||
#include "backends/platform/3ds/osystem.h"
|
||||
#include "backends/platform/3ds/options-dialog.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
namespace _3DS {
|
||||
@ -33,8 +33,9 @@ Config config;
|
||||
static Common::String prefix = "3ds_";
|
||||
|
||||
static bool confGetBool(Common::String key, bool defaultVal) {
|
||||
if (ConfMan.hasKey(prefix + key))
|
||||
if (ConfMan.hasKey(prefix + key)) {
|
||||
return ConfMan.getBool(prefix + key);
|
||||
}
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
@ -43,8 +44,9 @@ static void confSetBool(Common::String key, bool val) {
|
||||
}
|
||||
|
||||
static int confGetInt(Common::String key, int defaultVal) {
|
||||
if (ConfMan.hasKey(prefix + key))
|
||||
if (ConfMan.hasKey(prefix + key)) {
|
||||
return ConfMan.getInt(prefix + key);
|
||||
}
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
@ -67,8 +69,9 @@ void loadConfig() {
|
||||
} else if (config.screen == kScreenBottom) {
|
||||
GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTTOM);
|
||||
GSPLCD_PowerOffBacklight(GSPLCD_SCREEN_TOP);
|
||||
} else
|
||||
} else {
|
||||
GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTH);
|
||||
}
|
||||
gspLcdExit();
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "osystem.h"
|
||||
#include "backends/platform/3ds/osystem.h"
|
||||
#include "backends/plugins/3ds/3ds-provider.h"
|
||||
|
||||
#include <3ds.h>
|
||||
|
@ -20,7 +20,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "osystem.h"
|
||||
#include "backends/platform/3ds/osystem.h"
|
||||
#include "audio/mixer.h"
|
||||
|
||||
namespace _3DS {
|
||||
@ -55,7 +55,9 @@ static void audioThreadFunc(void *arg) {
|
||||
while (!osys->exiting) {
|
||||
svcSleepThread(5000 * 1000); // Wake up the thread every 5 ms
|
||||
|
||||
if (osys->sleeping) continue;
|
||||
if (osys->sleeping) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ndspWaveBuf *buf = &buffers[bufferIndex];
|
||||
if (buf->status == NDSP_WBUF_FREE || buf->status == NDSP_WBUF_DONE) {
|
||||
|
@ -108,10 +108,12 @@ static void eventThreadFunc(void *arg) {
|
||||
|
||||
// C-Pad used to control the cursor
|
||||
hidCircleRead(&circle);
|
||||
if (circle.dx < circleDeadzone && circle.dx > -circleDeadzone)
|
||||
if (circle.dx < circleDeadzone && circle.dx > -circleDeadzone) {
|
||||
circle.dx = 0;
|
||||
if (circle.dy < circleDeadzone && circle.dy > -circleDeadzone)
|
||||
}
|
||||
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);
|
||||
|
||||
@ -119,14 +121,18 @@ static void eventThreadFunc(void *arg) {
|
||||
if (held & KEY_TOUCH) {
|
||||
hidTouchRead(&touch);
|
||||
if (config.snapToBorder) {
|
||||
if (touch.px < borderSnapZone)
|
||||
if (touch.px < borderSnapZone) {
|
||||
touch.px = 0;
|
||||
if (touch.px > 319 - borderSnapZone)
|
||||
}
|
||||
if (touch.px > 319 - borderSnapZone) {
|
||||
touch.px = 319;
|
||||
if (touch.py < borderSnapZone)
|
||||
}
|
||||
if (touch.py < borderSnapZone) {
|
||||
touch.py = 0;
|
||||
if (touch.py > 239 - borderSnapZone)
|
||||
}
|
||||
if (touch.py > 239 - borderSnapZone) {
|
||||
touch.py = 239;
|
||||
}
|
||||
}
|
||||
|
||||
osys->transformPoint(touch);
|
||||
@ -201,8 +207,9 @@ static void aptHookFunc(APT_HookType hookType, void *param) {
|
||||
switch (hookType) {
|
||||
case APTHOOK_ONSUSPEND:
|
||||
case APTHOOK_ONSLEEP:
|
||||
if (g_engine)
|
||||
if (g_engine) {
|
||||
g_engine->pauseEngine(true);
|
||||
}
|
||||
osys->sleeping = true;
|
||||
if (R_SUCCEEDED(gspLcdInit())) {
|
||||
GSPLCD_PowerOnBacklight(GSPLCD_SCREEN_BOTH);
|
||||
@ -211,8 +218,9 @@ static void aptHookFunc(APT_HookType hookType, void *param) {
|
||||
break;
|
||||
case APTHOOK_ONRESTORE:
|
||||
case APTHOOK_ONWAKEUP:
|
||||
if (g_engine)
|
||||
if (g_engine) {
|
||||
g_engine->pauseEngine(false);
|
||||
}
|
||||
osys->sleeping = false;
|
||||
loadConfig();
|
||||
break;
|
||||
@ -348,8 +356,9 @@ bool OSystem_3DS::pollEvent(Common::Event &event) {
|
||||
|
||||
Common::StackLock lock(*eventMutex);
|
||||
|
||||
if (_eventQueue.empty())
|
||||
if (_eventQueue.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
event = _eventQueue.pop();
|
||||
return true;
|
||||
@ -381,7 +390,7 @@ bool OSystem_3DS::notifyEvent(const Common::Event &event) {
|
||||
return true;
|
||||
|
||||
case k3DSEventToggleMagnifyMode:
|
||||
if (g_gui.isActive()) {
|
||||
if (_overlayVisible) {
|
||||
displayMessageOnOSD(_("Magnify Mode cannot be activated in menus."));
|
||||
} else if (config.screen != kScreenBoth && _magnifyMode == MODE_MAGOFF) {
|
||||
// TODO: Automatically enable both screens while magnify mode is on
|
||||
@ -429,11 +438,13 @@ void OSystem_3DS::runOptionsDialog() {
|
||||
optionsDialogRunning = true;
|
||||
|
||||
OptionsDialog dialog;
|
||||
if (g_engine)
|
||||
if (g_engine) {
|
||||
g_engine->pauseEngine(true);
|
||||
}
|
||||
int result = dialog.runModal();
|
||||
if (g_engine)
|
||||
if (g_engine) {
|
||||
g_engine->pauseEngine(false);
|
||||
}
|
||||
|
||||
if (result > 0) {
|
||||
int oldScreen = config.screen;
|
||||
|
@ -23,24 +23,44 @@
|
||||
|
||||
#include "backends/platform/3ds/osystem.h"
|
||||
#include "backends/platform/3ds/shader_shbin.h"
|
||||
#include "backends/platform/3ds/options-dialog.h"
|
||||
#include "backends/platform/3ds/config.h"
|
||||
#include "common/rect.h"
|
||||
#include "graphics/fontman.h"
|
||||
#include "gui/gui-manager.h"
|
||||
#include "options-dialog.h"
|
||||
#include "config.h"
|
||||
|
||||
// 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))
|
||||
#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))
|
||||
#define TEXTURE_TRANSFER_FLAGS(fmt) \
|
||||
(GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | \
|
||||
GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(fmt) | \
|
||||
GX_TRANSFER_OUT_FORMAT(fmt) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
|
||||
#define DEFAULT_MODE _modeRGBA8
|
||||
|
||||
namespace _3DS {
|
||||
/* Group the various enums, values, etc. needed for
|
||||
* each graphics mode into instaces of GfxMode3DS */
|
||||
static const GfxMode3DS _modeRGBA8 = { Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0),
|
||||
GPU_RGBA8, TEXTURE_TRANSFER_FLAGS(GX_TRANSFER_FMT_RGBA8) };
|
||||
static const GfxMode3DS _modeRGB565 = { Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0),
|
||||
GPU_RGB565, TEXTURE_TRANSFER_FLAGS(GX_TRANSFER_FMT_RGB565) };
|
||||
static const GfxMode3DS _modeRGB555 = { Graphics::PixelFormat(2, 5, 5, 5, 0, 11, 6, 1, 0),
|
||||
GPU_RGBA5551, TEXTURE_TRANSFER_FLAGS(GX_TRANSFER_FMT_RGB5A1) };
|
||||
static const GfxMode3DS _modeRGB5A1 = { Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0),
|
||||
GPU_RGBA5551, TEXTURE_TRANSFER_FLAGS(GX_TRANSFER_FMT_RGB5A1) };
|
||||
static const GfxMode3DS _modeCLUT8 = _modeRGBA8;
|
||||
|
||||
void OSystem_3DS::initGraphics() {
|
||||
static const GfxMode3DS *gfxModes[] = { &_modeRGBA8, &_modeRGB565, &_modeRGB555, &_modeRGB5A1, &_modeCLUT8 };
|
||||
|
||||
|
||||
void OSystem_3DS::init3DSGraphics() {
|
||||
_gfxState.gfxMode = gfxModes[CLUT8];
|
||||
_pfGame = Graphics::PixelFormat::createFormatCLUT8();
|
||||
_pfGameTexture = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
|
||||
_pfDefaultTexture = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
|
||||
|
||||
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||
|
||||
@ -83,10 +103,12 @@ void OSystem_3DS::initGraphics() {
|
||||
C3D_CullFace(GPU_CULL_NONE);
|
||||
}
|
||||
|
||||
void OSystem_3DS::destroyGraphics() {
|
||||
void OSystem_3DS::destroy3DSGraphics() {
|
||||
_gameScreen.free();
|
||||
_gameTopTexture.free();
|
||||
_gameBottomTexture.free();
|
||||
_cursor.free();
|
||||
_cursorTexture.free();
|
||||
_overlay.free();
|
||||
_activityIcon.free();
|
||||
|
||||
@ -124,8 +146,37 @@ bool OSystem_3DS::getFeatureState(OSystem::Feature f) {
|
||||
}
|
||||
}
|
||||
|
||||
GraphicsModeID OSystem_3DS::chooseMode(Graphics::PixelFormat *format) {
|
||||
if (format->bytesPerPixel > 2) {
|
||||
return RGBA8;
|
||||
} else if (format->bytesPerPixel > 1) {
|
||||
if (format->gBits() > 5) {
|
||||
return RGB565;
|
||||
} else if (format->aBits() == 0) {
|
||||
return RGB555;
|
||||
} else {
|
||||
return RGB5A1;
|
||||
}
|
||||
}
|
||||
return CLUT8;
|
||||
}
|
||||
|
||||
bool OSystem_3DS::setGraphicsMode(GraphicsModeID modeID) {
|
||||
switch (modeID) {
|
||||
case RGBA8:
|
||||
case RGB565:
|
||||
case RGB555:
|
||||
case RGB5A1:
|
||||
case CLUT8:
|
||||
_gfxState.gfxMode = gfxModes[modeID];
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_3DS::initSize(uint width, uint height,
|
||||
const Graphics::PixelFormat *format) {
|
||||
const Graphics::PixelFormat *format) {
|
||||
debug("3ds initsize w:%d h:%d", width, height);
|
||||
int oldScreen = config.screen;
|
||||
loadConfig();
|
||||
@ -135,16 +186,28 @@ void OSystem_3DS::initSize(uint width, uint height,
|
||||
|
||||
_gameWidth = width;
|
||||
_gameHeight = height;
|
||||
_gameTopTexture.create(width, height, _pfGameTexture);
|
||||
_overlay.create(400, 320, _pfGameTexture);
|
||||
_magCenterX = _magWidth / 2;
|
||||
_magCenterY = _magHeight / 2;
|
||||
|
||||
if (format) {
|
||||
_oldPfGame = _pfGame;
|
||||
if (!format) {
|
||||
_pfGame = Graphics::PixelFormat::createFormatCLUT8();
|
||||
} else {
|
||||
debug("pixelformat: %d %d %d %d %d", format->bytesPerPixel, format->rBits(), format->gBits(), format->bBits(), format->aBits());
|
||||
_pfGame = *format;
|
||||
}
|
||||
|
||||
/* If the current graphics mode does not fit with the pixel
|
||||
* format being requested, choose one that does and switch to it */
|
||||
assert(_pfGame.bytesPerPixel > 0);
|
||||
if (_pfGame != _oldPfGame) {
|
||||
assert(_transactionState == kTransactionActive);
|
||||
_gfxState.gfxModeID = chooseMode(&_pfGame);
|
||||
_transactionDetails.formatChanged = true;
|
||||
}
|
||||
|
||||
_gameTopTexture.create(width, height, _gfxState.gfxMode);
|
||||
_overlay.create(400, 320, &DEFAULT_MODE);
|
||||
_gameScreen.create(width, height, _pfGame);
|
||||
|
||||
_focusDirty = true;
|
||||
@ -188,30 +251,69 @@ void OSystem_3DS::updateSize() {
|
||||
_gameBottomTexture.setPosition(_gameBottomX, _gameBottomY);
|
||||
_gameTopTexture.setOffset(0, 0);
|
||||
_gameBottomTexture.setOffset(0, 0);
|
||||
if (_overlayVisible)
|
||||
if (_overlayVisible) {
|
||||
_cursorTexture.setScale(1.f, 1.f);
|
||||
else if (config.screen == kScreenTop)
|
||||
} else if (config.screen == kScreenTop) {
|
||||
_cursorTexture.setScale(_gameTopTexture.getScaleX(), _gameTopTexture.getScaleY());
|
||||
else
|
||||
} else {
|
||||
_cursorTexture.setScale(_gameBottomTexture.getScaleX(), _gameBottomTexture.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, 0, 11, 6, 1, 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() {
|
||||
//
|
||||
assert(_transactionState == kTransactionNone);
|
||||
_transactionState = kTransactionActive;
|
||||
_transactionDetails.formatChanged = false;
|
||||
_oldGfxState = _gfxState;
|
||||
}
|
||||
|
||||
OSystem::TransactionError OSystem_3DS::endGFXTransaction() {
|
||||
return OSystem::kTransactionSuccess;
|
||||
int errors = OSystem::kTransactionSuccess;
|
||||
|
||||
assert(_transactionState != kTransactionNone);
|
||||
if (_transactionState == kTransactionRollback) {
|
||||
if (_gfxState.gfxModeID != _oldGfxState.gfxModeID) {
|
||||
errors |= OSystem::kTransactionModeSwitchFailed;
|
||||
_gfxState = _oldGfxState;
|
||||
} else if ((_gfxState.gfxMode != _oldGfxState.gfxMode) |
|
||||
(_gfxState.gfxMode != gfxModes[_gfxState.gfxModeID])) {
|
||||
errors |= OSystem::kTransactionFormatNotSupported;
|
||||
_gfxState = _oldGfxState;
|
||||
}
|
||||
|
||||
_oldGfxState.setup = false;
|
||||
}
|
||||
if (_transactionDetails.formatChanged) {
|
||||
if (!setGraphicsMode(_gfxState.gfxModeID)) {
|
||||
if (_oldGfxState.setup) {
|
||||
_transactionState = kTransactionRollback;
|
||||
errors |= endGFXTransaction();
|
||||
}
|
||||
} else if (_gfxState.gfxMode != gfxModes[_gfxState.gfxModeID]) {
|
||||
if (_oldGfxState.setup) {
|
||||
_transactionState = kTransactionRollback;
|
||||
errors |= endGFXTransaction();
|
||||
}
|
||||
} else {
|
||||
initSize(_gameWidth, _gameHeight, &_pfGame);
|
||||
clearOverlay();
|
||||
_gfxState.setup = true;
|
||||
_screenChangeId++;
|
||||
}
|
||||
}
|
||||
|
||||
_transactionState = kTransactionNone;
|
||||
return (OSystem::TransactionError)errors;
|
||||
}
|
||||
|
||||
float OSystem_3DS::getScaleRatio() const {
|
||||
@ -239,25 +341,34 @@ void OSystem_3DS::grabPalette(byte *colors, uint start, uint num) const {
|
||||
}
|
||||
|
||||
void OSystem_3DS::copyRectToScreen(const void *buf, int pitch, int x,
|
||||
int y, int w, int h) {
|
||||
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);
|
||||
_gameTopTexture.copyRectToSurface(*convertedSubSurface, x, y, Common::Rect(w, h));
|
||||
if (_pfGame == _gameTopTexture.format) {
|
||||
_gameTopTexture.copyRectToSurface(subSurface, x, y, Common::Rect(w, h));
|
||||
} else {
|
||||
Graphics::Surface *convertedSubSurface = subSurface.convertTo(_gameTopTexture.format, _palette);
|
||||
_gameTopTexture.copyRectToSurface(*convertedSubSurface, x, y, Common::Rect(w, h));
|
||||
convertedSubSurface->free();
|
||||
delete convertedSubSurface;
|
||||
}
|
||||
|
||||
convertedSubSurface->free();
|
||||
delete convertedSubSurface;
|
||||
_gameTopTexture.markDirty();
|
||||
}
|
||||
|
||||
void OSystem_3DS::flushGameScreen() {
|
||||
Graphics::Surface *converted = _gameScreen.convertTo(_pfGameTexture, _palette);
|
||||
_gameTopTexture.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
|
||||
if (_pfGame == _gameTopTexture.format) {
|
||||
_gameTopTexture.copyRectToSurface(_gameScreen, 0, 0, Common::Rect(_gameScreen.w, _gameScreen.h));
|
||||
} else {
|
||||
Graphics::Surface *converted = _gameScreen.convertTo(_gameTopTexture.format, _palette);
|
||||
_gameTopTexture.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
|
||||
converted->free();
|
||||
delete converted;
|
||||
}
|
||||
|
||||
_gameTopTexture.markDirty();
|
||||
converted->free();
|
||||
delete converted;
|
||||
}
|
||||
|
||||
Graphics::Surface *OSystem_3DS::lockScreen() {
|
||||
@ -268,8 +379,9 @@ void OSystem_3DS::unlockScreen() {
|
||||
}
|
||||
|
||||
void OSystem_3DS::updateScreen() {
|
||||
if (sleeping || exiting)
|
||||
if (sleeping || exiting) {
|
||||
return;
|
||||
}
|
||||
|
||||
// updateFocus();
|
||||
updateMagnify();
|
||||
@ -396,10 +508,12 @@ void OSystem_3DS::updateFocus() {
|
||||
_focusTargetPosY = _focusTargetScaleY * _focusRect.top;
|
||||
_focusTargetPosX = _focusTargetScaleX * ((float)_focusRect.left - (newWidth - _focusRect.width())/2.f);
|
||||
}
|
||||
if (_focusTargetPosX < 0 && _focusTargetScaleY != 240.f / _gameHeight)
|
||||
if (_focusTargetPosX < 0 && _focusTargetScaleY != 240.f / _gameHeight) {
|
||||
_focusTargetPosX = 0;
|
||||
if (_focusTargetPosY < 0 && _focusTargetScaleX != 400.f / _gameWidth)
|
||||
}
|
||||
if (_focusTargetPosY < 0 && _focusTargetScaleX != 400.f / _gameWidth) {
|
||||
_focusTargetPosY = 0;
|
||||
}
|
||||
_focusStepPosX = duration * (_focusTargetPosX - _focusPosX);
|
||||
_focusStepPosY = duration * (_focusTargetPosY - _focusPosY);
|
||||
_focusStepScaleX = duration * (_focusTargetScaleX - _focusScaleX);
|
||||
@ -407,28 +521,32 @@ void OSystem_3DS::updateFocus() {
|
||||
}
|
||||
|
||||
if (_focusDirty || _focusPosX != _focusTargetPosX || _focusPosY != _focusTargetPosY ||
|
||||
_focusScaleX != _focusTargetScaleX || _focusScaleY != _focusTargetScaleY) {
|
||||
_focusScaleX != _focusTargetScaleX || _focusScaleY != _focusTargetScaleY) {
|
||||
_focusDirty = false;
|
||||
|
||||
if ((_focusStepPosX > 0 && _focusPosX > _focusTargetPosX) || (_focusStepPosX < 0 && _focusPosX < _focusTargetPosX))
|
||||
if ((_focusStepPosX > 0 && _focusPosX > _focusTargetPosX) || (_focusStepPosX < 0 && _focusPosX < _focusTargetPosX)) {
|
||||
_focusPosX = _focusTargetPosX;
|
||||
else if (_focusPosX != _focusTargetPosX)
|
||||
} else if (_focusPosX != _focusTargetPosX) {
|
||||
_focusPosX += _focusStepPosX;
|
||||
}
|
||||
|
||||
if ((_focusStepPosY > 0 && _focusPosY > _focusTargetPosY) || (_focusStepPosY < 0 && _focusPosY < _focusTargetPosY))
|
||||
if ((_focusStepPosY > 0 && _focusPosY > _focusTargetPosY) || (_focusStepPosY < 0 && _focusPosY < _focusTargetPosY)) {
|
||||
_focusPosY = _focusTargetPosY;
|
||||
else if (_focusPosY != _focusTargetPosY)
|
||||
} else if (_focusPosY != _focusTargetPosY) {
|
||||
_focusPosY += _focusStepPosY;
|
||||
}
|
||||
|
||||
if ((_focusStepScaleX > 0 && _focusScaleX > _focusTargetScaleX) || (_focusStepScaleX < 0 && _focusScaleX < _focusTargetScaleX))
|
||||
if ((_focusStepScaleX > 0 && _focusScaleX > _focusTargetScaleX) || (_focusStepScaleX < 0 && _focusScaleX < _focusTargetScaleX)) {
|
||||
_focusScaleX = _focusTargetScaleX;
|
||||
else if (_focusScaleX != _focusTargetScaleX)
|
||||
} else if (_focusScaleX != _focusTargetScaleX) {
|
||||
_focusScaleX += _focusStepScaleX;
|
||||
}
|
||||
|
||||
if ((_focusStepScaleY > 0 && _focusScaleY > _focusTargetScaleY) || (_focusStepScaleY < 0 && _focusScaleY < _focusTargetScaleY))
|
||||
if ((_focusStepScaleY > 0 && _focusScaleY > _focusTargetScaleY) || (_focusStepScaleY < 0 && _focusScaleY < _focusTargetScaleY)) {
|
||||
_focusScaleY = _focusTargetScaleY;
|
||||
else if (_focusScaleY != _focusTargetScaleY)
|
||||
} else if (_focusScaleY != _focusTargetScaleY) {
|
||||
_focusScaleY += _focusStepScaleY;
|
||||
}
|
||||
|
||||
Mtx_Identity(&_focusMatrix);
|
||||
Mtx_Translate(&_focusMatrix, -_focusPosX, -_focusPosY, 0, true);
|
||||
@ -442,17 +560,14 @@ void OSystem_3DS::updateMagnify() {
|
||||
_magnifyMode = MODE_MAGOFF;
|
||||
}
|
||||
|
||||
// TODO: When exiting GUI, prevent cursor's position within GUI from changing
|
||||
// position of magnification viewport. Possible solution: save in-game cursor
|
||||
// coordinates separately from GUI cursor coordinates?
|
||||
if (_magnifyMode == MODE_MAGON) {
|
||||
if (!g_gui.isActive()) {
|
||||
_magX = (_cursorX < _magCenterX) ?
|
||||
0 : ((_cursorX < (_gameWidth - _magCenterX)) ?
|
||||
_cursorX - _magCenterX : _gameWidth - _magWidth);
|
||||
_magY = (_cursorY < _magCenterY) ?
|
||||
0 : ((_cursorY < _gameHeight - _magCenterY) ?
|
||||
_cursorY - _magCenterY : _gameHeight - _magHeight);
|
||||
if (!_overlayVisible) {
|
||||
_magX = (_cursorScreenX < _magCenterX) ?
|
||||
0 : ((_cursorScreenX < (_gameWidth - _magCenterX)) ?
|
||||
_cursorScreenX - _magCenterX : _gameWidth - _magWidth);
|
||||
_magY = (_cursorScreenY < _magCenterY) ?
|
||||
0 : ((_cursorScreenY < _gameHeight - _magCenterY) ?
|
||||
_cursorScreenY - _magCenterY : _gameHeight - _magHeight);
|
||||
}
|
||||
_gameTopTexture.setScale(1.f,1.f);
|
||||
_gameTopTexture.setPosition(0,0);
|
||||
@ -471,7 +586,7 @@ void OSystem_3DS::hideOverlay() {
|
||||
}
|
||||
|
||||
Graphics::PixelFormat OSystem_3DS::getOverlayFormat() const {
|
||||
return _pfGameTexture;
|
||||
return _overlay.format;
|
||||
}
|
||||
|
||||
void OSystem_3DS::clearOverlay() {
|
||||
@ -482,13 +597,13 @@ void OSystem_3DS::grabOverlay(void *buf, int pitch) {
|
||||
byte *dst = (byte *)buf;
|
||||
|
||||
for (int y = 0; y < getOverlayHeight(); ++y) {
|
||||
memcpy(dst, _overlay.getBasePtr(0, y), getOverlayWidth() * _pfGameTexture.bytesPerPixel);
|
||||
memcpy(dst, _overlay.getBasePtr(0, y), getOverlayWidth() * _overlay.format.bytesPerPixel);
|
||||
dst += pitch;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_3DS::copyRectToOverlay(const void *buf, int pitch, int x,
|
||||
int y, int w, int h) {
|
||||
int y, int w, int h) {
|
||||
_overlay.copyRectToSurface(buf, pitch, x, y, w, h);
|
||||
_overlay.markDirty();
|
||||
}
|
||||
@ -525,19 +640,21 @@ void OSystem_3DS::displayMessageOnOSD(const char *msg) {
|
||||
}
|
||||
|
||||
// Clip the rect
|
||||
if (width > getOverlayWidth())
|
||||
if (width > getOverlayWidth()) {
|
||||
width = getOverlayWidth();
|
||||
if (height > getOverlayHeight())
|
||||
}
|
||||
if (height > getOverlayHeight()) {
|
||||
height = getOverlayHeight();
|
||||
}
|
||||
|
||||
_osdMessage.create(width, height, _pfGameTexture);
|
||||
_osdMessage.fillRect(Common::Rect(width, height), _pfGameTexture.ARGBToColor(200, 0, 0, 0));
|
||||
_osdMessage.create(width, height, &DEFAULT_MODE);
|
||||
_osdMessage.fillRect(Common::Rect(width, height), _pfDefaultTexture.ARGBToColor(200, 0, 0, 0));
|
||||
|
||||
// Render the message, centered, and in white
|
||||
for (i = 0; i < lines.size(); i++) {
|
||||
font->drawString(&_osdMessage, lines[i],
|
||||
0, 0 + i * lineHeight + vOffset + lineSpacing, width,
|
||||
_pfGameTexture.RGBToColor(255, 255, 255),
|
||||
_pfDefaultTexture.RGBToColor(255, 255, 255),
|
||||
Graphics::kTextAlignCenter);
|
||||
}
|
||||
|
||||
@ -549,14 +666,19 @@ void OSystem_3DS::displayActivityIconOnOSD(const Graphics::Surface *icon) {
|
||||
_activityIcon.free();
|
||||
} else {
|
||||
if (!_activityIcon.getPixels() || icon->w != _activityIcon.w || icon->h != _activityIcon.h) {
|
||||
_activityIcon.create(icon->w, icon->h, _pfGameTexture);
|
||||
_activityIcon.create(icon->w, icon->h, &DEFAULT_MODE);
|
||||
}
|
||||
|
||||
if (icon->format == _activityIcon.format) {
|
||||
_activityIcon.copyRectToSurface(*icon, 0, 0, Common::Rect(icon->w, icon->h));
|
||||
} else {
|
||||
Graphics::Surface *converted = icon->convertTo(_activityIcon.format);
|
||||
_activityIcon.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
|
||||
converted->free();
|
||||
delete converted;
|
||||
}
|
||||
|
||||
Graphics::Surface *converted = icon->convertTo(_pfGameTexture);
|
||||
_activityIcon.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
|
||||
_activityIcon.markDirty();
|
||||
converted->free();
|
||||
delete converted;
|
||||
}
|
||||
}
|
||||
|
||||
@ -575,8 +697,13 @@ bool OSystem_3DS::showMouse(bool visible) {
|
||||
}
|
||||
|
||||
void OSystem_3DS::warpMouse(int x, int y) {
|
||||
_cursorX = x;
|
||||
_cursorY = y;
|
||||
if (!_overlayVisible) {
|
||||
_cursorScreenX = x;
|
||||
_cursorScreenY = y;
|
||||
} else {
|
||||
_cursorOverlayX = x;
|
||||
_cursorOverlayY = y;
|
||||
}
|
||||
|
||||
// TODO: adjust for _cursorScalable ?
|
||||
x -= _cursorHotspotX;
|
||||
@ -598,9 +725,9 @@ void OSystem_3DS::setCursorDelta(float deltaX, float deltaY) {
|
||||
}
|
||||
|
||||
void OSystem_3DS::setMouseCursor(const void *buf, uint w, uint h,
|
||||
int hotspotX, int hotspotY,
|
||||
uint32 keycolor, bool dontScale,
|
||||
const Graphics::PixelFormat *format) {
|
||||
int hotspotX, int hotspotY,
|
||||
uint32 keycolor, bool dontScale,
|
||||
const Graphics::PixelFormat *format) {
|
||||
_cursorScalable = !dontScale;
|
||||
_cursorHotspotX = hotspotX;
|
||||
_cursorHotspotY = hotspotY;
|
||||
@ -609,7 +736,7 @@ void OSystem_3DS::setMouseCursor(const void *buf, uint w, uint h,
|
||||
|
||||
if (w != _cursor.w || h != _cursor.h || _cursor.format != _pfCursor) {
|
||||
_cursor.create(w, h, _pfCursor);
|
||||
_cursorTexture.create(w, h, _pfGameTexture);
|
||||
_cursorTexture.create(w, h, &DEFAULT_MODE);
|
||||
}
|
||||
|
||||
if ( w != 0 && h != 0 ) {
|
||||
@ -618,7 +745,11 @@ void OSystem_3DS::setMouseCursor(const void *buf, uint w, uint h,
|
||||
|
||||
flushCursor();
|
||||
|
||||
warpMouse(_cursorX, _cursorY);
|
||||
if (!_overlayVisible) {
|
||||
warpMouse(_cursorScreenX, _cursorScreenY);
|
||||
} else {
|
||||
warpMouse(_cursorOverlayX, _cursorOverlayY);
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_3DS::setCursorPalette(const byte *colors, uint start, uint num) {
|
||||
@ -653,7 +784,7 @@ void applyKeyColor(Graphics::Surface *src, Graphics::Surface *dst, const SrcColo
|
||||
|
||||
void OSystem_3DS::flushCursor() {
|
||||
if (_cursor.getPixels()) {
|
||||
Graphics::Surface *converted = _cursor.convertTo(_pfGameTexture, _cursorPaletteEnabled ? _cursorPalette : _palette);
|
||||
Graphics::Surface *converted = _cursor.convertTo(_cursorTexture.format, _cursorPaletteEnabled ? _cursorPalette : _palette);
|
||||
_cursorTexture.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
|
||||
_cursorTexture.markDirty();
|
||||
converted->free();
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <3ds.h>
|
||||
#include "osystem.h"
|
||||
|
||||
#include "backends/platform/3ds/config.h"
|
||||
#include "backends/saves/default/default-saves.h"
|
||||
#include "backends/timer/default/default-timer.h"
|
||||
#include "backends/events/default/default-events.h"
|
||||
@ -34,7 +35,6 @@
|
||||
#include "common/scummsys.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/str.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "backends/fs/posix-drives/posix-drives-fs-factory.h"
|
||||
#include "backends/fs/posix-drives/posix-drives-fs.h"
|
||||
@ -62,8 +62,10 @@ OSystem_3DS::OSystem_3DS():
|
||||
_cursorPaletteEnabled(false),
|
||||
_cursorVisible(false),
|
||||
_cursorScalable(false),
|
||||
_cursorX(0),
|
||||
_cursorY(0),
|
||||
_cursorScreenX(0),
|
||||
_cursorScreenY(0),
|
||||
_cursorOverlayX(0),
|
||||
_cursorOverlayY(0),
|
||||
_cursorHotspotX(0),
|
||||
_cursorHotspotY(0),
|
||||
_gameTopX(0),
|
||||
@ -110,7 +112,7 @@ OSystem_3DS::~OSystem_3DS() {
|
||||
exiting = true;
|
||||
destroyEvents();
|
||||
destroyAudio();
|
||||
destroyGraphics();
|
||||
destroy3DSGraphics();
|
||||
|
||||
delete _timerManager;
|
||||
_timerManager = 0;
|
||||
@ -125,15 +127,17 @@ void OSystem_3DS::initBackend() {
|
||||
ConfMan.set("joystick_num", 0);
|
||||
ConfMan.registerDefault("fullscreen", true);
|
||||
ConfMan.registerDefault("aspect_ratio", true);
|
||||
if (!ConfMan.hasKey("vkeybd_pack_name"))
|
||||
if (!ConfMan.hasKey("vkeybd_pack_name")) {
|
||||
ConfMan.set("vkeybd_pack_name", "vkeybd_small");
|
||||
if (!ConfMan.hasKey("gui_theme"))
|
||||
}
|
||||
if (!ConfMan.hasKey("gui_theme")) {
|
||||
ConfMan.set("gui_theme", "builtin");
|
||||
}
|
||||
|
||||
_timerManager = new DefaultTimerManager();
|
||||
_savefileManager = new DefaultSaveFileManager("sdmc:/3ds/scummvm/saves/");
|
||||
|
||||
initGraphics();
|
||||
init3DSGraphics();
|
||||
initAudio();
|
||||
EventsBaseBackend::initBackend();
|
||||
initEvents();
|
||||
@ -142,7 +146,8 @@ void OSystem_3DS::initBackend() {
|
||||
void OSystem_3DS::updateConfig() {
|
||||
if (_gameScreen.getPixels()) {
|
||||
updateSize();
|
||||
warpMouse(_cursorX, _cursorY);
|
||||
(!_overlayVisible) ? warpMouse(_cursorScreenX, _cursorScreenY) :
|
||||
warpMouse(_cursorOverlayX, _cursorOverlayY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,48 @@ enum InputMode {
|
||||
MODE_DRAG,
|
||||
};
|
||||
|
||||
enum GraphicsModeID {
|
||||
RGBA8,
|
||||
RGB565,
|
||||
RGB555,
|
||||
RGB5A1,
|
||||
CLUT8
|
||||
};
|
||||
|
||||
enum TransactionState {
|
||||
kTransactionNone = 0,
|
||||
kTransactionActive = 1,
|
||||
kTransactionRollback = 2
|
||||
};
|
||||
|
||||
|
||||
struct TransactionDetails {
|
||||
bool formatChanged, modeChanged;
|
||||
|
||||
TransactionDetails() {
|
||||
formatChanged = false;
|
||||
modeChanged = false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct GfxMode3DS {
|
||||
Graphics::PixelFormat surfaceFormat;
|
||||
GPU_TEXCOLOR textureFormat;
|
||||
uint32 textureTransferFlags;
|
||||
} GfxMode3DS;
|
||||
|
||||
struct GfxState {
|
||||
bool setup;
|
||||
GraphicsModeID gfxModeID;
|
||||
const GfxMode3DS *gfxMode;
|
||||
|
||||
GfxState() {
|
||||
setup = false;
|
||||
gfxModeID = CLUT8;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class OSystem_3DS : public EventsBaseBackend, public PaletteManager, public Common::EventObserver {
|
||||
public:
|
||||
OSystem_3DS();
|
||||
@ -95,6 +137,8 @@ public:
|
||||
void initSize(uint width, uint height,
|
||||
const Graphics::PixelFormat *format = NULL);
|
||||
virtual int getScreenChangeID() const { return _screenChangeId; };
|
||||
GraphicsModeID chooseMode(Graphics::PixelFormat *format);
|
||||
bool setGraphicsMode(GraphicsModeID modeID);
|
||||
|
||||
void beginGFXTransaction();
|
||||
OSystem::TransactionError endGFXTransaction();
|
||||
@ -143,8 +187,8 @@ public:
|
||||
void updateSize();
|
||||
|
||||
private:
|
||||
void initGraphics();
|
||||
void destroyGraphics();
|
||||
void init3DSGraphics();
|
||||
void destroy3DSGraphics();
|
||||
void initAudio();
|
||||
void destroyAudio();
|
||||
void initEvents();
|
||||
@ -166,8 +210,13 @@ private:
|
||||
Thread audioThread;
|
||||
|
||||
// Graphics
|
||||
Graphics::PixelFormat _pfGame;
|
||||
Graphics::PixelFormat _pfGameTexture;
|
||||
GraphicsModeID _graphicsModeID;
|
||||
TransactionState _transactionState;
|
||||
TransactionDetails _transactionDetails;
|
||||
|
||||
GfxState _gfxState, _oldGfxState;
|
||||
Graphics::PixelFormat _pfDefaultTexture;
|
||||
Graphics::PixelFormat _pfGame, _oldPfGame;
|
||||
Graphics::PixelFormat _pfCursor;
|
||||
byte _palette[3 * 256];
|
||||
byte _cursorPalette[3 * 256];
|
||||
@ -221,7 +270,8 @@ private:
|
||||
bool _cursorPaletteEnabled;
|
||||
bool _cursorVisible;
|
||||
bool _cursorScalable;
|
||||
float _cursorX, _cursorY;
|
||||
float _cursorScreenX, _cursorScreenY;
|
||||
float _cursorOverlayX, _cursorOverlayY;
|
||||
float _cursorDeltaX, _cursorDeltaY;
|
||||
int _cursorHotspotX, _cursorHotspotY;
|
||||
uint32 _cursorKeyColor;
|
||||
|
@ -20,12 +20,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "backends/platform/3ds/osystem.h"
|
||||
#include "backends/platform/3ds/sprite.h"
|
||||
#include "common/algorithm.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace _3DS {
|
||||
|
||||
Sprite::Sprite()
|
||||
: dirtyPixels(true)
|
||||
: textureTransferFlags(0)
|
||||
, dirtyPixels(true)
|
||||
, dirtyMatrix(true)
|
||||
, actualWidth(0)
|
||||
, actualHeight(0)
|
||||
@ -45,12 +49,13 @@ Sprite::~Sprite() {
|
||||
//
|
||||
}
|
||||
|
||||
void Sprite::create(uint16 width, uint16 height, const Graphics::PixelFormat &f) {
|
||||
void Sprite::create(uint16 width, uint16 height, const GfxMode3DS *mode) {
|
||||
free();
|
||||
|
||||
actualWidth = width;
|
||||
actualHeight = height;
|
||||
format = f;
|
||||
format = mode->surfaceFormat;
|
||||
textureTransferFlags = mode->textureTransferFlags;
|
||||
w = MAX<uint16>(Common::nextHigher2(width), 64u);
|
||||
h = MAX<uint16>(Common::nextHigher2(height), 64u);
|
||||
pitch = w * format.bytesPerPixel;
|
||||
@ -58,7 +63,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_TexInit(&texture, w, h, mode->textureFormat);
|
||||
C3D_TexSetFilter(&texture, GPU_LINEAR, GPU_LINEAR);
|
||||
assert(pixels && texture.data);
|
||||
clear();
|
||||
@ -94,7 +99,7 @@ void Sprite::transfer() {
|
||||
if (pixels && dirtyPixels) {
|
||||
dirtyPixels = false;
|
||||
GSPGPU_FlushDataCache(pixels, w * h * format.bytesPerPixel);
|
||||
C3D_SyncDisplayTransfer((u32*)pixels, GX_BUFFER_DIM(w, h), (u32*)texture.data, GX_BUFFER_DIM(w, h), TEXTURE_TRANSFER_FLAGS);
|
||||
C3D_SyncDisplayTransfer((u32*)pixels, GX_BUFFER_DIM(w, h), (u32*)texture.data, GX_BUFFER_DIM(w, h), textureTransferFlags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,3 +148,5 @@ C3D_Mtx* Sprite::getMatrix() {
|
||||
}
|
||||
return &modelview;
|
||||
}
|
||||
|
||||
} // namespace _3DS
|
||||
|
@ -29,21 +29,20 @@
|
||||
#include <3ds.h>
|
||||
#include <citro3d.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))
|
||||
namespace _3DS {
|
||||
|
||||
typedef struct {
|
||||
float position[3];
|
||||
float texcoord[2];
|
||||
} vertex;
|
||||
|
||||
struct GfxMode3DS;
|
||||
|
||||
class Sprite : public Graphics::Surface {
|
||||
public:
|
||||
Sprite();
|
||||
~Sprite();
|
||||
void create(uint16 width, uint16 height, const Graphics::PixelFormat &format);
|
||||
void create(uint16 width, uint16 height, const GfxMode3DS *mode);
|
||||
void free();
|
||||
void convertToInPlace(const Graphics::PixelFormat &dstFormat, const byte *palette = 0);
|
||||
void transfer();
|
||||
@ -64,6 +63,7 @@ public:
|
||||
uint16 actualHeight;
|
||||
|
||||
private:
|
||||
uint32 textureTransferFlags;
|
||||
bool dirtyPixels;
|
||||
bool dirtyMatrix;
|
||||
C3D_Mtx modelview;
|
||||
@ -77,4 +77,6 @@ private:
|
||||
float scaleY;
|
||||
};
|
||||
|
||||
} // namespace _3DS
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user